PageSourceSearch

https://vibeudlejning.dk/wp-content/cache/wpfc-minified/9ktje88h/23hdn.js

js vibeudlejning.dk collected 2026-10-04 02:00:22 UTC 2,207,197 bytes, 59,384 lines download raw bytes

1// source --> https://vibeudlejning.dk/wp-content/plugins/trustpilot-reviews/review/assets/js/headerScript.min.js?ver=1.0' async='async 
2function inIframe(){try{return window.self!==window.top}catch(t){return!1}}function tryParseJson(t){if("string"==typeof t)try{return JSON.parse(t)}catch(t){return!1}return!1}!function(t,e,r,s,i){t.TrustpilotObject=i,t.tp=t.tp||function(){(t.tp.q=t.tp.q||[]).push(arguments)},a=e.createElement(r),a.async=1,a.src=s,a.type="text/java"+r,f=e.getElementsByTagName(r)[0],f.parentNode.insertBefore(a,f)}(window,document,"script",trustpilot_settings.TrustpilotScriptUrl,"tp"),tp("register",trustpilot_settings.key),inIframe()&&window.addEventListener("message",function(t){var e=new URL(window.location).hostname;if(t.data&&-1!==t.origin.indexOf(e))if("undefined"!=typeof TrustpilotPreview){if("string"!=typeof t.data||"submit"!==t.data)return jsonData=tryParseJson(t.data),void(jsonData&&(jsonData.trustbox?TrustpilotPreview.setSettings(jsonData.trustbox):jsonData.customised&&TrustpilotPreview.updateActive(jsonData.customised)));TrustpilotPreview.sendTrustboxes()}else{var r=tryParseJson(t.data);if(r&&r.trustboxes){var s=document.createElement("script");s.type="text/javascript",s.src=trustpilot_settings.WidgetScriptUrl,document.head.appendChild(s);var i=document.createElement("script");i.type="text/javascript",i.onload=function(){const e=t.source.parent.document.getElementById("configuration_iframe").contentWindow;TrustpilotPreview.init([trustpilot_settings.PreviewCssUrl,trustpilot_settings.PreviewWPCssUrl],r,e,t.source)},i.src=trustpilot_settings.PreviewScriptUrl,document.head.appendChild(i)}}});
3//# sourceMappingURL=headerScript.min.js.map;
4// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/public/lib/pannellum/src/js/pannellum.js?ver=1 
5/*
6 * Pannellum - An HTML5 based Panorama Viewer
7 * Copyright (c) 2011-2019 Matthew Petroff
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28window.pannellum = (function(window, document, undefined) {
29
30    'use strict';
31
32    /**
33     * Creates a new panorama viewer.
34     * @constructor
35     * @param {HTMLElement|string} container - The container (div) element for the
36     *      viewer, or its ID.
37     * @param {Object} initialConfig - Inital configuration for viewer.
38     */
39    function Viewer(container, initialConfig) {
40
41        var _this = this;
42
43// Declare variables
44        var config,
45            renderer,
46            preview,
47            isUserInteracting = false,
48            latestInteraction = Date.now(),
49            onPointerDownPointerX = 0,
50            onPointerDownPointerY = 0,
51            onPointerDownPointerDist = -1,
52            onPointerDownYaw = 0,
53            onPointerDownPitch = 0,
54            keysDown = new Array(10),
55            fullscreenActive = false,
56            loaded,
57            error = false,
58            isTimedOut = false,
59            listenersAdded = false,
60            panoImage,
61            prevTime,
62            speed = {'yaw': 0, 'pitch': 0, 'hfov': 0},
63            animating = false,
64            orientation = false,
65            orientationYawOffset = 0,
66            autoRotateStart,
67            autoRotateSpeed = 0,
68            origHfov,
69            origPitch,
70            animatedMove = {},
71            externalEventListeners = {},
72            specifiedPhotoSphereExcludes = [],
73            update = false, // Should we update when still to render dynamic content
74            eps = 1e-6,
75            hotspotsCreated = false,
76            destroyed = false;
77
78        var defaultConfig = {
79            hfov: 100,
80            minHfov: 50,
81            multiResMinHfov: false,
82            maxHfov: 120,
83            pitch: 0,
84            minPitch: undefined,
85            maxPitch: undefined,
86            yaw: 0,
87            minYaw: -180,
88            maxYaw: 180,
89            roll: 0,
90            haov: 360,
91            vaov: 180,
92            vOffset: 0,
93            autoRotate: false,
94            autoRotateInactivityDelay: -1,
95            autoRotateStopDelay: undefined,
96            type: 'equirectangular',
97            northOffset: 0,
98            showFullscreenCtrl: true,
99            dynamic: false,
100            dynamicUpdate: false,
101            doubleClickZoom: true,
102            keyboardZoom: true,
103            mouseZoom: true,
104            showZoomCtrl: true,
105            autoLoad: false,
106            showControls: true,
107            orientationOnByDefault: false,
108            hotSpotDebug: false,
109            backgroundColor: [0, 0, 0],
110            avoidShowingBackground: false,
111            animationTimingFunction: timingFunction,
112            draggable: true,
113            disableKeyboardCtrl: false,
114            crossOrigin: 'anonymous',
115            touchPanSpeedCoeffFactor: 1,
116            capturedKeyNumbers: [16, 17, 27, 37, 38, 39, 40, 61, 107, 109, 173, 187, 189],
117            friction: 0.15
118        };
119
120// Translatable / configurable strings
121// Some strings contain '%s', which is a placeholder for inserted values
122// When setting strings in external configuration, `\n` should be used instead of `<br>` to insert line breaks
123        defaultConfig.strings = {
124            // Labels
125            loadButtonLabel: 'Click to<br>Load<br>Panorama',
126            loadingLabel: 'Loading...',
127            bylineLabel: ' %s',    // One substitution: author
128
129            // Errors
130            noPanoramaError: 'No panorama image was specified.',
vendor: 4,477 bytes, lines 131-218
131            fileAccessError: 'The file %s could not be accessed.',  // One substitution: file URL
132            malformedURLError: 'There is something wrong with the panorama URL.',
133            iOS8WebGLError: "Due to iOS 8's broken WebGL implementation, only " +
134                "progressive encoded JPEGs work for your device (this " +
135                "panorama uses standard encoding).",
136            genericWebGLError: 'Your browser does not have the necessary WebGL support to display this panorama.',
137            textureSizeError: 'This panorama is too big for your device! It\'s ' +
138                '%spx wide, but your device only supports images up to ' +
139                '%spx wide. Try another device.' +
140                ' (If you\'re the author, try scaling down the image.)',    // Two substitutions: image width, max image width
141            unknownError: 'Unknown error. Check developer console.',
142        };
143
144// Initialize container
145        container = typeof container === 'string' ? document.getElementById(container) : container;
146        container.classList.add('pnlm-container');
147        container.tabIndex = 0;
148
149// Create container for ui
150        var uiContainer = document.createElement('div');
151        uiContainer.className = 'pnlm-ui';
152        container.appendChild(uiContainer);
153
154// Create container for renderer
155        var renderContainer = document.createElement('div');
156        renderContainer.className = 'pnlm-render-container';
157        container.appendChild(renderContainer);
158        var dragFix = document.createElement('div');
159        dragFix.className = 'pnlm-dragfix';
160        uiContainer.appendChild(dragFix);
161
162// Display about information on right click off
163//         var aboutMsg = document.createElement('span');
164//         aboutMsg.className = 'pnlm-about-msg';
165//==wpvr custom rextheme link==//
166//         aboutMsg.innerHTML = '<a href="https://rextheme.com/docs/wpvr-360-panorama-and-virtual-tour-creator-for-wordpress/" target="_blank">Rextheme</a>';
167//==wpvr custom rextheme link end==//
168//         uiContainer.appendChild(aboutMsg);
169//         dragFix.addEventListener('contextmenu', aboutMessage);
170
171// Create info display
172        var infoDisplay = {};
173
174// Hot spot debug indicator
175        var hotSpotDebugIndicator = document.createElement('div');
176        hotSpotDebugIndicator.className = 'pnlm-sprite pnlm-hot-spot-debug-indicator';
177        uiContainer.appendChild(hotSpotDebugIndicator);
178
179// Panorama info
180        infoDisplay.container = document.createElement('div');
181        infoDisplay.container.className = 'pnlm-panorama-info';
182        infoDisplay.title = document.createElement('div');
183        infoDisplay.title.className = 'pnlm-title-box';
184        infoDisplay.container.appendChild(infoDisplay.title);
185        infoDisplay.author = document.createElement('div');
186        infoDisplay.author.className = 'pnlm-author-box';
187        infoDisplay.container.appendChild(infoDisplay.author);
188        uiContainer.appendChild(infoDisplay.container);
189
190// Load box
191        infoDisplay.load = {};
192        infoDisplay.load.box = document.createElement('div');
193        infoDisplay.load.box.className = 'pnlm-load-box';
194        infoDisplay.load.boxp = document.createElement('p');
195        infoDisplay.load.box.appendChild(infoDisplay.load.boxp);
196        infoDisplay.load.lbox = document.createElement('div');
197        infoDisplay.load.lbox.className = 'pnlm-lbox';
198        infoDisplay.load.lbox.innerHTML = '<div class="pnlm-loading"></div>';
199        infoDisplay.load.box.appendChild(infoDisplay.load.lbox);
200        infoDisplay.load.lbar = document.createElement('div');
201        infoDisplay.load.lbar.className = 'pnlm-lbar';
202        infoDisplay.load.lbarFill = document.createElement('div');
203        infoDisplay.load.lbarFill.className = 'pnlm-lbar-fill';
204        infoDisplay.load.lbar.appendChild(infoDisplay.load.lbarFill);
205        infoDisplay.load.box.appendChild(infoDisplay.load.lbar);
206        infoDisplay.load.msg = document.createElement('p');
207        infoDisplay.load.msg.className = 'pnlm-lmsg';
208        infoDisplay.load.box.appendChild(infoDisplay.load.msg);
209        uiContainer.appendChild(infoDisplay.load.box);
210
211// Error message
212        infoDisplay.errorMsg = document.createElement('div');
213        infoDisplay.errorMsg.className = 'pnlm-error-msg pnlm-info-box';
214        uiContainer.appendChild(infoDisplay.errorMsg);
215
216// Create controls
217        var controls = {};
218        controls.container = document.createElement('div');
219        controls.container.className = 'pnlm-controls-container';
220        uiContainer.appendChild(controls.container);
221
222// Load button
223        controls.load = document.createElement('div');
224        controls.load.className = 'pnlm-load-button';
225        controls.load.addEventListener('click', function() {
226            processOptions();
227            load();
228        });
229        uiContainer.appendChild(controls.load);
230
231// Zoom controls
232        controls.zoom = document.createElement('div');
233        controls.zoom.className = 'pnlm-zoom-controls pnlm-controls';
234        controls.zoomIn = document.createElement('div');
235        controls.zoomIn.className = 'pnlm-zoom-in pnlm-sprite pnlm-control';
236        controls.zoomIn.addEventListener('click', zoomIn);
237        controls.zoom.appendChild(controls.zoomIn);
238        controls.zoomOut = document.createElement('div');
239        controls.zoomOut.className = 'pnlm-zoom-out pnlm-sprite pnlm-control';
240        controls.zoomOut.addEventListener('click', zoomOut);
241        controls.zoom.appendChild(controls.zoomOut);
242        controls.container.appendChild(controls.zoom);
243
244// Fullscreen toggle
245        controls.fullscreen = document.createElement('div');
246        controls.fullscreen.addEventListener('click', toggleFullscreen);
247        controls.fullscreen.className = 'pnlm-fullscreen-toggle-button pnlm-sprite pnlm-fullscreen-toggle-button-inactive pnlm-controls pnlm-control';
248        if (document.fullscreenEnabled || document.mozFullScreenEnabled || document.webkitFullscreenEnabled || document.msFullscreenEnabled)
249            controls.container.appendChild(controls.fullscreen);
250
251// Device orientation toggle
252        controls.orientation = document.createElement('div');
253        controls.orientation.addEventListener('click', function(e) {
254            if (orientation)
255                stopOrientation();
256            else
257                startOrientation();
258        });
259        controls.orientation.addEventListener('mousedown', function(e) {e.stopPropagation();});
260        controls.orientation.addEventListener('touchstart', function(e) {e.stopPropagation();});
261        controls.orientation.addEventListener('pointerdown', function(e) {e.stopPropagation();});
262        controls.orientation.className = 'pnlm-orientation-button pnlm-orientation-button-inactive pnlm-sprite pnlm-controls pnlm-control';
263        var orientationSupport = false;
264        if (window.DeviceOrientationEvent && location.protocol == 'https:' &&
265            navigator.userAgent.toLowerCase().indexOf('mobi') >= 0) {
266            // This user agent check is here because there's no way to check if a
267            // device has an inertia measurement unit. We used to be able to check if a
268            // DeviceOrientationEvent had non-null values, but with iOS 13 requiring a
269            // permission prompt to access such events, this is no longer possible.
270            controls.container.appendChild(controls.orientation);
271            orientationSupport = true;
272        }
273
274// Compass
275        var compass = document.createElement('div');
276        compass.className = 'pnlm-compass pnlm-controls pnlm-control';
277        uiContainer.appendChild(compass);
278
279// Load and process configuration
280        if (initialConfig.firstScene) {
281            // Activate first scene if specified in URL
282            mergeConfig(initialConfig.firstScene);
283        } else if (initialConfig.default && initialConfig.default.firstScene) {
284            // Activate first scene if specified in file
285            mergeConfig(initialConfig.default.firstScene);
286        } else {
287            mergeConfig(null);
288        }
289        processOptions(true);
290
291        /**
292         * Initializes viewer.
293         * @private
294         */
295        function init() {
296            // Display an error for IE 9 as it doesn't work but also doesn't otherwise
297            // show an error (older versions don't work at all)
298            // Based on: http://stackoverflow.com/a/10965203
299            var div = document.createElement("div");
300            div.innerHTML = "<!--[if lte IE 9]><i></i><![endif]-->";
301            if (div.getElementsByTagName("i").length == 1) {
302                anError();
303                return;
304            }
305
306            origHfov = config.hfov;
307            origPitch = config.pitch;
308
309            var i, p;
310
311            if (config.type == 'cubemap') {
312                panoImage = [];
313                for (i = 0; i < 6; i++) {
314                    panoImage.push(new Image());
315                    panoImage[i].crossOrigin = config.crossOrigin;
316                }
317                infoDisplay.load.lbox.style.display = 'block';
318                infoDisplay.load.lbar.style.display = 'none';
319            } else if (config.type == 'multires') {
320                var c = JSON.parse(JSON.stringify(config.multiRes));    // Deep copy
321                // Avoid "undefined" in path, check (optional) multiRes.basePath, too
322                // Use only multiRes.basePath if it's an absolute URL
323                if (config.basePath && config.multiRes.basePath &&
324                    !(/^(?:[a-z]+:)?\/\//i.test(config.multiRes.basePath))) {
325                    c.basePath = config.basePath + config.multiRes.basePath;
326                } else if (config.multiRes.basePath) {
327                    c.basePath = config.multiRes.basePath;
328                } else if(config.basePath) {
329                    c.basePath = config.basePath;
330                }
331                panoImage = c;
332            } else {
333                if (config.dynamic === true) {
334                    panoImage = config.panorama;
335                } else {
336                    if (config.panorama === undefined) {
337                        anError(config.strings.noPanoramaError);
338                        return;
339                    }
340                    panoImage = new Image();
341                }
342            }
343
344            // Configure image loading
345            if (config.type == 'cubemap') {
346                // Quick loading counter for synchronous loading
347                var itemsToLoad = 6;
348
349                var onLoad = function() {
350                    itemsToLoad--;
351                    if (itemsToLoad === 0) {
352                        onImageLoad();
353                    }
354                };
355
356                var onError = function(e) {
357                    var a = document.createElement('a');
358                    a.href = e.target.src;
359                    a.textContent = a.href;
vendor: 7,842 bytes, lines 360-516
360                    anError(config.strings.fileAccessError.replace('%s', a.outerHTML));
361                };
362
363                for (i = 0; i < panoImage.length; i++) {
364                    p = config.cubeMap[i];
365                    if (p == "null") { // support partial cubemap image with explicitly empty faces
366                        console.log('Will use background instead of missing cubemap face ' + i);
367                        onLoad();
368                    } else {
369                        if (config.basePath && !absoluteURL(p)) {
370                            p = config.basePath + p;
371                        }
372                        panoImage[i].onload = onLoad;
373                        panoImage[i].onerror = onError;
374                        panoImage[i].src = sanitizeURL(p);
375                    }
376                }
377            } else if (config.type == 'multires') {
378                onImageLoad();
379            } else {
380                p = '';
381                if (config.basePath) {
382                    p = config.basePath;
383                }
384
385                if (config.dynamic !== true) {
386                    // Still image
387                    p = absoluteURL(config.panorama) ? config.panorama : p + config.panorama;
388
389                    panoImage.onload = function() {
390                        window.URL.revokeObjectURL(this.src);  // Clean up
391                        onImageLoad();
392                    };
393
394                    var xhr = new XMLHttpRequest();
395                    xhr.onloadend = function() {
396                        if (xhr.status != 200) {
397                            // Display error if image can't be loaded
398                            var a = document.createElement('a');
399                            a.href = p;
400                            a.textContent = a.href;
401                            anError(config.strings.fileAccessError.replace('%s', a.outerHTML));
402                        }
403                        var img = this.response;
404                        parseGPanoXMP(img, p);
405                        infoDisplay.load.msg.innerHTML = '';
406                    };
407                    xhr.onprogress = function(e) {
408                        if (e.lengthComputable) {
409                            // Display progress
410                            var percent = e.loaded / e.total * 100;
411                            infoDisplay.load.lbarFill.style.width = percent + '%';
412                            var unit, numerator, denominator;
413                            if (e.total > 1e6) {
414                                unit = 'MB';
415                                numerator = (e.loaded / 1e6).toFixed(2);
416                                denominator = (e.total / 1e6).toFixed(2);
417                            } else if (e.total > 1e3) {
418                                unit = 'kB';
419                                numerator = (e.loaded / 1e3).toFixed(1);
420                                denominator = (e.total / 1e3).toFixed(1);
421                            } else {
422                                unit = 'B';
423                                numerator = e.loaded;
424                                denominator = e.total;
425                            }
426                            infoDisplay.load.msg.innerHTML = numerator + ' / ' + denominator + ' ' + unit;
427                        } else {
428                            // Display loading spinner
429                            infoDisplay.load.lbox.style.display = 'block';
430                            infoDisplay.load.lbar.style.display = 'none';
431                        }
432                    };
433                    try {
434                        xhr.open('GET', p, true);
435                    } catch (e) {
436                        // Malformed URL
437                        anError(config.strings.malformedURLError);
438                    }
439                    xhr.responseType = 'blob';
440                    xhr.setRequestHeader('Accept', 'image/*,*/*;q=0.9');
441                    xhr.withCredentials = config.crossOrigin === 'use-credentials';
442                    xhr.send();
443                }
444            }
445
446            if (config.draggable)
447                uiContainer.classList.add('pnlm-grab');
448            uiContainer.classList.remove('pnlm-grabbing');
449
450            // Properly handle switching to dynamic scenes
451            update = config.dynamicUpdate === true;
452            if (config.dynamic && update) {
453                panoImage = config.panorama;
454                onImageLoad();
455            }
456        }
457
458        /**
459         * Test if URL is absolute or relative.
460         * @private
461         * @param {string} url - URL to test
462         * @returns {boolean} True if absolute, else false
463         */
464        function absoluteURL(url) {
465            // From http://stackoverflow.com/a/19709846
466            return new RegExp('^(?:[a-z]+:)?//', 'i').test(url) || url[0] == '/' || url.slice(0, 5) == 'blob:';
467        }
468
469        /**
470         * Create renderer and initialize event listeners once image is loaded.
471         * @private
472         */
473        function onImageLoad() {
474            if (!renderer)
475                renderer = new libpannellum.renderer(renderContainer);
476
477            // Only add event listeners once
478            if (!listenersAdded) {
479                listenersAdded = true;
480                dragFix.addEventListener('mousedown', onDocumentMouseDown, false);
481                document.addEventListener('mousemove', onDocumentMouseMove, false);
482                document.addEventListener('compasschange', onDocumentCompassChange, false);
483                document.addEventListener('mouseup', onDocumentMouseUp, false);
484                if (config.mouseZoom) {
485                    uiContainer.addEventListener('mousewheel', onDocumentMouseWheel, false);
486                    uiContainer.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
487                }
488                if (config.doubleClickZoom) {
489                    dragFix.addEventListener('dblclick', onDocumentDoubleClick, false);
490                }
491                container.addEventListener('mozfullscreenchange', onFullScreenChange, false);
492                container.addEventListener('webkitfullscreenchange', onFullScreenChange, false);
493                container.addEventListener('msfullscreenchange', onFullScreenChange, false);
494                container.addEventListener('fullscreenchange', onFullScreenChange, false);
495                window.addEventListener('resize', onDocumentResize, false);
496                window.addEventListener('orientationchange', onDocumentResize, false);
497                if (!config.disableKeyboardCtrl) {
498                    container.addEventListener('keydown', onDocumentKeyPress, false);
499                    container.addEventListener('keyup', onDocumentKeyUp, false);
500                    container.addEventListener('blur', clearKeys, false);
501                }
502                document.addEventListener('mouseleave', onDocumentMouseUp, false);
503                if (document.documentElement.style.pointerAction === '' &&
504                    document.documentElement.style.touchAction === '') {
505                    dragFix.addEventListener('pointerdown', onDocumentPointerDown, false);
506                    dragFix.addEventListener('pointermove', onDocumentPointerMove, false);
507                    dragFix.addEventListener('pointerup', onDocumentPointerUp, false);
508                    dragFix.addEventListener('pointerleave', onDocumentPointerUp, false);
509                } else {
510                    dragFix.addEventListener('touchstart', onDocumentTouchStart, false);
511                    dragFix.addEventListener('touchmove', onDocumentTouchMove, false);
512                    dragFix.addEventListener('touchend', onDocumentTouchEnd, false);
513                }
514
515                // Deal with MS pointer events
516                if (window.navigator.pointerEnabled)
517                    container.style.touchAction = 'none';
518            }
519
520            renderInit();
521            setHfov(config.hfov); // possibly adapt hfov after configuration and canvas is complete; prevents empty space on top or bottom by zomming out too much
522            setTimeout(function(){isTimedOut = true;}, 500);
523        }
524
525        /**
526         * Parses Google Photo Sphere XMP Metadata.
527         * https://developers.google.com/photo-sphere/metadata/
528         * @private
529         * @param {Image} image - Image to read XMP metadata from.
530         */
531        function parseGPanoXMP(image, url) {
532            var reader = new FileReader();
533            reader.addEventListener('loadend', function() {
534                var img = reader.result;
535
536                // This awful browser specific test exists because iOS 8 does not work
537                // with non-progressive encoded JPEGs.
538                if (navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 8_/)) {
539                    var flagIndex = img.indexOf('\xff\xc2');
540                    if (flagIndex < 0 || flagIndex > 65536)
541                        anError(config.strings.iOS8WebGLError);
542                }
543
544                var start = img.indexOf('<x:xmpmeta');
545                if (start > -1 && config.ignoreGPanoXMP !== true) {
546                    var xmpData = img.substring(start, img.indexOf('</x:xmpmeta>') + 12);
547
548                    // Extract the requested tag from the XMP data
549                    var getTag = function(tag) {
550                        var result;
551                        if (xmpData.indexOf(tag + '="') >= 0) {
552                            result = xmpData.substring(xmpData.indexOf(tag + '="') + tag.length + 2);
553                            result = result.substring(0, result.indexOf('"'));
554                        } else if (xmpData.indexOf(tag + '>') >= 0) {
555                            result = xmpData.substring(xmpData.indexOf(tag + '>') + tag.length + 1);
556                            result = result.substring(0, result.indexOf('<'));
557                        }
558                        if (result !== undefined) {
559                            return Number(result);
560                        }
561                        return null;
562                    };
563
564                    // Relevant XMP data
565                    var xmp = {
566                        fullWidth: getTag('GPano:FullPanoWidthPixels'),
567                        croppedWidth: getTag('GPano:CroppedAreaImageWidthPixels'),
568                        fullHeight: getTag('GPano:FullPanoHeightPixels'),
569                        croppedHeight: getTag('GPano:CroppedAreaImageHeightPixels'),
570                        topPixels: getTag('GPano:CroppedAreaTopPixels'),
571                        heading: getTag('GPano:PoseHeadingDegrees'),
572                        horizonPitch: getTag('GPano:PosePitchDegrees'),
573                        horizonRoll: getTag('GPano:PoseRollDegrees')
574                    };
575
576                    if (xmp.fullWidth !== null && xmp.croppedWidth !== null &&
577                        xmp.fullHeight !== null && xmp.croppedHeight !== null &&
578                        xmp.topPixels !== null) {
579
580                        // Set up viewer using GPano XMP data
581                        if (specifiedPhotoSphereExcludes.indexOf('haov') < 0)
582                            config.haov = xmp.croppedWidth / xmp.fullWidth * 360;
583                        if (specifiedPhotoSphereExcludes.indexOf('vaov') < 0)
584                            config.vaov = xmp.croppedHeight / xmp.fullHeight * 180;
585                        if (specifiedPhotoSphereExcludes.indexOf('vOffset') < 0)
586                            config.vOffset = ((xmp.topPixels + xmp.croppedHeight / 2) / xmp.fullHeight - 0.5) * -180;
587                        if (xmp.heading !== null && specifiedPhotoSphereExcludes.indexOf('northOffset') < 0) {
588                            // TODO: make sure this works correctly for partial panoramas
589                            config.northOffset = xmp.heading;
590                            if (config.compass !== false) {
591                                config.compass = true;
592                            }
593                        }
594                        if (xmp.horizonPitch !== null && xmp.horizonRoll !== null) {
595                            if (specifiedPhotoSphereExcludes.indexOf('horizonPitch') < 0)
596                                config.horizonPitch = xmp.horizonPitch;
597                            if (specifiedPhotoSphereExcludes.indexOf('horizonRoll') < 0)
598                                config.horizonRoll = xmp.horizonRoll;
599                        }
600
601                        // TODO: add support for initial view settings
602                    }
603                }
604
605                // Load panorama
606                panoImage.src = window.URL.createObjectURL(image);
607                panoImage.onerror = function() {
608                    // If the image fails to load, we check the Content Security Policy
609                    // headers and see if they block loading images as blobs. If they
610                    // do, we load the image directly from the URL. While this should
611                    // allow the image to load, it does prevent parsing of XMP data.
612                    function getCspHeaders() {
613                        if (!window.fetch)
614                            return null;
615                        return window.fetch(document.location.href)
616                            .then(function(resp){
617                                return resp.headers.get('Content-Security-Policy');
618                            });
619                    }
620                    getCspHeaders().then(function(cspHeaders) {
621                        if (cspHeaders) {
622                            var invalidImgSource = cspHeaders.split(";").find(function(p) {
623                                var matchstring = p.match(/img-src(.*)/);
624                                if (matchstring) {
625                                    return !matchstring[1].includes("blob");
626                                }
627                            });
628                            if (invalidImgSource) {
629                                console.log('CSP blocks blobs; reverting to URL.');
630                                panoImage.crossOrigin = config.crossOrigin;
631                                panoImage.src = url;
632                            }
633                        }
634                    });
635                }
636            });
637            if (reader.readAsBinaryString !== undefined)
638                reader.readAsBinaryString(image);
639            else
640                reader.readAsText(image);
641        }
642
643        /**
644         * Displays an error message.
645         * @private
646         * @param {string} errorMsg - Error message to display. If not specified, a
647         *      generic WebGL error is displayed.
648         */
649        function anError(errorMsg) {
650            if (errorMsg === undefined)
651                errorMsg = config.strings.genericWebGLError;
652            infoDisplay.errorMsg.innerHTML = '<p>' + errorMsg + '</p>';
653            controls.load.style.display = 'none';
654            infoDisplay.load.box.style.display = 'none';
655            infoDisplay.errorMsg.style.display = 'table';
656            error = true;
657            loaded = undefined;
658            renderContainer.style.display = 'none';
659            fireEvent('error', errorMsg);
660        }
661
662        /**
663         * Hides error message display.
664         * @private
665         */
666        function clearError() {
667            if (error) {
668                infoDisplay.load.box.style.display = 'none';
669                infoDisplay.errorMsg.style.display = 'none';
670                error = false;
671                renderContainer.style.display = 'block';
672                fireEvent('errorcleared');
673            }
674        }
675
676        /**
677         * Displays about message.
678         * @private
679         * @param {MouseEvent} event - Right click location
680         */
681        function aboutMessage(event) {
682            var pos = mousePosition(event);
683            aboutMsg.style.left = pos.x + 'px';
684            aboutMsg.style.top = pos.y + 'px';
685            clearTimeout(aboutMessage.t1);
686            clearTimeout(aboutMessage.t2);
687            aboutMsg.style.display = 'block';
688            aboutMsg.style.opacity = 1;
689            aboutMessage.t1 = setTimeout(function() {aboutMsg.style.opacity = 0;}, 2000);
690            aboutMessage.t2 = setTimeout(function() {aboutMsg.style.display = 'none';}, 2500);
691            event.preventDefault();
692        }
693
694        /**
695         * Calculate mouse position relative to top left of viewer container.
696         * @private
697         * @param {MouseEvent} event - Mouse event to use in calculation
698         * @returns {Object} Calculated X and Y coordinates
699         */
700        function mousePosition(event) {
701            var bounds = container.getBoundingClientRect();
702            var pos = {};
703            // pageX / pageY needed for iOS
704            pos.x = (event.clientX || event.pageX) - bounds.left;
705            pos.y = (event.clientY || event.pageY) - bounds.top;
706            return pos;
707        }
708
709        /**
710         * Event handler for mouse clicks. Initializes panning. Prints center and click
711         * location coordinates when hot spot debugging is enabled.
712         * @private
713         * @param {MouseEvent} event - Document mouse down event.
714         */
715        function onDocumentMouseDown(event) {
716            // Override default action
717            event.preventDefault();
718            // But not all of it
719            container.focus();
720
721            // Only do something if the panorama is loaded
722            if (!loaded || !config.draggable) {
723                return;
724            }
725
726            // Calculate mouse position relative to top left of viewer container
727            var pos = mousePosition(event);
728
729            // Log pitch / yaw of mouse click when debugging / placing hot spots
730            if (config.hotSpotDebug) {
731                var coords = mouseEventToCoords(event);
732                console.log('Pitch: ' + coords[0] + ', Yaw: ' + coords[1] + ', Center Pitch: ' +
733                    config.pitch + ', Center Yaw: ' + config.yaw + ', HFOV: ' + config.hfov);
734            }
735
736            // Turn off auto-rotation if enabled
737            stopAnimation();
738
739            stopOrientation();
740            config.roll = 0;
741
742            speed.hfov = 0;
743
744            isUserInteracting = true;
745            latestInteraction = Date.now();
746
747            onPointerDownPointerX = pos.x;
748            onPointerDownPointerY = pos.y;
749
750            onPointerDownYaw = config.yaw;
751            onPointerDownPitch = config.pitch;
752
753            uiContainer.classList.add('pnlm-grabbing');
754            uiContainer.classList.remove('pnlm-grab');
755
756            fireEvent('mousedown', event);
757            animateInit();
758        }
759
760        /**
761         * Event handler for double clicks. Zooms in at clicked location
762         * @private
763         * @param {MouseEvent} event - Document mouse down event.
764         */
765        function onDocumentDoubleClick(event) {
766            if (config.minHfov === config.hfov) {
767                _this.setHfov(origHfov, 1000);
768            } else {
769                var coords = mouseEventToCoords(event);
770                _this.lookAt(coords[0], coords[1], config.minHfov, 1000);
771            }
772        }
773
774        /**
775         * Calculate panorama pitch and yaw from location of mouse event.
776         * @private
777         * @param {MouseEvent} event - Document mouse down event.
778         * @returns {number[]} [pitch, yaw]
779         */
780        function mouseEventToCoords(event) {
781            var pos = mousePosition(event);
782            var canvas = renderer.getCanvas();
783            var canvasWidth = canvas.clientWidth,
784                canvasHeight = canvas.clientHeight;
785            var x = pos.x / canvasWidth * 2 - 1;
786            var y = (1 - pos.y / canvasHeight * 2) * canvasHeight / canvasWidth;
787            var focal = 1 / Math.tan(config.hfov * Math.PI / 360);
788            var s = Math.sin(config.pitch * Math.PI / 180);
789            var c = Math.cos(config.pitch * Math.PI / 180);
790            var a = focal * c - y * s;
791            var root = Math.sqrt(x*x + a*a);
792            var pitch = Math.atan((y * c + focal * s) / root) * 180 / Math.PI;
793            var yaw = Math.atan2(x / root, a / root) * 180 / Math.PI + config.yaw;
794            if (yaw < -180)
795                yaw += 360;
796            if (yaw > 180)
797                yaw -= 360;
798            return [pitch, yaw];
799        }
800
801        function onDocumentCompassChange(event) {
802            
803        }
804
805        /**
806         * Event handler for mouse moves. Pans center of view.
807         * @private
808         * @param {MouseEvent} event - Document mouse move event.
809         */
810        function onDocumentMouseMove(event) {
811            if (isUserInteracting && loaded) {
812                latestInteraction = Date.now();
813                var canvas = renderer.getCanvas();
814                var canvasWidth = canvas.clientWidth,
815                    canvasHeight = canvas.clientHeight;
816                var pos = mousePosition(event);
817                //TODO: This still isn't quite right
818                var yaw = ((Math.atan(onPointerDownPointerX / canvasWidth * 2 - 1) - Math.atan(pos.x / canvasWidth * 2 - 1)) * 180 / Math.PI * config.hfov / 90) + onPointerDownYaw;
819                speed.yaw = (yaw - config.yaw) % 360 * 0.2;
820                config.yaw = yaw;
821
822                var vfov = 2 * Math.atan(Math.tan(config.hfov/360*Math.PI) * canvasHeight / canvasWidth) * 180 / Math.PI;
823
824                var pitch = ((Math.atan(pos.y / canvasHeight * 2 - 1) - Math.atan(onPointerDownPointerY / canvasHeight * 2 - 1)) * 180 / Math.PI * vfov / 90) + onPointerDownPitch;
825                speed.pitch = (pitch - config.pitch) * 0.2;
826                config.pitch = pitch;
827
828                var mirrorData = {
829                    pitch: pitch,
830                    yaw: yaw
831                }
832                fireEvent('mousemove', mirrorData);
833
834            }
835        }
836
837        /**
838         * Event handler for mouse up events. Stops panning.
839         * @private
840         */
841        function onDocumentMouseUp(event) {
842            if (!isUserInteracting) {
843                return;
844            }
845            isUserInteracting = false;
vendor: 4,780 bytes, lines 846-962
846            if (Date.now() - latestInteraction > 15) {
847                // Prevents jump when user rapidly moves mouse, stops, and then
848                // releases the mouse button
849                speed.pitch = speed.yaw = 0;
850            }
851            uiContainer.classList.add('pnlm-grab');
852            uiContainer.classList.remove('pnlm-grabbing');
853            latestInteraction = Date.now();
854
855            fireEvent('mouseup', event);
856        }
857
858        /**
859         * Event handler for touches. Initializes panning if one touch or zooming if
860         * two touches.
861         * @private
862         * @param {TouchEvent} event - Document touch start event.
863         */
864        function onDocumentTouchStart(event) {
865            // Only do something if the panorama is loaded
866            if (!loaded || !config.draggable) {
867                return;
868            }
869
870            // Turn off auto-rotation if enabled
871            stopAnimation();
872
873            stopOrientation();
874            config.roll = 0;
875
876            speed.hfov = 0;
877
878            // Calculate touch position relative to top left of viewer container
879            var pos0 = mousePosition(event.targetTouches[0]);
880
881            onPointerDownPointerX = pos0.x;
882            onPointerDownPointerY = pos0.y;
883
884            if (event.targetTouches.length == 2) {
885                // Down pointer is the center of the two fingers
886                var pos1 = mousePosition(event.targetTouches[1]);
887                onPointerDownPointerX += (pos1.x - pos0.x) * 0.5;
888                onPointerDownPointerY += (pos1.y - pos0.y) * 0.5;
889                onPointerDownPointerDist = Math.sqrt((pos0.x - pos1.x) * (pos0.x - pos1.x) +
890                    (pos0.y - pos1.y) * (pos0.y - pos1.y));
891            }
892            isUserInteracting = true;
893            latestInteraction = Date.now();
894
895            onPointerDownYaw = config.yaw;
896            onPointerDownPitch = config.pitch;
897
898            fireEvent('touchstart', event);
899            animateInit();
900        }
901
902        /**
903         * Event handler for touch movements. Pans center of view if one touch or
904         * adjusts zoom if two touches.
905         * @private
906         * @param {TouchEvent} event - Document touch move event.
907         */
908        function onDocumentTouchMove(event) {
909            if (!config.draggable) {
910                return;
911            }
912
913            // Override default action
914            event.preventDefault();
915            if (loaded) {
916                latestInteraction = Date.now();
917            }
918            if (isUserInteracting && loaded) {
919                var pos0 = mousePosition(event.targetTouches[0]);
920                var clientX = pos0.x;
921                var clientY = pos0.y;
922
923                if (event.targetTouches.length == 2 && onPointerDownPointerDist != -1) {
924                    var pos1 = mousePosition(event.targetTouches[1]);
925                    clientX += (pos1.x - pos0.x) * 0.5;
926                    clientY += (pos1.y - pos0.y) * 0.5;
927                    var clientDist = Math.sqrt((pos0.x - pos1.x) * (pos0.x - pos1.x) +
928                        (pos0.y - pos1.y) * (pos0.y - pos1.y));
929                    setHfov(config.hfov + (onPointerDownPointerDist - clientDist) * 0.1);
930                    onPointerDownPointerDist = clientDist;
931                }
932
933                // The smaller the config.hfov value (the more zoomed-in the user is), the faster
934                // yaw/pitch are perceived to change on one-finger touchmove (panning) events and vice versa.
935                // To improve usability at both small and large zoom levels (config.hfov values)
936                // we introduce a dynamic pan speed coefficient.
937                //
938                // Currently this seems to *roughly* keep initial drag/pan start position close to
939                // the user's finger while panning regardless of zoom level / config.hfov value.
940                var touchmovePanSpeedCoeff = (config.hfov / 360) * config.touchPanSpeedCoeffFactor;
941
942                var yaw = (onPointerDownPointerX - clientX) * touchmovePanSpeedCoeff + onPointerDownYaw;
943                speed.yaw = (yaw - config.yaw) % 360 * 0.2;
944                config.yaw = yaw;
945
946                var pitch = (clientY - onPointerDownPointerY) * touchmovePanSpeedCoeff + onPointerDownPitch;
947                speed.pitch = (pitch - config.pitch) * 0.2;
948                config.pitch = pitch;
949                var mirrorData = {
950                    pitch: pitch,
951                    yaw: yaw
952                }
953                fireEvent('touchmove', mirrorData);
954            }
955        }
956
957        /**
958         * Event handler for end of touches. Stops panning and/or zooming.
959         * @private
960         */
961        function onDocumentTouchEnd() {
962            isUserInteracting = false;
963            if (Date.now() - latestInteraction > 150) {
964                speed.pitch = speed.yaw = 0;
965            }
966            onPointerDownPointerDist = -1;
967            latestInteraction = Date.now();
968
969            fireEvent('touchend', event);
970        }
971
972        var pointerIDs = [],
973            pointerCoordinates = [];
974        /**
975         * Event handler for touch starts in IE / Edge.
976         * @private
977         * @param {PointerEvent} event - Document pointer down event.
978         */
979        function onDocumentPointerDown(event) {
980            if (event.pointerType == 'touch') {
981                // Only do something if the panorama is loaded
982                if (!loaded || !config.draggable)
983                    return;
984                pointerIDs.push(event.pointerId);
985                pointerCoordinates.push({clientX: event.clientX, clientY: event.clientY});
986                event.targetTouches = pointerCoordinates;
987                onDocumentTouchStart(event);
988                event.preventDefault();
989            }
990        }
991
992        /**
993         * Event handler for touch moves in IE / Edge.
994         * @private
995         * @param {PointerEvent} event - Document pointer move event.
996         */
997        function onDocumentPointerMove(event) {
998            if (event.pointerType == 'touch') {
999                if (!config.draggable)
1000                    return;
1001                for (var i = 0; i < pointerIDs.length; i++) {
1002                    if (event.pointerId == pointerIDs[i]) {
1003                        pointerCoordinates[i].clientX = event.clientX;
1004                        pointerCoordinates[i].clientY = event.clientY;
1005                        event.targetTouches = pointerCoordinates;
1006                        onDocumentTouchMove(event);
1007                        event.preventDefault();
1008                        return;
1009                    }
1010                }
1011            }
1012        }
1013
1014        /**
1015         * Event handler for touch ends in IE / Edge.
1016         * @private
1017         * @param {PointerEvent} event - Document pointer up event.
1018         */
1019        function onDocumentPointerUp(event) {
1020            if (event.pointerType == 'touch') {
1021                var defined = false;
1022                for (var i = 0; i < pointerIDs.length; i++) {
1023                    if (event.pointerId == pointerIDs[i])
1024                        pointerIDs[i] = undefined;
1025                    if (pointerIDs[i])
1026                        defined = true;
1027                }
1028                if (!defined) {
1029                    pointerIDs = [];
1030                    pointerCoordinates = [];
1031                    onDocumentTouchEnd();
1032                }
1033                event.preventDefault();
1034            }
1035        }
1036
1037        /**
1038         * Event handler for mouse wheel. Changes zoom.
1039         * @private
1040         * @param {WheelEvent} event - Document mouse wheel event.
1041         */
1042        function onDocumentMouseWheel(event) {
1043            // Only do something if the panorama is loaded and mouse wheel zoom is enabled
1044            if (!loaded || (config.mouseZoom == 'fullscreenonly' && !fullscreenActive)) {
1045                return;
1046            }
1047
1048            event.preventDefault();
1049
1050            // Turn off auto-rotation if enabled
1051            stopAnimation();
1052            latestInteraction = Date.now();
1053
1054            if (event.wheelDeltaY) {
1055                // WebKit
1056                setHfov(config.hfov - event.wheelDeltaY * 0.05);
1057                speed.hfov = event.wheelDelta < 0 ? 1 : -1;
1058            } else if (event.wheelDelta) {
1059                // Opera / Explorer 9
1060                setHfov(config.hfov - event.wheelDelta * 0.05);
1061                speed.hfov = event.wheelDelta < 0 ? 1 : -1;
1062            } else if (event.detail) {
1063                // Firefox
1064                setHfov(config.hfov + event.detail * 1.5);
1065                speed.hfov = event.detail > 0 ? 1 : -1;
1066            }
1067            animateInit();
1068        }
1069
1070        /**
1071         * Event handler for key presses. Updates list of currently pressed keys.
1072         * @private
1073         * @param {KeyboardEvent} event - Document key press event.
1074         */
1075        function onDocumentKeyPress(event) {
1076            // Turn off auto-rotation if enabled
1077            stopAnimation();
1078            latestInteraction = Date.now();
1079
1080            stopOrientation();
1081            config.roll = 0;
1082
1083            // Record key pressed
1084            var keynumber = event.which || event.keycode;
1085
1086            // Override default action for keys that are used
1087            if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
1088                return;
1089            event.preventDefault();
1090
1091            // If escape key is pressed
1092            if (keynumber == 27) {
1093                // If in fullscreen mode
1094                if (fullscreenActive) {
1095                    toggleFullscreen();
1096                }
1097            } else {
1098                // Change key
1099                changeKey(keynumber, true);
1100            }
1101        }
1102
1103        /**
1104         * Clears list of currently pressed keys.
1105         * @private
1106         */
1107        function clearKeys() {
1108            for (var i = 0; i < 10; i++) {
1109                keysDown[i] = false;
vendor: 6,327 bytes, lines 1110-1287
1110            }
1111        }
1112
1113        /**
1114         * Event handler for key releases. Updates list of currently pressed keys.
1115         * @private
1116         * @param {KeyboardEvent} event - Document key up event.
1117         */
1118        function onDocumentKeyUp(event) {
1119            // Record key pressed
1120            var keynumber = event.which || event.keycode;
1121
1122            // Override default action for keys that are used
1123            if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
1124                return;
1125            event.preventDefault();
1126
1127            // Change key
1128            changeKey(keynumber, false);
1129        }
1130
1131        /**
1132         * Updates list of currently pressed keys.
1133         * @private
1134         * @param {number} keynumber - Key number.
1135         * @param {boolean} value - Whether or not key is pressed.
1136         */
1137        function changeKey(keynumber, value) {
1138            var keyChanged = false;
1139            switch(keynumber) {
1140                // If minus key is released
1141                case 109: case 189: case 17: case 173:
1142                    if (keysDown[0] != value) { keyChanged = true; }
1143                    keysDown[0] = value; break;
1144
1145                // If plus key is released
1146                case 107: case 187: case 16: case 61:
1147                    if (keysDown[1] != value) { keyChanged = true; }
1148                    keysDown[1] = value; break;
1149
1150                // If up arrow is released
1151                case 38:
1152                    if (keysDown[2] != value) { keyChanged = true; }
1153                    keysDown[2] = value; break;
1154
1155                // If "w" is released
1156                case 87:
1157                    if (keysDown[6] != value) { keyChanged = true; }
1158                    keysDown[6] = value; break;
1159
1160                // If down arrow is released
1161                case 40:
1162                    if (keysDown[3] != value) { keyChanged = true; }
1163                    keysDown[3] = value; break;
1164
1165                // If "s" is released
1166                case 83:
1167                    if (keysDown[7] != value) { keyChanged = true; }
1168                    keysDown[7] = value; break;
1169
1170                // If left arrow is released
1171                case 37:
1172                    if (keysDown[4] != value) { keyChanged = true; }
1173                    keysDown[4] = value; break;
1174
1175                // If "a" is released
1176                case 65:
1177                    if (keysDown[8] != value) { keyChanged = true; }
1178                    keysDown[8] = value; break;
1179
1180                // If right arrow is released
1181                case 39:
1182                    if (keysDown[5] != value) { keyChanged = true; }
1183                    keysDown[5] = value; break;
1184
1185                // If "d" is released
1186                case 68:
1187                    if (keysDown[9] != value) { keyChanged = true; }
1188                    keysDown[9] = value;
1189            }
1190
1191            if (keyChanged && value) {
1192                if (typeof performance !== 'undefined' && performance.now()) {
1193                    prevTime = performance.now();
1194                } else {
1195                    prevTime = Date.now();
1196                }
1197                animateInit();
1198            }
1199        }
1200
1201        /**
1202         * Pans and/or zooms panorama based on currently pressed keys. Also handles
1203         * panorama "inertia" and auto rotation.
1204         * @private
1205         */
1206        function keyRepeat() {
1207            // Only do something if the panorama is loaded
1208            if (!loaded) {
1209                return;
1210            }
1211
1212            var isKeyDown = false;
1213
1214            var prevPitch = config.pitch;
1215            var prevYaw = config.yaw;
1216            var prevZoom = config.hfov;
1217
1218            var newTime;
1219            if (typeof performance !== 'undefined' && performance.now()) {
1220                newTime = performance.now();
1221            } else {
1222                newTime = Date.now();
1223            }
1224            if (prevTime === undefined) {
1225                prevTime = newTime;
1226            }
1227            var diff = (newTime - prevTime) * config.hfov / 1700;
1228            diff = Math.min(diff, 1.0);
1229
1230            // If minus key is down
1231            if (keysDown[0] && config.keyboardZoom === true) {
1232                setHfov(config.hfov + (speed.hfov * 0.8 + 0.5) * diff);
1233                isKeyDown = true;
1234            }
1235
1236            // If plus key is down
1237            if (keysDown[1] && config.keyboardZoom === true) {
1238                setHfov(config.hfov + (speed.hfov * 0.8 - 0.2) * diff);
1239                isKeyDown = true;
1240            }
1241
1242            // If up arrow or "w" is down
1243            if (keysDown[2] || keysDown[6]) {
1244                // Pan up
1245                config.pitch += (speed.pitch * 0.8 + 0.2) * diff;
1246                isKeyDown = true;
1247            }
1248
1249            // If down arrow or "s" is down
1250            if (keysDown[3] || keysDown[7]) {
1251                // Pan down
1252                config.pitch += (speed.pitch * 0.8 - 0.2) * diff;
1253                isKeyDown = true;
1254            }
1255
1256            // If left arrow or "a" is down
1257            if (keysDown[4] || keysDown[8]) {
1258                // Pan left
1259                config.yaw += (speed.yaw * 0.8 - 0.2) * diff;
1260                isKeyDown = true;
1261            }
1262
1263            // If right arrow or "d" is down
1264            if (keysDown[5] || keysDown[9]) {
1265                // Pan right
1266                config.yaw += (speed.yaw * 0.8 + 0.2) * diff;
1267                isKeyDown = true;
1268            }
1269
1270            if (isKeyDown)
1271                latestInteraction = Date.now();
1272
1273            // If auto-rotate
1274            if (config.autoRotate) {
1275                // Pan
1276                if (newTime - prevTime > 0.001) {
1277                    var timeDiff = (newTime - prevTime) / 1000;
1278                    var yawDiff = (speed.yaw / timeDiff * diff - config.autoRotate * 0.2) * timeDiff;
1279                    yawDiff = (-config.autoRotate > 0 ? 1 : -1) * Math.min(Math.abs(config.autoRotate * timeDiff), Math.abs(yawDiff));
1280                    config.yaw += yawDiff;
1281                }
1282
1283                // Deal with stopping auto rotation after a set delay
1284                if (config.autoRotateStopDelay) {
1285                    config.autoRotateStopDelay -= newTime - prevTime;
1286                    if (config.autoRotateStopDelay <= 0) {
1287                        config.autoRotateStopDelay = false;
1288                        autoRotateSpeed = config.autoRotate;
1289                        config.autoRotate = 0;
1290                    }
1291                }
1292            }
1293
1294            // Animated moves
1295            if (animatedMove.pitch) {
1296                animateMove('pitch');
1297                prevPitch = config.pitch;
1298            }
1299            if (animatedMove.yaw) {
1300                animateMove('yaw');
1301                prevYaw = config.yaw;
1302            }
1303            if (animatedMove.hfov) {
1304                animateMove('hfov');
1305                prevZoom = config.hfov;
1306            }
1307
1308            // "Inertia"
1309            if (diff > 0 && !config.autoRotate) {
1310                // "Friction"
1311                var slowDownFactor = 1 - config.friction;
1312
1313                // Yaw
1314                if (!keysDown[4] && !keysDown[5] && !keysDown[8] && !keysDown[9] && !animatedMove.yaw) {
1315                    config.yaw += speed.yaw * diff * slowDownFactor;
1316                }
1317                // Pitch
1318                if (!keysDown[2] && !keysDown[3] && !keysDown[6] && !keysDown[7] && !animatedMove.pitch) {
1319                    config.pitch += speed.pitch * diff * slowDownFactor;
1320                }
1321                // Zoom
1322                if (!keysDown[0] && !keysDown[1] && !animatedMove.hfov) {
1323                    setHfov(config.hfov + speed.hfov * diff * slowDownFactor);
1324                }
1325            }
1326
1327            prevTime = newTime;
1328            if (diff > 0) {
1329                speed.yaw = speed.yaw * 0.8 + (config.yaw - prevYaw) / diff * 0.2;
1330                speed.pitch = speed.pitch * 0.8 + (config.pitch - prevPitch) / diff * 0.2;
1331                speed.hfov = speed.hfov * 0.8 + (config.hfov - prevZoom) / diff * 0.2;
1332
1333                // Limit speed
1334                var maxSpeed = config.autoRotate ? Math.abs(config.autoRotate) : 5;
1335                speed.yaw = Math.min(maxSpeed, Math.max(speed.yaw, -maxSpeed));
1336                speed.pitch = Math.min(maxSpeed, Math.max(speed.pitch, -maxSpeed));
1337                speed.hfov = Math.min(maxSpeed, Math.max(speed.hfov, -maxSpeed));
1338            }
1339
1340            // Stop movement if opposite controls are pressed
1341            if (keysDown[0] && keysDown[1]) {
1342                speed.hfov = 0;
1343            }
1344            if ((keysDown[2] || keysDown[6]) && (keysDown[3] || keysDown[7])) {
1345                speed.pitch = 0;
1346            }
1347            if ((keysDown[4] || keysDown[8]) && (keysDown[5] || keysDown[9])) {
1348                speed.yaw = 0;
1349            }
1350        }
1351
1352        /**
1353         * Animates moves.
1354         * @param {string} axis - Axis to animate
1355         * @private
1356         */
1357        function animateMove(axis) {
1358            var t = animatedMove[axis];
1359            var normTime = Math.min(1, Math.max((Date.now() - t.startTime) / 1000 / (t.duration / 1000), 0));
1360            var result = t.startPosition + config.animationTimingFunction(normTime) * (t.endPosition - t.startPosition);
1361            if ((t.endPosition > t.startPosition && result >= t.endPosition) ||
1362                (t.endPosition < t.startPosition && result <= t.endPosition) ||
1363                t.endPosition === t.startPosition) {
1364                result = t.endPosition;
1365                speed[axis] = 0;
1366                delete animatedMove[axis];
1367            }
1368            config[axis] = result;
1369        }
1370
1371        /**
1372         * @param {number} t - Normalized time in animation
1373         * @return {number} Position in animation
1374         * @private
1375         */
1376        function timingFunction(t) {
1377            // easeInOutQuad from https://gist.github.com/gre/1650294
1378            return t < 0.5 ? 2*t*t : -1+(4-2*t)*t;
1379        }
1380
1381        /**
1382         * Event handler for document resizes. Updates viewer size and rerenders view.
1383         * @private
1384         */
1385        function onDocumentResize() {
1386            // Resize panorama renderer (moved to onFullScreenChange)
1387            //renderer.resize();
1388            //animateInit();
1389
1390            // Kludge to deal with WebKit regression: https://bugs.webkit.org/show_bug.cgi?id=93525
1391            onFullScreenChange('resize');
1392        }
1393
1394        /**
1395         * Initializes animation.
1396         * @private
1397         */
1398        function animateInit() {
1399            if (animating) {
1400                return;
1401            }
1402            animating = true;
1403            animate();
1404        }
1405
1406        /**
1407         * Animates view, using requestAnimationFrame to trigger rendering.
1408         * @private
1409         */
1410        function animate() {
1411            if (destroyed) {
1412                return;
1413            }
1414
1415            render();
1416            if (autoRotateStart)
1417                clearTimeout(autoRotateStart);
1418            if (isUserInteracting || orientation === true) {
1419                requestAnimationFrame(animate);
1420            } else if (keysDown[0] || keysDown[1] || keysDown[2] || keysDown[3] ||
1421                keysDown[4] || keysDown[5] || keysDown[6] || keysDown[7] ||
1422                keysDown[8] || keysDown[9] || config.autoRotate ||
1423                animatedMove.pitch || animatedMove.yaw || animatedMove.hfov ||
1424                Math.abs(speed.yaw) > 0.01 || Math.abs(speed.pitch) > 0.01 ||
1425                Math.abs(speed.hfov) > 0.01) {
1426
1427                keyRepeat();
1428                if (config.autoRotateInactivityDelay >= 0 && autoRotateSpeed &&
1429                    Date.now() - latestInteraction > config.autoRotateInactivityDelay &&
1430                    !config.autoRotate) {
1431                    config.autoRotate = autoRotateSpeed;
1432                    _this.lookAt(origPitch, undefined, origHfov, 3000);
1433                }
1434                requestAnimationFrame(animate);
1435            } else if (renderer && (renderer.isLoading() || (config.dynamic === true && update))) {
1436                requestAnimationFrame(animate);
1437            } else {
1438                fireEvent('animatefinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()});
1439                animating = false;
vendor: 14,108 bytes, lines 1440-1763
1440                prevTime = undefined;
1441                var autoRotateStartTime = config.autoRotateInactivityDelay -
1442                    (Date.now() - latestInteraction);
1443                if (autoRotateStartTime > 0) {
1444                    autoRotateStart = setTimeout(function() {
1445                        config.autoRotate = autoRotateSpeed;
1446                        _this.lookAt(origPitch, undefined, origHfov, 3000);
1447                        animateInit();
1448                    }, autoRotateStartTime);
1449                } else if (config.autoRotateInactivityDelay >= 0 && autoRotateSpeed) {
1450                    config.autoRotate = autoRotateSpeed;
1451                    _this.lookAt(origPitch, undefined, origHfov, 3000);
1452                    animateInit();
1453                }
1454            }
1455        }
1456
1457        /**
1458         * Renders panorama view.
1459         * @private
1460         */
1461        function render() {
1462            var tmpyaw;
1463
1464            if (loaded) {
1465                var canvas = renderer.getCanvas();
1466
1467                if (config.autoRotate !== false) {
1468                    // When auto-rotating this check needs to happen first (see issue #764)
1469                    if (config.yaw > 360) {
1470                        config.yaw -= 360;
1471                    } else if (config.yaw < -360) {
1472                        config.yaw += 360;
1473                    }
1474                }
1475
1476                // Keep a tmp value of yaw for autoRotate comparison later
1477                tmpyaw = config.yaw;
1478
1479                // Optionally avoid showing background (empty space) on left or right by adapting min/max yaw
1480                var hoffcut = 0,
1481                    voffcut = 0;
1482                if (config.avoidShowingBackground) {
1483                    var hfov2 = config.hfov / 2,
1484                        vfov2 = Math.atan2(Math.tan(hfov2 / 180 * Math.PI), (canvas.width / canvas.height)) * 180 / Math.PI,
1485                        transposed = config.vaov > config.haov;
1486                    if (transposed) {
1487                        voffcut = vfov2 * (1 - Math.min(Math.cos((config.pitch - hfov2) / 180 * Math.PI),
1488                            Math.cos((config.pitch + hfov2) / 180 * Math.PI)));
1489                    } else {
1490                        hoffcut = hfov2 * (1 - Math.min(Math.cos((config.pitch - vfov2) / 180 * Math.PI),
1491                            Math.cos((config.pitch + vfov2) / 180 * Math.PI)));
1492                    }
1493                }
1494
1495                // Ensure the yaw is within min and max allowed
1496                var yawRange = config.maxYaw - config.minYaw,
1497                    minYaw = -180,
1498                    maxYaw = 180;
1499                if (yawRange < 360) {
1500                    minYaw = config.minYaw + config.hfov / 2 + hoffcut;
1501                    maxYaw = config.maxYaw - config.hfov / 2 - hoffcut;
1502                    if (yawRange < config.hfov) {
1503                        // Lock yaw to average of min and max yaw when both can be seen at once
1504                        minYaw = maxYaw = (minYaw + maxYaw) / 2;
1505                    }
1506                    config.yaw = Math.max(minYaw, Math.min(maxYaw, config.yaw));
1507                }
1508
1509                if (!(config.autoRotate !== false)) {
1510                    // When not auto-rotating, this check needs to happen after the
1511                    // previous check (see issue #698)
1512                    if (config.yaw > 360) {
1513                        config.yaw -= 360;
1514                    } else if (config.yaw < -360) {
1515                        config.yaw += 360;
1516                    }
1517                }
1518
1519                // Check if we autoRotate in a limited by min and max yaw
1520                // If so reverse direction
1521                if (config.autoRotate !== false && tmpyaw != config.yaw &&
1522                    prevTime !== undefined) { // this condition prevents changing the direction initially
1523                    config.autoRotate *= -1;
1524                }
1525
1526                // Ensure the calculated pitch is within min and max allowed
1527                var vfov = 2 * Math.atan(Math.tan(config.hfov / 180 * Math.PI * 0.5) /
1528                    (canvas.width / canvas.height)) / Math.PI * 180;
1529                var minPitch = config.minPitch + vfov / 2,
1530                    maxPitch = config.maxPitch - vfov / 2;
1531                var pitchRange = config.maxPitch - config.minPitch;
1532                if (pitchRange < vfov) {
1533                    // Lock pitch to average of min and max pitch when both can be seen at once
1534                    minPitch = maxPitch = (minPitch + maxPitch) / 2;
1535                }
1536                if (isNaN(minPitch))
1537                    minPitch = -90;
1538                if (isNaN(maxPitch))
1539                    maxPitch = 90;
1540                config.pitch = Math.max(minPitch, Math.min(maxPitch, config.pitch));
1541
1542                renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {roll: config.roll * Math.PI / 180});
1543
1544                renderHotSpots();
1545
1546                // Update compass
1547                //compass data fired by sakib
1548                // const node = document.getElementsByClassName('add-pulse')[0];
1549                // if(node) {
1550                //     node.style.transform = 'rotate(' + (-config.yaw - config.northOffset) + 'deg)';
1551                // }
1552                if (config.compass) {
1553                    compass.style.transform = 'rotate(' + (-config.yaw - config.northOffset) + 'deg)';
1554                    compass.style.webkitTransform = 'rotate(' + (-config.yaw - config.northOffset) + 'deg)';
1555                }
1556            }
1557        }
1558
1559        /**
1560         * Creates a new quaternion.
1561         * @private
1562         * @constructor
1563         * @param {Number} w - W value
1564         * @param {Number} x - X value
1565         * @param {Number} y - Y value
1566         * @param {Number} z - Z value
1567         */
1568        function Quaternion(w, x, y, z) {
1569            this.w = w;
1570            this.x = x;
1571            this.y = y;
1572            this.z = z;
1573        }
1574
1575        /**
1576         * Multiplies quaternions.
1577         * @private
1578         * @param {Quaternion} q - Quaternion to multiply
1579         * @returns {Quaternion} Result of multiplication
1580         */
1581        Quaternion.prototype.multiply = function(q) {
1582            return new Quaternion(this.w*q.w - this.x*q.x - this.y*q.y - this.z*q.z,
1583                this.x*q.w + this.w*q.x + this.y*q.z - this.z*q.y,
1584                this.y*q.w + this.w*q.y + this.z*q.x - this.x*q.z,
1585                this.z*q.w + this.w*q.z + this.x*q.y - this.y*q.x);
1586        };
1587
1588        /**
1589         * Converts quaternion to Euler angles.
1590         * @private
1591         * @returns {Number[]} [phi angle, theta angle, psi angle]
1592         */
1593        Quaternion.prototype.toEulerAngles = function() {
1594            var phi = Math.atan2(2 * (this.w * this.x + this.y * this.z),
1595                    1 - 2 * (this.x * this.x + this.y * this.y)),
1596                theta = Math.asin(2 * (this.w * this.y - this.z * this.x)),
1597                psi = Math.atan2(2 * (this.w * this.z + this.x * this.y),
1598                    1 - 2 * (this.y * this.y + this.z * this.z));
1599            return [phi, theta, psi];
1600        };
1601
1602        /**
1603         * Converts device orientation API Tait-Bryan angles to a quaternion.
1604         * @private
1605         * @param {Number} alpha - Alpha angle (in degrees)
1606         * @param {Number} beta - Beta angle (in degrees)
1607         * @param {Number} gamma - Gamma angle (in degrees)
1608         * @returns {Quaternion} Orientation quaternion
1609         */
1610        function taitBryanToQuaternion(alpha, beta, gamma) {
1611            var r = [beta ? beta * Math.PI / 180 / 2 : 0,
1612                gamma ? gamma * Math.PI / 180 / 2 : 0,
1613                alpha ? alpha * Math.PI / 180 / 2 : 0];
1614            var c = [Math.cos(r[0]), Math.cos(r[1]), Math.cos(r[2])],
1615                s = [Math.sin(r[0]), Math.sin(r[1]), Math.sin(r[2])];
1616
1617            return new Quaternion(c[0]*c[1]*c[2] - s[0]*s[1]*s[2],
1618                s[0]*c[1]*c[2] - c[0]*s[1]*s[2],
1619                c[0]*s[1]*c[2] + s[0]*c[1]*s[2],
1620                c[0]*c[1]*s[2] + s[0]*s[1]*c[2]);
1621        }
1622
1623        /**
1624         * Computes current device orientation quaternion from device orientation API
1625         * Tait-Bryan angles.
1626         * @private
1627         * @param {Number} alpha - Alpha angle (in degrees)
1628         * @param {Number} beta - Beta angle (in degrees)
1629         * @param {Number} gamma - Gamma angle (in degrees)
1630         * @returns {Quaternion} Orientation quaternion
1631         */
1632        function computeQuaternion(alpha, beta, gamma) {
1633            // Convert Tait-Bryan angles to quaternion
1634            var quaternion = taitBryanToQuaternion(alpha, beta, gamma);
1635            // Apply world transform
1636            quaternion = quaternion.multiply(new Quaternion(Math.sqrt(0.5), -Math.sqrt(0.5), 0, 0));
1637            // Apply screen transform
1638            var angle = window.orientation ? -window.orientation * Math.PI / 180 / 2 : 0;
1639            return quaternion.multiply(new Quaternion(Math.cos(angle), 0, -Math.sin(angle), 0));
1640        }
1641
1642        /**
1643         * Event handler for device orientation API. Controls pointing.
1644         * @private
1645         * @param {DeviceOrientationEvent} event - Device orientation event.
1646         */
1647        function orientationListener(e) {
1648            var q = computeQuaternion(e.alpha, e.beta, e.gamma).toEulerAngles();
1649            if (typeof(orientation) == 'number' && orientation < 10) {
1650                // This kludge is necessary because iOS sometimes provides a few stale
1651                // device orientation events when the listener is removed and then
1652                // readded. Thus, we skip the first 10 events to prevent this from
1653                // causing problems.
1654                orientation += 1;
1655            } else if (orientation === 10) {
1656                // Record starting yaw to prevent jumping
1657                orientationYawOffset = q[2] / Math.PI * 180 + config.yaw;
1658                orientation = true;
1659                requestAnimationFrame(animate);
1660            } else {
1661                config.pitch = q[0] / Math.PI * 180;
1662                config.roll = -q[1] / Math.PI * 180;
1663                config.yaw = -q[2] / Math.PI * 180 + orientationYawOffset;
1664            }
1665        }
1666
1667        /**
1668         * Initializes renderer.
1669         * @private
1670         */
1671        function renderInit() {
1672            try {
1673                var params = {};
1674                if (config.horizonPitch !== undefined)
1675                    params.horizonPitch = config.horizonPitch * Math.PI / 180;
1676                if (config.horizonRoll !== undefined)
1677                    params.horizonRoll = config.horizonRoll * Math.PI / 180;
1678                if (config.backgroundColor !== undefined)
1679                    params.backgroundColor = config.backgroundColor;
1680                renderer.init(panoImage, config.type, config.dynamic, config.haov * Math.PI / 180, config.vaov * Math.PI / 180, config.vOffset * Math.PI / 180, renderInitCallback, params);
1681                if (config.dynamic !== true) {
1682                    // Allow image to be garbage collected
1683                    panoImage = undefined;
1684                }
1685            } catch(event) {
1686                // Panorama not loaded
1687
1688                // Display error if there is a bad texture
1689                if (event.type == 'webgl error' || event.type == 'no webgl') {
1690                    anError();
1691                } else if (event.type == 'webgl size error') {
1692                    anError(config.strings.textureSizeError.replace('%s', event.width).replace('%s', event.maxWidth));
1693                } else {
1694                    anError(config.strings.unknownError);
1695                    throw event;
1696                }
1697            }
1698        }
1699
1700        /**
1701         * Triggered when render initialization finishes. Handles fading between
1702         * scenes as well as showing the compass and hotspots and hiding the loading
1703         * display.
1704         * @private
1705         */
1706        function renderInitCallback() {
1707            // Fade if specified
1708            if (config.sceneFadeDuration && renderer.fadeImg !== undefined) {
1709                renderer.fadeImg.style.opacity = 0;
1710                // Remove image
1711                var fadeImg = renderer.fadeImg;
1712                delete renderer.fadeImg;
1713                setTimeout(function() {
1714                    renderContainer.removeChild(fadeImg);
1715                    fireEvent('scenechangefadedone');
1716                }, config.sceneFadeDuration);
1717            }
1718
1719            // Show compass if applicable
1720            if (config.compass) {
1721                compass.style.display = 'inline';
1722            } else {
1723                compass.style.display = 'none';
1724            }
1725
1726            // Show hotspots
1727            createHotSpots();
1728
1729            // Hide loading display
1730            infoDisplay.load.box.style.display = 'none';
1731            if (preview !== undefined) {
1732                renderContainer.removeChild(preview);
1733                preview = undefined;
1734            }
1735            loaded = true;
1736
1737            animateInit();
1738
1739            fireEvent('load');
1740        }
1741
1742        /**
1743         * Creates hot spot element for the current scene.
1744         * @private
1745         * @param {Object} hs - The configuration for the hotspot
1746         */
1747        function createHotSpot(hs) {
1748            // Make sure hot spot pitch and yaw are numbers
1749            hs.pitch = Number(hs.pitch) || 0;
1750            hs.yaw = Number(hs.yaw) || 0;
1751
1752            var div = document.createElement('div');
1753            div.className = 'pnlm-hotspot-base';
1754            if (hs.cssClass)
1755                div.className += ' ' + hs.cssClass;
1756            else
1757                div.className += ' pnlm-hotspot pnlm-sprite pnlm-' + escapeHTML(hs.type);
1758
1759            //Shahin - customized hotspot dom for Hexagon shape
1760            if(hs.hotspot_shape === 'hexagon'){
1761                var hotspotShape = document.createElement('div');
1762                hotspotShape.className = 'hexagon-wrapper';
1763                const hexagonShapeIcon = '<svg fill="none" width="30" height="25" viewB
1763ox="0 0 40 35" xmlns="http://www.w3.org/2000/svg"><path fill="#00b4ff" d="M0 17.32L10 0h20l10 17.32-10 17.321H10L0 17.321z"/></svg>';
1764                hotspotShape.innerHTML = hexagonShapeIcon;
1765                div.appendChild(hotspotShape);
1766            }
1767            //Sakib - customized hotspot dom for vr mode
1768            var title = document.createElement('span');
1769            title.className = 'vr-mode-title';
1770            if (hs.sceneId)
1771                title.innerHTML = escapeHTML(hs.sceneId);
1772            //Sakib - customized hotspot dom for vr mode end
1773
1774            var span = document.createElement('span');
1775            if (hs.text)
1776                span.innerHTML = escapeHTML(hs.text);
1777
1778            var a;
1779            if (hs.video) {
1780                var video = document.createElement('video'),
1781                    vidp = hs.video;
1782                if (config.basePath && !absoluteURL(vidp))
1783                    vidp = config.basePath + vidp;
1784                video.src = sanitizeURL(vidp);
1785                video.controls = true;
1786                video.style.width = hs.width + 'px';
1787                renderContainer.appendChild(div);
1788                span.appendChild(video);
1789            } else if (hs.image) {
1790                var imgp = hs.image;
1791                if (config.basePath && !absoluteURL(imgp))
1792                    imgp = config.basePath + imgp;
1793                a = document.createElement('a');
1794                a.href = sanitizeURL(hs.URL ? hs.URL : imgp, true);
1795                a.target = '_blank';
1796                span.appendChild(a);
1797                var image = document.createElement('img');
1798                image.src = sanitizeURL(imgp);
1799                image.style.width = hs.width + 'px';
1800                image.style.paddingTop = '5px';
1801                renderContainer.appendChild(div);
1802                a.appendChild(image);
1803                span.style.maxWidth = 'initial';
1804            } else if (hs.URL) {
1805                a = document.createElement('a');
1806                a.href = sanitizeURL(hs.URL, true);
1807                if (hs.attributes) {
1808                    for (var key in hs.attributes) {
1809                        a.setAttribute(key, hs.attributes[key]);
1810                    }
1811                } else {
1812                    //wpvr edit by sakib for in tab url open// -- handling from here
1813                    if (hs.wpvr_url_open == 'on') {
1814                        a.target = '_self';
1815                    }
1816                    else {
1817                        a.target = '_blank';
1818                    }
1819                }
1820                renderContainer.appendChild(a);
1821                div.className += ' pnlm-pointer';
1822                span.className += ' pnlm-pointer';
1823                a.appendChild(div);
1824            } else {
1825                if (hs.sceneId) {
1826                    div.onclick = div.ontouchend = function() {
1827                        if (!div.clicked) {
1828                            div.clicked = true;
1829                            loadScene(hs.sceneId, hs.targetPitch, hs.targetYaw, hs.targetHfov);
1830                        }
1831                        return false;
1832                    };
1833                    div.className += ' pnlm-pointer';
1834                    span.className += ' pnlm-pointer';
1835                }
1836
1837                if (hs.sceneId)
1838                    div.appendChild(title);
1839
1840                renderContainer.appendChild(div);
1841            }
1842
1843            if (hs.createTooltipFunc) {
1844                hs.createTooltipFunc(div, hs.createTooltipArgs);
1845            } else if (hs.text || hs.video || hs.image) {
1846                div.classList.add('pnlm-tooltip');
1847                div.appendChild(span);
1848                span.style.width = span.scrollWidth - 20 + 'px';
1849                span.style.marginLeft = -(span.scrollWidth - div.offsetWidth) / 2 + 'px';
1850                span.style.marginTop = -span.scrollHeight - 12 + 'px';
1851            }
1852            if (hs.clickHandlerFunc) {
1853                div.addEventListener('click', function(e) {
1854                    hs.clickHandlerFunc(e, hs.clickHandlerArgs);
1855                }, 'false');
1856                div.className += ' pnlm-pointer';
1857                span.className += ' pnlm-pointer';
1858            }
1859            hs.div = div;
1860        }
1861
1862        /**
1863         * Creates hot spot elements for the current scene.
1864         * @private
1865         */
1866        function createHotSpots() {
1867            if (hotspotsCreated) return;
1868
1869            if (!config.hotSpots) {
1870                config.hotSpots = [];
1871            } else {
1872                // Sort by pitch so tooltip is never obscured by another hot spot
1873                config.hotSpots = config.hotSpots.sort(function(a, b) {
1874                    return a.pitch < b.pitch;
1875                });
1876                config.hotSpots.forEach(createHotSpot);
1877            }
1878            hotspotsCreated = true;
1879            renderHotSpots();
1880        }
1881
1882        /**
1883         * Destroys currently created hot spot elements.
1884         * @private
1885         */
1886        function destroyHotSpots() {
1887            var hs = config.hotSpots;
1888            hotspotsCreated = false;
1889            delete config.hotSpots;
1890            if (hs) {
1891                for (var i = 0; i < hs.length; i++) {
1892                    var current = hs[i].div;
1893                    if (current) {
1894                        while (current.parentNode && current.parentNode != renderContainer) {
1895                            current = current.parentNode;
1896                        }
1897                        renderContainer.removeChild(current);
1898                    }
1899                    delete hs[i].div;
1900                }
1901            }
1902        }
1903
1904        /**
1905         * Renders hot spot, updating its position and visibility.
1906         * @private
1907         */
1908        function renderHotSpot(hs) {
1909            var hsPitchSin = Math.sin(hs.pitch * Math.PI / 180),
1910                hsPitchCos = Math.cos(hs.pitch * Math.PI / 180),
1911                configPitchSin = Math.sin(config.pitch * Math.PI / 180),
1912                configPitchCos = Math.cos(config.pitch * Math.PI / 180),
1913                yawCos = Math.cos((-hs.yaw + config.yaw) * Math.PI / 180);
1914            var z = hsPitchSin * configPitchSin + hsPitchCos * yawCos * configPitchCos;
1915            if ((hs.yaw <= 90 && hs.yaw > -90 && z <= 0) ||
1916                ((hs.yaw > 90 || hs.yaw <= -90) && z <= 0)) {
1917                hs.div.style.visibility = 'hidden';
1918            } else {
1919                var yawSin = Math.sin((-hs.yaw + config.yaw) * Math.PI / 180),
1920                    hfovTan = Math.tan(config.hfov * Math.PI / 360);
1921                hs.div.style.visibility = 'visible';
1922                // Subpixel rendering doesn't work in Firefox
1923                // https://bugzilla.mozilla.org/show_bug.cgi?id=739176
1924                var canvas = renderer.getCanvas(),
1925                    canvasWidth = canvas.clientWidth,
1926                    canvasHeight = canvas.clientHeight;
1927                var coord = [-canvasWidth / hfovTan * yawSin * hsPitchCos / z / 2,
1928                    -canvasWidth / hfovTan * (hsPitchSin * configPitchCos -
1929                        hsPitchCos * yawCos * configPitchSin) / z / 2];
1930                // Apply roll
1931                var rollSin = Math.sin(config.roll * Math.PI / 180),
1932                    rollCos = Math.cos(config.roll * Math.PI / 180);
1933                coord = [coord[0] * rollCos - coord[1] * rollSin,
1934                    coord[0] * rollSin + coord[1] * rollCos];
1935                // Apply transform
1936                coord[0] += (canvasWidth - hs.div.offsetWidth) / 2;
1937                coord[1] += (canvasHeight - hs.div.offsetHeight) / 2;
1938                var transform = 'translate(' + coord[0] + 'px, ' + coord[1] +
1939                    'px) translateZ(9999px) rotate(' + config.roll + 'deg)';
1940                if (hs.scale) {
1941                    transform += ' scale(' + (origHfov/config.hfov) / z + ')';
1942                }
1943                hs.div.style.webkitTransform = transform;
1944                hs.div.style.MozTransform = transform;
1945                hs.div.style.transform = transform;
1946            }
1947        }
1948
1949        /**
1950         * Renders hot spots, updating their positions and visibility.
1951         * @private
1952         */
1953        function renderHotSpots() {
1954            config.hotSpots.forEach(renderHotSpot);
1955        }
1956
1957        /**
1958         * Merges a scene configuration into the current configuration.
1959         * @private
1960         * @param {string} sceneId - Identifier of scene configuration to merge in.
1961         */
1962        function mergeConfig(sceneId) {
1963            config = {};
1964            var k, s;
1965            var photoSphereExcludes = ['haov', 'vaov', 'vOffset', 'northOffset', 'horizonPitch', 'horizonRoll'];
1966            specifiedPhotoSphereExcludes = [];
1967
1968            // Merge default config
1969            for (k in defaultConfig) {
1970                if (defaultConfig.hasOwnProperty(k)) {
1971                    config[k] = defaultConfig[k];
1972                }
1973            }
1974
1975            // Merge default scene config
1976            for (k in initialConfig.default) {
1977                if (initialConfig.default.hasOwnProperty(k)) {
1978                    if (k == 'strings') {
1979                        for (s in initialConfig.default.strings) {
1980                            if (initialConfig.default.strings.hasOwnProperty(s)) {
1981                                config.strings[s] = escapeHTML(initialConfig.default.strings[s]);
1982                            }
1983                        }
1984                    } else {
1985                        config[k] = initialConfig.default[k];
1986                        if (photoSphereExcludes.indexOf(k) >= 0) {
1987                            specifiedPhotoSphereExcludes.push(k);
1988                        }
1989                    }
1990                }
1991            }
1992
1993            // Merge current scene config
1994            if ((sceneId !== null) && (sceneId !== '') && (initialConfig.scenes) && (initialConfig.scenes[sceneId])) {
1995                var scene = initialConfig.scenes[sceneId];
1996                for (k in scene) {
1997                    if (scene.hasOwnProperty(k)) {
1998                        if (k == 'strings') {
1999                            for (s in scene.strings) {
2000                                if (scene.strings.hasOwnProperty(s)) {
2001                                    config.strings[s] = escapeHTML(scene.strings[s]);
2002                                }
2003                            }
2004                        } else {
2005                            config[k] = scene[k];
2006                            if (photoSphereExcludes.indexOf(k) >= 0) {
2007                                specifiedPhotoSphereExcludes.push(k);
2008                            }
2009                        }
2010                    }
2011                }
2012                config.scene = sceneId;
2013            }
2014
2015            // Merge initial config
2016            for (k in initialConfig) {
2017                if (initialConfig.hasOwnProperty(k)) {
2018                    if (k == 'strings') {
2019                        for (s in initialConfig.strings) {
2020                            if (initialConfig.strings.hasOwnProperty(s)) {
2021                                config.strings[s] = escapeHTML(initialConfig.strings[s]);
2022                            }
2023                        }
2024                    } else {
2025                        config[k] = initialConfig[k];
2026                        if (photoSphereExcludes.indexOf(k) >= 0) {
2027                            specifiedPhotoSphereExcludes.push(k);
2028                        }
2029                    }
2030                }
2031            }
2032        }
2033
2034        /**
2035         * Processes configuration options.
2036         * @param {boolean} [isPreview] - Whether or not the preview is being displayed
2037         * @private
2038         */
2039        function processOptions(isPreview) {
2040            isPreview = isPreview ? isPreview : false;
2041
2042            // Process preview first so it always loads before the browser hits its
2043            // maximum number of connections to a server as can happen with cubic
2044            // panoramas
2045            if (isPreview && 'preview' in config) {
2046                var p = config.preview;
2047                if (config.basePath && !absoluteURL(p))
2048                    p = config.basePath + p;
2049                preview = document.createElement('div');
2050                preview.className = 'pnlm-preview-img';
2051                preview.style.backgroundImage = "url('" + sanitizeURLForCss(p) + "')";
2052                renderContainer.appendChild(preview);
2053            }
2054
2055            // Handle different preview values
2056            var title = config.title,
2057                author = config.author;
2058            if (isPreview) {
2059                if ('previewTitle' in config)
2060                    config.title = config.previewTitle;
2061                if ('previewAuthor' in config)
2062                    config.author = config.previewAuthor;
2063            }
2064
2065            // Reset title / author display
2066            if (!config.hasOwnProperty('title'))
2067                infoDisplay.title.innerHTML = '';
2068            if (!config.hasOwnProperty('author'))
2069                infoDisplay.author.innerHTML = '';
2070            if (!config.hasOwnProperty('title') && !config.hasOwnProperty('author'))
2071                infoDisplay.container.style.display = 'none';
2072
2073            // Fill in load button label and loading box text
2074            controls.load.innerHTML = '<p>' + config.strings.loadButtonLabel + '</p>';
2075            infoDisplay.load.boxp.innerHTML = config.strings.loadingLabel;
2076
2077            // Process other options
2078            for (var key in config) {
2079                if (config.hasOwnProperty(key)) {
2080                    switch(key) {
2081                        case 'title':
2082                            infoDisplay.title.innerHTML = escapeHTML(config[key]);
2083                            infoDisplay.container.style.display = 'inline';
2084                            break;
2085
2086                        case 'author':
2087                            var authorText = escapeHTML(config[key]);
2088                            if (config.authorURL) {
2089                                var authorLink = document.createElement('a');
2090                                authorLink.href = sanitizeURL(config['authorURL'], true);
2091                                authorLink.target = '_blank';
2092                                authorLink.innerHTML = escapeHTML(config[key]);
2093                                authorText = authorLink.outerHTML;
2094                            }
2095                            infoDisplay.author.innerHTML = config.strings.bylineLabel.replace('%s', authorText);
2096                            infoDisplay.container.style.display = 'inline';
2097                            break;
2098
2099                        case 'fallback':
2100                            var link = document.createElement('a');
2101                            link.href = sanitizeURL(config[key], true);
2102                            link.target = '_blank';
2103                            link.textContent = 'Click here to view this panorama in an alternative viewer.';
2104                            var message = document.createElement('p');
2105                            message.textContent = 'Your browser does not support WebGL.';
2106                            message.appendChild(document.createElement('br'));
2107                            message.appendChild(link);
2108                            infoDisplay.errorMsg.innerHTML = ''; // Removes all children nodes
2109                            infoDisplay.errorMsg.appendChild(message);
2110                            break;
2111
2112                        case 'hfov':
2113                            setHfov(Number(config[key]));
2114                            break;
2115
2116                        case 'autoLoad':
2117                            if (config[key] === true && renderer === undefined) {
2118                                // Show loading box
2119                                infoDisplay.load.box.style.display = 'inline';
2120                                // Hide load button
2121                                controls.load.style.display = 'none';
2122                                // Initialize
2123                                init();
2124                            }
2125                            break;
2126
2127                        case 'showZoomCtrl':
2128                            if (config[key] && config.showControls != false) {
2129                                // Show zoom controls
2130                                controls.zoom.style.display = 'block';
2131                            } else {
2132                                // Hide zoom controls
2133                                controls.zoom.style.display = 'none';
2134                            }
2135                            break;
2136
2137                        case 'showFullscreenCtrl':
2138                            if (config[key] && config.showControls != false && ('fullscreen' in document || 'mozFullScreen' in document ||
2139                                'webkitIsFullScreen' in document || 'msFullscreenElement' in document)) {
2140
2141                                // Show fullscreen control
2142                                controls.fullscreen.style.display = 'block';
2143                            } else {
2144                                // Hide fullscreen control
2145                                controls.fullscreen.style.display = 'none';
2146                            }
2147                            break;
2148
2149                        case 'hotSpotDebug':
2150                            if (config[key])
2151                                hotSpotDebugIndicator.style.display = 'block';
2152                            else
2153                                hotSpotDebugIndicator.style.display = 'none';
2154                            break;
2155
2156                        case 'showControls':
2157                            if (!config[key]) {
2158                                controls.orientation.style.display = 'none';
2159                                controls.zoom.style.display = 'none';
2160                                controls.fullscreen.style.display = 'none';
2161                            }
2162                            break;
2163
2164                        case 'orientationOnByDefault':
2165                            if (config[key])
2166                                startOrientation();
2167                            break;
2168                    }
2169                }
2170            }
2171
2172            if (isPreview) {
2173                // Restore original values if changed for preview
2174                if (title)
2175                    config.title = title;
2176                else
2177                    delete config.title;
2178                if (author)
2179                    config.author = author;
2180                else
2181                    delete config.author;
2182            }
2183        }
2184
2185        /**
2186         * Toggles fullscreen mode.
2187         * @private
2188         */
2189        function toggleFullscreen() {
2190            if (loaded && !error) {
2191                if (!fullscreenActive) {
2192                    try {
2193                        if (container.requestFullscreen) {
2194                            container.requestFullscreen();
2195                        } else if (container.mozRequestFullScreen) {
2196                            container.mozRequestFullScreen();
2197                        } else if (container.msRequestFullscreen) {
2198                            container.msRequestFullscreen();
2199                        } else {
2200                            container.webkitRequestFullScreen();
2201                        }
2202                    } catch(event) {
2203                        // Fullscreen doesn't work
2204                    }
2205                } else {
2206                    if (document.exitFullscreen) {
2207                        document.exitFullscreen();
2208                    } else if (document.mozCancelFullScreen) {
2209                        document.mozCancelFullScreen();
2210                    } else if (document.webkitCancelFullScreen) {
2211                        document.webkitCancelFullScreen();
2212                    } else if (document.msExitFullscreen) {
2213                        document.msExitFullscreen();
2214                    }
2215                }
2216            }
2217        }
2218
2219        /**
2220         * Event handler for fullscreen changes.
2221         * @private
2222         */
2223        function onFullScreenChange(resize) {
2224            if (document.fullscreenElement || document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement) {
2225                controls.fullscreen.classList.add('pnlm-fullscreen-toggle-button-active');
2226                fullscreenActive = true;
2227            } else {
2228                controls.fullscreen.classList.remove('pnlm-fullscreen-toggle-button-active');
2229                fullscreenActive = false;
vendor: 4,274 bytes, lines 2230-2344
2230            }
2231            if (resize !== 'resize')
2232                fireEvent('fullscreenchange', fullscreenActive);
2233            // Resize renderer (deal with browser quirks and fixes #155)
2234            renderer.resize();
2235            setHfov(config.hfov);
2236            animateInit();
2237        }
2238
2239        /**
2240         * Increases panorama zoom. For use with zoom button.
2241         * @private
2242         */
2243        function zoomIn() {
2244            if (loaded) {
2245                setHfov(config.hfov - 5);
2246                animateInit();
2247            }
2248        }
2249
2250        /**
2251         * Decreases panorama zoom. For use with zoom button.
2252         * @private
2253         */
2254        function zoomOut() {
2255            if (loaded) {
2256                setHfov(config.hfov + 5);
2257                animateInit();
2258            }
2259        }
2260
2261        /**
2262         * Clamps horzontal field of view to viewer's limits.
2263         * @private
2264         * @param {number} hfov - Input horizontal field of view (in degrees)
2265         * @return {number} - Clamped horizontal field of view (in degrees)
2266         */
2267        function constrainHfov(hfov) {
2268            // Keep field of view within bounds
2269            var minHfov = config.minHfov;
2270            if (config.type == 'multires' && renderer && !config.multiResMinHfov) {
2271                minHfov = Math.min(minHfov, renderer.getCanvas().width / (config.multiRes.cubeResolution / 90 * 0.9));
2272            }
2273            if (minHfov > config.maxHfov) {
2274                // Don't change view if bounds don't make sense
2275                console.log('HFOV bounds do not make sense (minHfov > maxHfov).');
2276                return config.hfov;
2277            }
2278            var newHfov = config.hfov;
2279            if (hfov < minHfov) {
2280                newHfov = minHfov;
2281            } else if (hfov > config.maxHfov) {
2282                newHfov = config.maxHfov;
2283            } else {
2284                newHfov = hfov;
2285            }
2286            // Optionally avoid showing background (empty space) on top or bottom by adapting newHfov
2287            if (config.avoidShowingBackground && renderer) {
2288                var canvas = renderer.getCanvas();
2289                newHfov = Math.min(newHfov,
2290                    Math.atan(Math.tan((config.maxPitch - config.minPitch) / 360 * Math.PI) /
2291                        canvas.height * canvas.width) * 360 / Math.PI);
2292            }
2293            return newHfov;
2294        }
2295
2296        /**
2297         * Sets viewer's horizontal field of view.
2298         * @private
2299         * @param {number} hfov - Desired horizontal field of view in degrees.
2300         */
2301        function setHfov(hfov) {
2302            config.hfov = constrainHfov(hfov);
2303            fireEvent('zoomchange', config.hfov);
2304        }
2305
2306        /**
2307         * Stops auto rotation and animated moves.
2308         * @private
2309         */
2310        function stopAnimation() {
2311            animatedMove = {};
2312            autoRotateSpeed = config.autoRotate ? config.autoRotate : autoRotateSpeed;
2313            config.autoRotate = false;
2314        }
2315
2316        /**
2317         * Loads panorama.
2318         * @private
2319         */
2320        function load() {
2321            // Since WebGL error handling is very general, first we clear any error box
2322            // since it is a new scene and the error from previous maybe because of lacking
2323            // memory etc and not because of a lack of WebGL support etc
2324            clearError();
2325            loaded = false;
2326
2327            controls.load.style.display = 'none';
2328            infoDisplay.load.box.style.display = 'inline';
2329            init();
2330        }
2331
2332        /**
2333         * Loads scene.
2334         * @private
2335         * @param {string} sceneId - Identifier of scene configuration to merge in.
2336         * @param {number} targetPitch - Pitch viewer should be centered on once scene loads.
2337         * @param {number} targetYaw - Yaw viewer should be centered on once scene loads.
2338         * @param {number} targetHfov - HFOV viewer should use once scene loads.
2339         * @param {boolean} [fadeDone] - If `true`, fade setup is skipped.
2340         */
2341        function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) {
2342            if (!loaded)
2343                fadeDone = true;    // Don't try to fade when there isn't a scene loaded
2344            loaded = false;
2345            animatedMove = {};
2346
2347            // Set up fade if specified
2348            var fadeImg, workingPitch, workingYaw, workingHfov;
2349            if (config.sceneFadeDuration && !fadeDone) {
2350                var data = renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {returnImage: true});
2351                if (data !== undefined) {
2352                    fadeImg = new Image();
2353                    fadeImg.className = 'pnlm-fade-img';
2354                    fadeImg.style.transition = 'opacity ' + (config.sceneFadeDuration / 1000) + 's';
2355                    fadeImg.style.width = '100%';
2356                    fadeImg.style.height = '100%';
2357                    fadeImg.onload = function() {
2358                        loadScene(sceneId, targetPitch, targetYaw, targetHfov, true);
2359                    };
2360                    fadeImg.src = data;
2361                    renderContainer.appendChild(fadeImg);
2362                    renderer.fadeImg = fadeImg;
2363                    return;
2364                }
2365            }
2366
2367            // Set new pointing
2368            if (targetPitch === 'same') {
2369                workingPitch = config.pitch;
2370            } else {
2371                workingPitch = targetPitch;
2372            }
2373            if (targetYaw === 'same') {
2374                workingYaw = config.yaw;
2375            } else if (targetYaw === 'sameAzimuth') {
2376                workingYaw = config.yaw + (config.northOffset || 0) - (initialConfig.scenes[sceneId].northOffset || 0);
2377            } else {
2378                workingYaw = targetYaw;
2379            }
2380            if (targetHfov === 'same') {
2381                workingHfov = config.hfov;
2382            } else {
2383                workingHfov = targetHfov;
2384            }
2385
2386            // Destroy hot spots from previous scene
2387            destroyHotSpots();
2388
2389            // Create the new config for the scene
2390            mergeConfig(sceneId);
2391
2392            // Stop motion
2393            speed.yaw = speed.pitch = speed.hfov = 0;
2394
2395            // Reload scene
2396            processOptions();
2397            if (workingPitch !== undefined) {
2398                config.pitch = workingPitch;
2399            }
2400            if (workingYaw !== undefined) {
2401                config.yaw = workingYaw;
2402            }
2403            if (workingHfov !== undefined) {
2404                config.hfov = workingHfov;
2405            }
2406            fireEvent('scenechange', sceneId);
2407            load();
2408        }
2409
2410        /**
2411         * Stop using device orientation.
2412         * @private
2413         */
2414        function stopOrientation() {
2415            window.removeEventListener('deviceorientation', orientationListener);
2416            controls.orientation.classList.remove('pnlm-orientation-button-active');
2417            orientation = false;
2418        }
2419
2420        /**
2421         * Start using device orientation.
2422         * @private
2423         */
2424        function startOrientation() {
2425            if (!orientationSupport)
2426                return;
2427            if (typeof DeviceMotionEvent !== 'undefined' &&
2428                typeof DeviceMotionEvent.requestPermission === 'function') {
2429                DeviceOrientationEvent.requestPermission().then(function(response) {
2430                    if (response == 'granted') {
2431                        orientation = 1;
2432                        window.addEventListener('deviceorientation', orientationListener);
2433                        controls.orientation.classList.add('pnlm-orientation-button-active');
2434                    }
2435                });
2436            } else {
2437                orientation = 1;
2438                window.addEventListener('deviceorientation', orientationListener);
2439                controls.orientation.classList.add('pnlm-orientation-button-active');
2440            }
2441        }
2442
2443        /**
2444         * Escapes HTML string (to mitigate possible DOM XSS attacks).
2445         * @private
2446         * @param {string} s - String to escape
2447         * @returns {string} Escaped string
2448         */
2449        function escapeHTML(s) {
2450            if (!initialConfig.escapeHTML)
2451                return String(s).split('\n').join('<br>');
2452            return String(s).split(/&/g).join('&amp;')
2453                .split('"').join('&quot;')
2454                .split("'").join('&#39;')
2455                .split('<').join('&lt;')
2456                .split('>').join('&gt;')
2457                .split('/').join('&#x2f;')
2458                .split('\n').join('<br>');  // Allow line breaks
2459        }
2460
2461        /**
2462         * Removes possibility of XSS attacks with URLs.
2463         * The URL cannot be of protocol 'javascript'.
2464         * @private
2465         * @param {string} url - URL to sanitize
2466         * @param {boolean} href - True if URL is for link (blocks data URIs)
2467         * @returns {string} Sanitized URL
2468         */
2469        function sanitizeURL(url, href) {
2470            try {
2471                var decoded_url = decodeURIComponent(unescape(url)).replace(/[^\w:]/g, '').toLowerCase();
2472            } catch (e) {
2473                return 'about:blank';
2474            }
2475            if (decoded_url.indexOf('javascript:') === 0 ||
2476                decoded_url.indexOf('vbscript:') === 0) {
2477                console.log('Script URL removed.');
2478                return 'about:blank';
2479            }
2480            if (href && decoded_url.indexOf('data:') === 0) {
2481                console.log('Data URI removed from link.');
2482                return 'about:blank';
2483            }
2484            return url;
2485        }
2486
2487        /**
2488         * Unescapes HTML entities.
2489         * Copied from Marked.js 0.7.0.
2490         * @private
2491         * @param {string} url - URL to sanitize
2492         * @param {boolean} href - True if URL is for link (blocks data URIs)
2493         * @returns {string} Sanitized URL
2494         */
2495        function unescape(html) {
2496            // Explicitly match decimal, hex, and named HTML entities
2497            return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) {
2498                n = n.toLowerCase();
2499                if (n === 'colon') return ':';
2500                if (n.charAt(0) === '#') {
2501                    return n.charAt(1) === 'x'
2502                        ? String.fromCharCode(parseInt(n.substring(2), 16))
2503                        : String.fromCharCode(+n.substring(1));
2504                }
2505                return '';
2506            });
2507        }
2508
2509        /**
2510         * Removes possibility of XSS atacks with URLs for CSS.
2511         * The URL will be sanitized with `sanitizeURL()` and single quotes
2512         * and double quotes escaped.
2513         * @private
2514         * @param {string} url - URL to sanitize
2515         * @returns {string} Sanitized URL
2516         */
2517        function sanitizeURLForCss(url) {
2518            return sanitizeURL(url)
2519                .replace(/"/g, '%22')
2520                .replace(/'/g, '%27');
2521        }
2522
2523        /**
2524         * Checks whether or not a panorama is loaded.
2525         * @memberof Viewer
2526         * @instance
2527         * @returns {boolean} `true` if a panorama is loaded, else `false`
2528         */
2529        this.isLoaded = function() {
2530            return Boolean(loaded);
2531        };
2532
2533        /**
2534         * Returns the pitch of the center of the view.
2535         * @memberof Viewer
2536         * @instance
2537         * @returns {number} Pitch in degrees
2538         */
2539        this.getPitch = function() {
2540            return config.pitch;
2541        };
2542
2543        /**
2544         * Sets the pitch of the center of the view.
2545         * @memberof Viewer
2546         * @instance
2547         * @param {number} pitch - Pitch in degrees
2548         * @param {boolean|number} [animated=1000] - Animation duration in milliseconds or false for no animation
2549         * @param {function} [callback] - Function to call when animation finishes
2550         * @param {object} [callbackArgs] - Arguments to pass to callback function
2551         * @returns {Viewer} `this`
2552         */
2553        this.setPitch = function(pitch, animated, callback, callbackArgs) {
2554            latestInteraction = Date.now();
2555            if (Math.abs(pitch - config.pitch) <= eps) {
2556                if (typeof callback == 'function')
2557                    callback(callbackArgs);
2558                return this;
2559            }
2560            animated = animated == undefined ? 1000: Number(animated);
2561            if (animated) {
2562                animatedMove.pitch = {
2563                    'startTime': Date.now(),
2564                    'startPosition': config.pitch,
2565                    'endPosition': pitch,
2566                    'duration': animated
2567                };
2568                if (typeof callback == 'function')
2569                    setTimeout(function(){callback(callbackArgs);}, animated);
2570            } else {
2571                config.pitch = pitch;
2572            }
2573            animateInit();
2574            return this;
2575        };
2576
2577        /**
2578         * Returns the minimum and maximum allowed pitches (in degrees).
2579         * @memberof Viewer
2580         * @instance
2581         * @returns {number[]} [minimum pitch, maximum pitch]
2582         */
2583        this.getPitchBounds = function() {
2584            return [config.minPitch, config.maxPitch];
2585        };
2586
2587        /**
2588         * Set the minimum and maximum allowed pitches (in degrees).
2589         * @memberof Viewer
2590         * @instance
2591         * @param {number[]} bounds - [minimum pitch, maximum pitch]
2592         * @returns {Viewer} `this`
2593         */
2594        this.setPitchBounds = function(bounds) {
2595            config.minPitch = Math.max(-90, Math.min(bounds[0], 90));
2596            config.maxPitch = Math.max(-90, Math.min(bounds[1], 90));
2597            return this;
2598        };
2599
2600        /**
2601         * Returns the yaw of the center of the view.
2602         * @memberof Viewer
2603         * @instance
2604         * @returns {number} Yaw in degrees
2605         */
2606        this.getYaw = function() {
2607            return (config.yaw + 540) % 360 - 180;
2608        };
2609
2610        /**
2611         * Sets the yaw of the center of the view.
2612         * @memberof Viewer
2613         * @instance
2614         * @param {number} yaw - Yaw in degrees [-180, 180]
2615         * @param {boolean|number} [animated=1000] - Animation duration in milliseconds or false for no animation
2616         * @param {function} [callback] - Function to call when animation finishes
2617         * @param {object} [callbackArgs] - Arguments to pass to callback function
2618         * @returns {Viewer} `this`
2619         */
2620        this.setYaw = function(yaw, animated, callback, callbackArgs) {
2621            latestInteraction = Date.now();
2622            if (Math.abs(yaw - config.yaw) <= eps) {
2623                if (typeof callback == 'function')
2624                    callback(callbackArgs);
2625                return this;
2626            }
2627            animated = animated == undefined ? 1000: Number(animated);
2628            yaw = ((yaw + 180) % 360) - 180; // Keep in bounds
2629            if (animated) {
2630                // Animate in shortest direction
2631                if (config.yaw - yaw > 180)
2632                    yaw += 360;
2633                else if (yaw - config.yaw > 180)
2634                    yaw -= 360;
2635
2636                animatedMove.yaw = {
2637                    'startTime': Date.now(),
2638                    'startPosition': config.yaw,
2639                    'endPosition': yaw,
2640                    'duration': animated
2641                };
2642                if (typeof callback == 'function')
2643                    setTimeout(function(){callback(callbackArgs);}, animated);
2644            } else {
2645                config.yaw = yaw;
2646            }
2647            animateInit();
2648            return this;
2649        };
2650
2651        /**
2652         * Returns the minimum and maximum allowed pitches (in degrees).
2653         * @memberof Viewer
2654         * @instance
2655         * @returns {number[]} [yaw pitch, maximum yaw]
2656         */
2657        this.getYawBounds = function() {
2658            return [config.minYaw, config.maxYaw];
2659        };
2660
2661        /**
2662         * Set the minimum and maximum allowed yaws (in degrees [-360, 360]).
2663         * @memberof Viewer
2664         * @instance
2665         * @param {number[]} bounds - [minimum yaw, maximum yaw]
2666         * @returns {Viewer} `this`
2667         */
2668        this.setYawBounds = function(bounds) {
2669            config.minYaw = Math.max(-360, Math.min(bounds[0], 360));
2670            config.maxYaw = Math.max(-360, Math.min(bounds[1], 360));
2671            return this;
2672        };
2673
2674        /**
2675         * Returns the horizontal field of view.
2676         * @memberof Viewer
2677         * @instance
2678         * @returns {number} Horizontal field of view in degrees
2679         */
2680        this.getHfov = function() {
2681            return config.hfov;
2682        };
2683
2684        /**
2685         * Sets the horizontal field of view.
2686         * @memberof Viewer
2687         * @instance
2688         * @param {number} hfov - Horizontal field of view in degrees
2689         * @param {boolean|number} [animated=1000] - Animation duration in milliseconds or false for no animation
2690         * @param {function} [callback] - Function to call when animation finishes
2691         * @param {object} [callbackArgs] - Arguments to pass to callback function
2692         * @returns {Viewer} `this`
2693         */
2694        this.setHfov = function(hfov, animated, callback, callbackArgs) {
2695            latestInteraction = Date.now();
2696            if (Math.abs(hfov - config.hfov) <= eps) {
2697                if (typeof callback == 'function')
2698                    callback(callbackArgs);
2699                return this;
2700            }
2701            animated = animated == undefined ? 1000: Number(animated);
2702            if (animated) {
2703                animatedMove.hfov = {
2704                    'startTime': Date.now(),
2705                    'startPosition': config.hfov,
2706                    'endPosition': constrainHfov(hfov),
2707                    'duration': animated
2708                };
2709                if (typeof callback == 'function')
2710                    setTimeout(function(){callback(callbackArgs);}, animated);
2711            } else {
2712                setHfov(hfov);
2713            }
2714            animateInit();
2715            return this;
2716        };
2717
2718        /**
2719         * Returns the minimum and maximum allowed horizontal fields of view
2720         * (in degrees).
2721         * @memberof Viewer
2722         * @instance
2723         * @returns {number[]} [minimum hfov, maximum hfov]
2724         */
2725        this.getHfovBounds = function() {
2726            return [config.minHfov, config.maxHfov];
2727        };
2728
2729        /**
2730         * Set the minimum and maximum allowed horizontal fields of view (in degrees).
2731         * @memberof Viewer
2732         * @instance
2733         * @param {number[]} bounds - [minimum hfov, maximum hfov]
2734         * @returns {Viewer} `this`
2735         */
2736        this.setHfovBounds = function(bounds) {
2737            config.minHfov = Math.max(0, bounds[0]);
2738            config.maxHfov = Math.max(0, bounds[1]);
2739            return this;
2740        };
2741
2742        /**
2743         * Set a new view. Any parameters not specified remain the same.
2744         * @memberof Viewer
2745         * @instance
2746         * @param {number} [pitch] - Target pitch
2747         * @param {number} [yaw] - Target yaw
2748         * @param {number} [hfov] - Target hfov
2749         * @param {boolean|number} [animated=1000] - Animation duration in milliseconds or false for no animation
2750         * @param {function} [callback] - Function to call when animation finishes
2751         * @param {object} [callbackArgs] - Arguments to pass to callback function
2752         * @returns {Viewer} `this`
2753         */
2754        this.lookAt = function(pitch, yaw, hfov, animated, callback, callbackArgs) {
2755            animated = animated == undefined ? 1000: Number(animated);
2756            if (pitch !== undefined && Math.abs(pitch - config.pitch) > eps) {
2757                this.setPitch(pitch, animated, callback, callbackArgs);
2758                callback = undefined;
2759            }
2760            if (yaw !== undefined && Math.abs(yaw - config.yaw) > eps) {
2761                this.setYaw(yaw, animated, callback, callbackArgs);
2762                callback = undefined;
2763            }
2764            if (hfov !== undefined && Math.abs(hfov - config.hfov) > eps) {
2765                this.setHfov(hfov, animated, callback, callbackArgs);
2766                callback = undefined;
2767            }
2768            if (typeof callback == 'function')
2769                callback(callbackArgs);
2770            return this;
2771        };
2772
2773        /**
2774         * Returns the panorama's north offset.
2775         * @memberof Viewer
2776         * @instance
2777         * @returns {number} North offset in degrees
2778         */
2779        this.getNorthOffset = function() {
2780            return config.northOffset;
2781        };
2782
2783        /**
2784         * Sets the panorama's north offset.
2785         * @memberof Viewer
2786         * @instance
2787         * @param {number} heading - North offset in degrees
2788         * @returns {Viewer} `this`
2789         */
2790        this.setNorthOffset = function(heading) {
2791            config.northOffset = Math.min(360, Math.max(0, heading));
2792            animateInit();
2793            return this;
2794        };
2795
2796        /**
2797         * Returns the panorama's horizon roll.
2798         * @memberof Viewer
2799         * @instance
2800         * @returns {number} Horizon roll in degrees
2801         */
2802        this.getHorizonRoll = function() {
2803            return config.horizonRoll;
2804        };
2805
2806        /**
2807         * Sets the panorama's horizon roll.
2808         * @memberof Viewer
2809         * @instance
2810         * @param {number} roll - Horizon roll in degrees [-90, 90]
2811         * @returns {Viewer} `this`
2812         */
2813        this.setHorizonRoll = function(roll) {
2814            config.horizonRoll = Math.min(90, Math.max(-90, roll));
2815            renderer.setPose(config.horizonPitch * Math.PI / 180, config.horizonRoll * Math.PI / 180);
2816            animateInit();
2817            return this;
2818        };
2819
2820        /**
2821         * Returns the panorama's horizon pitch.
2822         * @memberof Viewer
2823         * @instance
2824         * @returns {number} Horizon pitch in degrees
2825         */
2826        this.getHorizonPitch = function() {
2827            return config.horizonPitch;
2828        };
2829
2830        /**
2831         * Sets the panorama's horizon pitch.
2832         * @memberof Viewer
2833         * @instance
2834         * @param {number} pitch - Horizon pitch in degrees [-90, 90]
2835         * @returns {Viewer} `this`
2836         */
2837        this.setHorizonPitch = function(pitch) {
2838            config.horizonPitch = Math.min(90, Math.max(-90, pitch));
2839            renderer.setPose(config.horizonPitch * Math.PI / 180, config.horizonRoll * Math.PI / 180);
2840            animateInit();
2841            return this;
2842        };
2843
2844        /**
2845         * Start auto rotation.
2846         *
2847         * Before starting rotation, the viewer is panned to `pitch`.
2848         * @memberof Viewer
2849         * @instance
2850         * @param {number}
2850 [speed] - Auto rotation speed / direction. If not specified, previous value is used.
2851         * @param {number} [pitch] - The pitch to rotate at. If not specified, inital pitch is used.
2852         * @returns {Viewer} `this`
2853         */
2854        this.startAutoRotate = function(speed, pitch) {
2855            speed = speed || autoRotateSpeed || 1;
2856            pitch = pitch === undefined ? origPitch : pitch;
2857            config.autoRotate = speed;
2858            _this.lookAt(pitch, undefined, origHfov, 3000);
2859            animateInit();
2860            return this;
2861        };
2862
2863        /**
2864         * Stop auto rotation.
2865         * @memberof Viewer
2866         * @instance
2867         * @returns {Viewer} `this`
2868         */
2869        this.stopAutoRotate = function() {
2870            autoRotateSpeed = config.autoRotate ? config.autoRotate : autoRotateSpeed;
2871            config.autoRotate = false;
2872            config.autoRotateInactivityDelay = -1;
2873            return this;
2874        };
2875
2876        /**
2877         * Stops all movement.
2878         * @memberof Viewer
2879         * @instance
2880         */
2881        this.stopMovement = function() {
2882            stopAnimation();
2883            speed = {'yaw': 0, 'pitch': 0, 'hfov': 0};
2884        };
2885
2886        /**
2887         * Returns the panorama renderer.
2888         * @memberof Viewer
2889         * @instance
2890         * @returns {Renderer}
2891         */
2892        this.getRenderer = function() {
2893            return renderer;
2894        };
2895
2896        /**
2897         * Sets update flag for dynamic content.
2898         * @memberof Viewer
2899         * @instance
2900         * @param {boolean} bool - Whether or not viewer should update even when still
2901         * @returns {Viewer} `this`
2902         */
2903        this.setUpdate = function(bool) {
2904            update = bool === true;
2905            if (renderer === undefined)
2906                onImageLoad();
2907            else
2908                animateInit();
2909            return this;
2910        };
2911
2912        /**
2913         * Calculate panorama pitch and yaw from location of mouse event.
2914         * @memberof Viewer
2915         * @instance
2916         * @param {MouseEvent} event - Document mouse down event.
2917         * @returns {number[]} [pitch, yaw]
2918         */
2919        this.mouseEventToCoords = function(event) {
2920            return mouseEventToCoords(event);
2921        };
2922
2923        /**
2924         * Change scene being viewed.
2925         * @memberof Viewer
2926         * @instance
2927         * @param {string} sceneId - Identifier of scene to switch to.
2928         * @param {number} [pitch] - Pitch to use with new scene
2929         * @param {number} [yaw] - Yaw to use with new scene
2930         * @param {number} [hfov] - HFOV to use with new scene
2931         * @returns {Viewer} `this`
2932         */
2933        this.loadScene = function(sceneId, pitch, yaw, hfov) {
2934            if (loaded !== false)
2935                loadScene(sceneId, pitch, yaw, hfov);
2936            return this;
2937        };
2938
2939        /**
2940         * Get ID of current scene.
2941         * @memberof Viewer
2942         * @instance
2943         * @returns {string} ID of current scene
2944         */
2945        this.getScene = function() {
2946            return config.scene;
2947        };
2948
2949        /**
2950         * Add a new scene.
2951         * @memberof Viewer
2952         * @instance
2953         * @param {string} sceneId - The ID of the new scene
2954         * @param {string} config - The configuration of the new scene
2955         * @returns {Viewer} `this`
2956         */
2957        this.addScene = function(sceneId, config) {
2958            initialConfig.scenes[sceneId] = config;
2959            return this;
2960        };
2961
2962        /**
2963         * Remove a scene.
2964         * @memberof Viewer
2965         * @instance
2966         * @param {string} sceneId - The ID of the scene
2967         * @returns {boolean} False if the scene is the current scene or if the scene doesn't exists, else true
2968         */
2969        this.removeScene = function(sceneId) {
2970            if (config.scene === sceneId || !initialConfig.scenes.hasOwnProperty(sceneId))
2971                return false;
2972            delete initialConfig.scenes[sceneId];
2973            return true;
2974        };
2975
2976        /**
2977         * Toggle fullscreen.
2978         * @memberof Viewer
2979         * @instance
2980         * @returns {Viewer} `this`
2981         */
2982        this.toggleFullscreen = function() {
2983            toggleFullscreen();
2984            return this;
2985        };
2986
2987        /**
2988         * Get configuration of current scene.
2989         * @memberof Viewer
2990         * @instance
2991         * @returns {Object} Configuration of current scene
2992         */
2993        this.getConfig = function() {
2994            return config;
2995        };
2996
2997        /**
2998         * Get viewer's container element.
2999         * @memberof Viewer
3000         * @instance
3001         * @returns {HTMLElement} Container `div` element
3002         */
3003        this.getContainer = function() {
3004            return container;
3005        };
3006
3007        /**
3008         * Add a new hot spot.
3009         * @memberof Viewer
3010         * @instance
3011         * @param {Object} hs - The configuration for the hot spot
3012         * @param {string} [sceneId] - Adds hot spot to specified scene if provided, else to current scene
3013         * @returns {Viewer} `this`
3014         * @throws Throws an error if the scene ID is provided but invalid
3015         */
3016        this.addHotSpot = function(hs, sceneId) {
3017            if (sceneId === undefined && config.scene === undefined) {
3018                // Not a tour
3019                config.hotSpots.push(hs);
3020            } else {
3021                // Tour
3022                var id = sceneId !== undefined ? sceneId : config.scene;
3023                if (initialConfig.scenes.hasOwnProperty(id)) {
3024                    if (!initialConfig.scenes[id].hasOwnProperty('hotSpots')) {
3025                        initialConfig.scenes[id].hotSpots = []; // Create hot spots array if needed
3026                        if (id == config.scene)
3027                            config.hotSpots = initialConfig.scenes[id].hotSpots;    // Link to current config
3028                    }
3029                    initialConfig.scenes[id].hotSpots.push(hs); // Add hot spot to config
3030                } else {
3031                    throw 'Invalid scene ID!';
3032                }
3033            }
3034            if (sceneId === undefined || config.scene == sceneId) {
3035                // Add to current scene
3036                createHotSpot(hs);
3037                if (loaded)
3038                    renderHotSpot(hs);
3039            }
3040            return this;
3041        };
3042
3043        /**
3044         * Remove a hot spot.
3045         * @memberof Viewer
3046         * @instance
3047         * @param {string} hotSpotId - The ID of the hot spot
3048         * @param {string} [sceneId] - Removes hot spot from specified scene if provided, else from current scene
3049         * @returns {boolean} True if deletion is successful, else false
3050         */
3051        this.removeHotSpot = function(hotSpotId, sceneId) {
3052            if (sceneId === undefined || config.scene == sceneId) {
3053                if (!config.hotSpots)
3054                    return false;
3055                for (var i = 0; i < config.hotSpots.length; i++) {
3056                    if (config.hotSpots[i].hasOwnProperty('id') &&
3057                        config.hotSpots[i].id === hotSpotId) {
3058                        // Delete hot spot DOM elements
3059                        var current = config.hotSpots[i].div;
3060                        while (current.parentNode != renderContainer)
3061                            current = current.parentNode;
3062                        renderContainer.removeChild(current);
3063                        delete config.hotSpots[i].div;
3064                        // Remove hot spot from configuration
3065                        config.hotSpots.splice(i, 1);
3066                        return true;
3067                    }
3068                }
3069            } else {
3070                if (initialConfig.scenes.hasOwnProperty(sceneId)) {
3071                    if (!initialConfig.scenes[sceneId].hasOwnProperty('hotSpots'))
3072                        return false;
vendor: 7,882 bytes, lines 3073-3275
3073                    for (var j = 0; j < initialConfig.scenes[sceneId].hotSpots.length; j++) {
3074                        if (initialConfig.scenes[sceneId].hotSpots[j].hasOwnProperty('id') &&
3075                            initialConfig.scenes[sceneId].hotSpots[j].id === hotSpotId) {
3076                            // Remove hot spot from configuration
3077                            initialConfig.scenes[sceneId].hotSpots.splice(j, 1);
3078                            return true;
3079                        }
3080                    }
3081                } else {
3082                    return false;
3083                }
3084            }
3085        };
3086
3087        /**
3088         * This method should be called if the viewer's container is resized.
3089         * @memberof Viewer
3090         * @instance
3091         */
3092        this.resize = function() {
3093            if (renderer)
3094                onDocumentResize();
3095        };
3096
3097        /**
3098         * Check if a panorama is loaded.
3099         * @memberof Viewer
3100         * @instance
3101         * @returns {boolean} True if a panorama is loaded, else false
3102         */
3103        this.isLoaded = function() {
3104            return loaded;
3105        };
3106
3107        /**
3108         * Check if device orientation control is supported.
3109         * @memberof Viewer
3110         * @instance
3111         * @returns {boolean} True if supported, else false
3112         */
3113        this.isOrientationSupported = function() {
3114            return orientationSupport || false;
3115        };
3116
3117        /**
3118         * Stop using device orientation.
3119         * @memberof Viewer
3120         * @instance
3121         */
3122        this.stopOrientation = function() {
3123            stopOrientation();
3124        };
3125
3126        /**
3127         * Start using device orientation (does nothing if not supported).
3128         * @memberof Viewer
3129         * @instance
3130         */
3131        this.startOrientation = function() {
3132            if (orientationSupport)
3133                startOrientation();
3134        };
3135
3136        /**
3137         * Check if device orientation control is currently activated.
3138         * @memberof Viewer
3139         * @instance
3140         * @returns {boolean} True if active, else false
3141         */
3142        this.isOrientationActive = function() {
3143            return Boolean(orientation);
3144        };
3145
3146        /**
3147         * Subscribe listener to specified event.
3148         * @memberof Viewer
3149         * @instance
3150         * @param {string} type - Type of event to subscribe to.
3151         * @param {Function} listener - Listener function to subscribe to event.
3152         * @returns {Viewer} `this`
3153         */
3154        this.on = function(type, listener) {
3155            externalEventListeners[type] = externalEventListeners[type] || [];
3156            externalEventListeners[type].push(listener);
3157            return this;
3158        };
3159
3160        /**
3161         * Remove an event listener (or listeners).
3162         * @memberof Viewer
3163         * @param {string} [type] - Type of event to remove listeners from. If not specified, all listeners are removed.
3164         * @param {Function} [listener] - Listener function to remove. If not specified, all listeners of specified type are removed.
3165         * @returns {Viewer} `this`
3166         */
3167        this.off = function(type, listener) {
3168            if (!type) {
3169                // Remove all listeners if type isn't specified
3170                externalEventListeners = {};
3171                return this;
3172            }
3173            if (listener) {
3174                var i = externalEventListeners[type].indexOf(listener);
3175                if (i >= 0) {
3176                    // Remove listener if found
3177                    externalEventListeners[type].splice(i, 1);
3178                }
3179                if (externalEventListeners[type].length == 0) {
3180                    // Remove category if empty
3181                    delete externalEventListeners[type];
3182                }
3183            } else {
3184                // Remove category of listeners if listener isn't specified
3185                delete externalEventListeners[type];
3186            }
3187            return this;
3188        };
3189
3190        /**
3191         * Fire listeners attached to specified event.
3192         * @private
3193         * @param {string} [type] - Type of event to fire listeners for.
3194         */
3195        function fireEvent(type) {
3196            if (type in externalEventListeners) {
3197                // Reverse iteration is useful, if event listener is removed inside its definition
3198                for (var i = externalEventListeners[type].length; i > 0; i--) {
3199                    externalEventListeners[type][externalEventListeners[type].length - i].apply(null, [].slice.call(arguments, 1));
3200                }
3201            }
3202        }
3203
3204        /**
3205         * Destructor.
3206         * @instance
3207         * @memberof Viewer
3208         */
3209        this.destroy = function() {
3210            destroyed = true;
3211            clearTimeout(autoRotateStart);
3212
3213            if (renderer)
3214                renderer.destroy();
3215            if (listenersAdded) {
3216                document.removeEventListener('mousemove', onDocumentMouseMove, false);
3217                document.removeEventListener('compasschange', onDocumentCompassChange, false);
3218                document.removeEventListener('mouseup', onDocumentMouseUp, false);
3219                container.removeEventListener('mozfullscreenchange', onFullScreenChange, false);
3220                container.removeEventListener('webkitfullscreenchange', onFullScreenChange, false);
3221                container.removeEventListener('msfullscreenchange', onFullScreenChange, false);
3222                container.removeEventListener('fullscreenchange', onFullScreenChange, false);
3223                window.removeEventListener('resize', onDocumentResize, false);
3224                window.removeEventListener('orientationchange', onDocumentResize, false);
3225                container.removeEventListener('keydown', onDocumentKeyPress, false);
3226                container.removeEventListener('keyup', onDocumentKeyUp, false);
3227                container.removeEventListener('blur', clearKeys, false);
3228                document.removeEventListener('mouseleave', onDocumentMouseUp, false);
3229            }
3230            container.innerHTML = '';
3231            container.classList.remove('pnlm-container');
3232        };
3233
3234    }
3235
3236    return {
3237        viewer: function(container, config) {
3238            return new Viewer(container, config);
3239        }
3240    };
3241
3242})(window, document);
3243// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/public/lib/pannellum/src/js/libpannellum.js?ver=1 
3244/*
3245 * libpannellum - A WebGL and CSS 3D transform based Panorama Renderer
3246 * Copyright (c) 2012-2019 Matthew Petroff
3247 * 
3248 * Permission is hereby granted, free of charge, to any person obtaining a copy
3249 * of this software and associated documentation files (the "Software"), to deal
3250 * in the Software without restriction, including without limitation the rights
3251 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3252 * copies of the Software, and to permit persons to whom the Software is
3253 * furnished to do so, subject to the following conditions:
3254 * 
3255 * The above copyright notice and this permission notice shall be included in
3256 * all copies or substantial portions of the Software.
3257 * 
3258 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3259 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3260 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3261 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3262 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3263 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3264 * THE SOFTWARE.
3265 */
3266
3267window.libpannellum = (function(window, document, undefined) {
3268
3269'use strict';
3270
3271/**
3272 * Creates a new panorama renderer.
3273 * @constructor
3274 * @param {HTMLElement} container - The container element for the renderer.
3275 */
3276function Renderer(container) {
3277    var canvas = document.createElement('canvas');
3278    canvas.style.width = canvas.style.height = '100%';
3279    container.appendChild(canvas);
3280
3281    var program, gl, vs, fs;
3282    var fallbackImgSize;
3283    var world;
3284    var vtmps;
3285    var pose;
3286    var image, imageType, dynamic;
3287    var texCoordBuffer, cubeVertBuf, cubeVertTexCoordBuf, cubeVertIndBuf;
3288    var globalParams;
3289
3290    /**
3291     * Initialize renderer.
3292     * @memberof Renderer
3293     * @instance
3294     * @param {Image|Array|Object} image - Input image; format varies based on
3295     *      `imageType`. For `equirectangular`, this is an image; for
3296     *      `cubemap`, this is an array of images for the cube faces in the
3297     *      order [+z, +x, -z, -x, +y, -y]; for `multires`, this is a
3298     *      configuration object.
3299     * @param {string} imageType - The type of the image: `equirectangular`,
3300     *      `cubemap`, or `multires`.
3301     * @param {boolean} dynamic - Whether or not the image is dynamic (e.g. video).
3302     * @param {number} haov - Initial horizontal angle of view.
3303     * @param {number} vaov - Initial vertical angle of view.
3304     * @param {number} voffset - Initial vertical offset angle.
3305     * @param {function} callback - Load callback function.
3306     * @param {Object} [params] - Other configuration parameters (`horizonPitch`, `horizonRoll`, `backgroundColor`).
3307     */
3308    this.init = function(_image, _imageType, _dynamic, haov, vaov, voffset, callback, params) {
3309        // Default argument for image type
3310        if (_imageType === undefined)
3311            _imageType = 'equirectangular';
3312
3313        if (_imageType != 'equirectangular' && _imageType != 'cubemap' &&
3314            _imageType != 'multires') {
3315            console.log('Error: invalid image type specified!');
3316            throw {type: 'config error'};
3317        }
3318
3319        imageType = _imageType;
3320        image = _image;
3321        dynamic = _dynamic;
3322        globalParams = params || {};
3323
3324        // Clear old data
3325        if (program) {
3326            if (vs) {
3327                gl.detachShader(program, vs);
3328                gl.deleteShader(vs);
3329            }
3330            if (fs) {
3331                gl.detachShader(program, fs);
3332                gl.deleteShader(fs);
3333            }
3334            gl.bindBuffer(gl.ARRAY_BUFFER, null);
3335            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
3336            if (program.texture)
3337                gl.deleteTexture(program.texture);
3338            if (program.nodeCache)
3339                for (var i = 0; i < program.nodeCache.length; i++)
3340                    gl.deleteTexture(program.nodeCache[i].texture);
3341            gl.deleteProgram(program);
3342            program = undefined;
3343        }
3344        pose = undefined;
3345
3346        var s;
3347        var faceMissing = false;
3348        var cubeImgWidth;
3349        if (imageType == 'cubemap') {
3350            for (s = 0; s < 6; s++) {
3351                if (image[s].width > 0) {
3352                    if (cubeImgWidth === undefined)
3353                        cubeImgWidth = image[s].width;
3354                    if (cubeImgWidth != image[s].width)
3355                        console.log('Cube faces have inconsistent widths: ' + cubeImgWidth + ' vs. ' + image[s].width);
3356                } else
3357                    faceMissing = true;
3358            }
3359        }
3360        function fillMissingFaces(imgSize) {
3361            if (faceMissing) { // Fill any missing fallback/cubemap faces with background
3362                var nbytes = imgSize * imgSize * 4; // RGB, plus non-functional alpha
3363                var imageArray = new Uint8ClampedArray(nbytes);
3364                var rgb = params.backgroundColor ? params.backgroundColor : [0, 0, 0];
3365                rgb[0] *= 255;
3366                rgb[1] *= 255;
3367                rgb[2] *= 255;
3368                // Maybe filling could be done faster, see e.g. https://stackoverflow.com/questions/1295584/most-efficient-way-to-create-a-zero-filled-javascript-array
3369                for (var i = 0; i < nbytes; i++) {
3370                    imageArray[i++] = rgb[0];
3371                    imageArray[i++] = rgb[1];
3372                    imageArray[i++] = rgb[2];
3373                }
3374                var backgroundSquare = new ImageData(imageArray, imgSize, imgSize);
3375                for (s = 0; s < 6; s++) {
3376                    if (image[s].width == 0)
3377                        image[s] = backgroundSquare;
3378                }
3379            }
3380        }
3381        
3382        // This awful browser specific test exists because iOS 8/9 and IE 11
3383        // don't display non-power-of-two cubemap textures but also don't
3384        // throw an error (tested on an iPhone 5c / iOS 8.1.3 / iOS 9.2 /
3385        // iOS 10.3.1).
3386        // Therefore, the WebGL context is never created for these browsers for
3387        // NPOT cubemaps, and the CSS 3D transform fallback renderer is used
3388        // instead.
3389        if (!(imageType == 'cubemap' &&
3390            (cubeImgWidth & (cubeImgWidth - 1)) !== 0 &&
3391            (navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 8_/) ||
3392            navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 9_/) ||
3393            navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 10_/) ||
3394            navigator.userAgent.match(/Trident.*rv[ :]*11\./)))) {
3395            // Enable WebGL on canvas
3396            if (!gl)
3397                gl = canvas.getContext('experimental-webgl', {alpha: false, depth: false});
3398            if (gl && gl.getError() == 1286)
3399                handleWebGLError1286();
3400        }
3401        
3402        // If there is no WebGL, fall back to CSS 3D transform renderer.
3403        // This will discard the image loaded so far and load the fallback image.
3404        // While browser specific tests are usually frowned upon, the
3405        // fallback viewer only really works with WebKit/Blink and IE 10/11
3406        // (it doesn't work properly in Firefox).
3407        if (!gl && ((imageType == 'multires' && image.hasOwnProperty('fallbackPath')) ||
3408            imageType == 'cubemap') &&
3409            ('WebkitAppearance' in document.documentElement.style ||
3410            navigator.userAgent.match(/Trident.*rv[ :]*11\./) ||
3411            navigator.appVersion.indexOf('MSIE 10') !== -1)) {
3412            // Remove old world if it exists
3413            if (world) {
3414                container.removeChild(world);
3415            }
3416            
3417            // Initialize renderer
3418            world = document.createElement('div');
3419            world.className = 'pnlm-world';
3420            
3421            // Add images
3422            var path;
3423            if (image.basePath) {
3424                path = image.basePath + image.fallbackPath;
3425            } else {
3426                path = image.fallbackPath;
3427            }
3428            var sides = ['f', 'r', 'b', 'l', 'u', 'd'];
3429            var loaded = 0;
3430            var onLoad = function() {
3431                // Draw image on canvas
3432                var faceCanvas = document.createElement('canvas');
3433                faceCanvas.className = 'pnlm-face pnlm-' + sides[this.side] + 'face';
3434                world.appendChild(faceCanvas);
3435                var faceContext = faceCanvas.getContext('2d');
3436                faceCanvas.style.width = this.width + 4 + 'px';
3437                faceCanvas.style.height = this.height + 4 + 'px';
3438                faceCanvas.width = this.width + 4;
3439                faceCanvas.height = this.height + 4;
3440                faceContext.drawImage(this, 2, 2);
3441                var imgData = faceContext.getImageData(0, 0, faceCanvas.width, faceCanvas.height);
3442                var data = imgData.data;
3443                
3444                // Duplicate edge pixels
3445                var i;
3446                var j;
3447                for (i = 2; i < faceCanvas.width - 2; i++) {
3448                    for (j = 0; j < 4; j++) {
3449                        data[(i + faceCanvas.width) * 4 + j] = data[(i + faceCanvas.width * 2) * 4 + j];
3450                        data[(i + faceCanvas.width * (faceCanvas.height - 2)) * 4 + j] = data[(i + faceCanvas.width * (faceCanvas.height - 3)) * 4 + j];
3451                    }
3452                }
3453                for (i = 2; i < faceCanvas.height - 2; i++) {
3454                    for (j = 0; j < 4; j++) {
3455                        data[(i * faceCanvas.width + 1) * 4 + j] = data[(i * faceCanvas.width + 2) * 4 + j];
3456                        data[((i + 1) * faceCanvas.width - 2) * 4 + j] = data[((i + 1) * faceCanvas.width - 3) * 4 + j];
3457                    }
3458                }
3459                for (j = 0; j < 4; j++) {
3460                    data[(faceCanvas.width + 1) * 4 + j] = data[(faceCanvas.width * 2 + 2) * 4 + j];
3461                    data[(faceCanvas.width * 2 - 2) * 4 + j] = data[(faceCanvas.width * 3 - 3) * 4 + j];
3462                    data[(faceCanvas.width * (faceCanvas.height - 2) + 1) * 4 + j] = data[(faceCanvas.width * (faceCanvas.height - 3) + 2) * 4 + j];
3463                    data[(faceCanvas.width * (faceCanvas.height - 1) - 2) * 4 + j] = data[(faceCanvas.width * (faceCanvas.height - 2) - 3) * 4 + j];
3464                }
3465                for (i = 1; i < faceCanvas.width - 1; i++) {
3466                    for (j = 0; j < 4; j++) {
3467                        data[i * 4 + j] = data[(i + faceCanvas.width) * 4 + j];
3468                        data[(i + faceCanvas.width * (faceCanvas.height - 1)) * 4 + j] = data[(i + faceCanvas.width * (faceCanvas.height - 2)) * 4 + j];
3469                    }
3470                }
3471                for (i = 1; i < faceCanvas.height - 1; i++) {
3472                    for (j = 0; j < 4; j++) {
3473                        data[(i * faceCanvas.width) * 4 + j] = data[(i * faceCanvas.width + 1) * 4 + j];
3474                        data[((i + 1) * faceCanvas.width - 1) * 4 + j] = data[((i + 1) * faceCanvas.width - 2) * 4 + j];
3475                    }
3476                }
3477                for (j = 0; j < 4; j++) {
3478                    data[j] = data[(faceCanvas.width + 1) * 4 + j];
3479                    data[(faceCanvas.width - 1) * 4 + j] = data[(faceCanvas.width * 2 - 2) * 4 + j];
3480                    data[(faceCanvas.width * (faceCanvas.height - 1)) * 4 + j] = data[(faceCanvas.width * (faceCanvas.height - 2) + 1) * 4 + j];
3481                    data[(faceCanvas.width * faceCanvas.height - 1) * 4 + j] = data[(faceCanvas.width * (faceCanvas.height - 1) - 2) * 4 + j];
3482                }
3483                
3484                // Draw image width duplicated edge pixels on canvas
3485                faceContext.putImageData(imgData, 0, 0);
3486                
3487                incLoaded.call(this);
3488            };
3489            var incLoaded = function() {
3490                if (this.width > 0) {
3491                    if (fallbackImgSize === undefined)
3492                        fallbackImgSize = this.width;
3493                    if (fallbackImgSize != this.width)
3494                        console.log('Fallback faces have inconsistent widths: ' + fallbackImgSize + ' vs. ' + this.width);
3495                } else
3496                    faceMissing = true;
3497                loaded++;
3498                if (loaded == 6) {
3499                    fallbackImgSize = this.width;
3500                    container.appendChild(world);
3501                    callback();
3502                }
3503            };
3504            faceMissing = false;
3505            for (s = 0; s < 6; s++) {
3506                var faceImg = new Image();
3507                faceImg.crossOrigin = globalParams.crossOrigin ? globalParams.crossOrigin : 'anonymous';
3508                faceImg.side = s;
3509                faceImg.onload = onLoad;
3510                faceImg.onerror = incLoaded; // ignore missing face to support partial fallback image
3511                if (imageType == 'multires') {
3512                    faceImg.src = path.replace('%s', sides[s]) + '.' + image.extension;
3513                } else {
3514                    faceImg.src = image[s].src;
3515                }
3516            }
3517            fillMissingFaces(fallbackImgSize);
3518            return;
3519        } else if (!gl) {
3520            console.log('Error: no WebGL support detected!');
3521            throw {type: 'no webgl'};
3522        }
3523        if (imageType == 'cubemap')
3524            fillMissingFaces(cubeImgWidth);
3525        if (image.basePath) {
3526            image.fullpath = image.basePath + image.path;
3527        } else {
3528            image.fullpath = image.path;
3529        }
3530        image.invTileResolution = 1 / image.tileResolution;
3531        
3532        var vertices = createCube();
3533        vtmps = [];
3534        for (s = 0; s < 6; s++) {
3535            vtmps[s] = vertices.slice(s * 12, s * 12 + 12);
3536            vertices = createCube();
3537        }
3538        
3539        // Make sure image isn't too big
3540        var maxWidth = 0;
3541        if (imageType == 'equirectangular') {
3542            maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);
3543            if (Math.max(image.width / 2, image.height) > maxWidth) {
3544                console.log('Error: The image is too big; it\'s ' + image.width + 'px wide, '+
3545                            'but this device\'s maximum supported size is ' + (maxWidth * 2) + 'px.');
3546                throw {type: 'webgl size error', width: image.width, maxWidth: maxWidth * 2};
3547            }
3548        } else if (imageType == 'cubemap') {
3549            if (cubeImgWidth > gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)) {
3550                console.log('Error: The image is too big; it\'s ' + cubeImgWidth + 'px wide, ' +
3551                            'but this device\'s maximum supported size is ' + maxWidth + 'px.');
3552                throw {type: 'webgl size error', width: cubeImgWidth, maxWidth: maxWidth};
3553            }
3554        }
3555
3556        // Store horizon pitch and roll if applicable
3557        if (params !== undefined && (params.horizonPitch !== undefined || params.horizonRoll !== undefined))
3558            pose = [params.horizonPitch == undefined ? 0 : params.horizonPitch,
3559                    params.horizonRoll == undefined ? 0 : params.horizonRoll];
3560
3561        // Set 2d texture binding
3562        var glBindType = gl.TEXTURE_2D;
3563
3564        // Create viewport for entire canvas
3565        gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
3566
3567        // Check precision support
3568        if (gl.getShaderPrecisionFormat) {
3569            var precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
3570            if (precision && precision.precision < 1) {
3571                // `highp` precision not supported; https://stackoverflow.com/a/33308927
3572                fragEquiCubeBase = fragEquiCubeBase.replace('highp', 'mediump');
3573            }
3574        }
3575
3576        // Create vertex shader
3577        vs = gl.createShader(gl.VERTEX_SHADER);
3578        var vertexSrc = v;
3579        if (imageType == 'multires') {
3580            vertexSrc = vMulti;
3581        }
3582        gl.shaderSource(vs, vertexSrc);
3583        gl.compileShader(vs);
3584
3585        // Create fragment shader
3586        fs = gl.createShader(gl.FRAGMENT_SHADER);
3587        var fragmentSrc = fragEquirectangular;
3588        if (imageType == 'cubemap') {
3589            glBindType = gl.TEXTURE_CUBE_MAP;
3590            fragmentSrc = fragCube;
3591        } else if (imageType == 'multires') {
3592            fragmentSrc = fragMulti;
3593        }
3594        gl.shaderSource(fs, fragmentSrc);
3595        gl.compileShader(fs);
3596
3597        // Link WebGL program
3598        program = gl.createProgram();
3599        gl.attachShader(program, vs);
3600        gl.attachShader(program, fs);
3601        gl.linkProgram(program);
3602
3603        // Log errors
3604        if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
3605            console.log(gl.getShaderInfoLog(vs));
3606        if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
3607            console.log(gl.getShaderInfoLog(fs));
3608        if (!gl.getProgramParameter(program, gl.LINK_STATUS))
3609            console.log(gl.getProgramInfoLog(program));
3610
3611        // Use WebGL program
3612        gl.useProgram(program);
3613
3614        program.drawInProgress = false;
3615
3616        // Set background clear color (does not apply to cubemap/fallback image)
3617        var color = params.backgroundColor ? params.backgroundColor : [0, 0, 0];
3618        gl.clearColor(color[0], color[1], color[2], 1.0);
3619        gl.clear(gl.COLOR_BUFFER_BIT);
3620
3621        // Look up texture coordinates location
3622        program.texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
3623        gl.enableVertexAttribArray(program.texCoordLocation);
3624
3625        if (imageType != 'multires') {
3626            // Provide texture coordinates for rectangle
3627            if (!texCoordBuffer)
3628                texCoordBuffer = gl.createBuffer();
3629            gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
3630            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,1,1,1,1,-1,-1,1,1,-1,-1,-1]), gl.STATIC_DRAW);
3631            gl.vertexAttribPointer(program.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
3632
3633            // Pass aspect ratio
3634            program.aspectRatio = gl.getUniformLocation(program, 'u_aspectRatio');
3635            gl.uniform1f(program.aspectRatio, gl.drawingBufferWidth / gl.drawingBufferHeight);
3636
3637            // Locate psi, theta, focal length, horizontal extent, vertical extent, and vertical offset
3638            program.psi = gl.getUniformLocation(program, 'u_psi');
3639            program.theta = gl.getUniformLocation(program, 'u_theta');
3640            program.f = gl.getUniformLocation(program, 'u_f');
3641            program.h = gl.getUniformLocation(program, 'u_h');
3642            program.v = gl.getUniformLocation(program, 'u_v');
3643            program.vo = gl.getUniformLocation(program, 'u_vo');
3644            program.rot = gl.getUniformLocation(program, 'u_rot');
3645
3646            // Pass horizontal extent, vertical extent, and vertical offset
3647            gl.uniform1f(program.h, haov / (Math.PI * 2.0));
3648            gl.uniform1f(program.v, vaov / Math.PI);
3649            gl.uniform1f(program.vo, voffset / Math.PI * 2);
3650
3651            // Set background color
3652            if (imageType == 'equirectangular') {
3653                program.backgroundColor = gl.getUniformLocation(program, 'u_backgroundColor');
3654                gl.uniform4fv(program.backgroundColor, color.concat([1]));
3655            }
3656
3657            // Create texture
3658            program.texture = gl.createTexture();
3659            gl.bindTexture(glBindType, program.texture);
3660
3661            // Upload images to texture depending on type
3662            if (imageType == 'cubemap') {
3663                // Load all six sides of the cube map
3664                gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[1]);
3665                gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[3]);
3666                gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[4]);
3667                gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[5]);
3668                gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[0]);
3669                gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[2]);
3670            } else {
3671                if (image.width <= maxWidth) {
3672                    gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 0);
3673                    // Upload image to the texture
3674                    gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
3675                } else {
3676                    // Image needs to be split into two parts due to texture size limits
3677                    gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 1);
3678
3679                    // Draw image on canvas
3680                    var cropCanvas = document.createElement('canvas');
3681                    cropCanvas.width = image.width / 2;
3682                    cropCanvas.height = image.height;
3683                    var cropContext = cropCanvas.getContext('2d');
3684                    cropContext.drawImage(image, 0, 0);
3685
3686                    // Upload first half of image to the texture
3687                    var cropImage = cropContext.getImageData(0, 0, image.width / 2, image.height);
3688                    gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);
3689
3690                    // Create and bind texture for second half of image
3691                    program.texture2 = gl.createTexture();
3692                    gl.activeTexture(gl.TEXTURE1);
3693                    gl.bindTexture(glBindType, program.texture2);
3694                    gl.uniform1i(gl.getUniformLocation(program, 'u_image1'), 1);
3695
3696                    // Upload second half of image to the texture
3697                    cropContext.drawImage(image, -image.width / 2, 0);
3698                    cropImage = cropContext.getImageData(0, 0, image.width / 2, image.height);
3699                    gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);
3700
3701                    // Set parameters for rendering any size
3702                    gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3703                    gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3704                    gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
3705                    gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
3706
3707                    // Reactivate first texture unit
3708                    gl.activeTexture(gl.TEXTURE0);
3709                }
3710            }
3711
3712            // Set parameters for rendering any size
3713            gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3714            gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3715            gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
3716            gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
3717
3718        } else {
3719            // Look up vertex coordinates location
3720            program.vertPosLocation = gl.getAttribLocation(program, 'a_vertCoord');
3721            gl.enableVertexAttribArray(program.vertPosLocation);
3722
3723            // Create buffers
3724            if (!cubeVertBuf)
3725                cubeVertBuf = gl.createBuffer();
3726            if (!cubeVertTexCoordBuf)
3727                cubeVertTexCoordBuf = gl.createBuffer();
3728            if (!cubeVertIndBuf)
3729                cubeVertIndBuf = gl.createBuffer();
3730
3731            // Bind texture coordinate buffer and pass coordinates to WebGL
3732            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertTexCoordBuf);
3733            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0,1,0,1,1,0,1]), gl.STATIC_DRAW);
3734
3735            // Bind square index buffer and pass indicies to WebGL
3736            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertIndBuf);
3737            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2,0,2,3]), gl.STATIC_DRAW);
3738
3739            // Find uniforms
3740            program.perspUniform = gl.getUniformLocation(program, 'u_perspMatrix');
3741            program.cubeUniform = gl.getUniformLocation(program, 'u_cubeMatrix');
3742            //program.colorUniform = gl.getUniformLocation(program, 'u_color');
3743
3744            program.level = -1;
3745
3746            program.currentNodes = [];
3747            program.nodeCache = [];
3748            program.nodeCacheTimestamp = 0;
3749        }
3750
3751        // Check if there was an error
3752        var err = gl.getError();
3753        if (err !== 0) {
3754            console.log('Error: Something went wrong with WebGL!', err);
3755            throw {type: 'webgl error'};
3756        }
3757
3758        callback();
3759     };
3760
3761    /**
3762     * Destroy renderer.
3763     * @memberof Renderer
3764     * @instance
3765     */
3766    this.destroy = function() {
3767        if (container !== undefined) {
3768            if (canvas !== undefined && container.contains(canvas)) {
3769                container.removeChild(canvas);
3770            }
3771            if (world !== undefined && container.contains(world)) {
3772                container.removeChild(world);
3773            }
3774        }
3775        if (gl) {
3776            // The spec says this is only supposed to simulate losing the WebGL
3777            // context, but in practice it tends to actually free the memory.
3778            var extension = gl.getExtension('WEBGL_lose_context');
3779            if (extension)
3780                extension.loseContext();
3781        }
3782    };
3783
3784    /**
3785     * Resize renderer (call after resizing container).
3786     * @memberof Renderer
3787     * @instance
3788     */
3789    this.resize = function() {
3790        var pixelRatio = window.devicePixelRatio || 1;
3791        canvas.width = canvas.clientWidth * pixelRatio;
3792        canvas.height = canvas.clientHeight * pixelRatio;
3793        if (gl) {
3794            if (gl.getError() == 1286)
3795                handleWebGLError1286();
3796            gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
3797            if (imageType != 'multires') {
3798                gl.uniform1f(program.aspectRatio, canvas.clientWidth / canvas.clientHeight);
3799            }
3800        }
3801    };
3802    // Initialize canvas size
3803    this.resize();
3804
3805    /**
3806     * Set renderer horizon pitch and roll.
3807     * @memberof Renderer
3808     * @instance
3809     */
3810    this.setPose = function(horizonPitch, horizonRoll) {
3811        pose = [horizonPitch, horizonRoll];
3812    };
3813
3814    /**
3815     * Render new view of panorama.
3816     * @memberof Renderer
3817     * @instance
3818     * @param {number} pitch - Pitch to render at (in radians).
3819     * @param {number} yaw - Yaw to render at (in radians).
3820     * @param {number} hfov - Horizontal field of view to render with (in radians).
3821     * @param {Object} [params] - Extra configuration parameters. 
3822     * @param {number} [params.roll] - Camera roll (in radians).
3823     * @param {boolean} [params.returnImage] - Return rendered image?
3824     */
3825    this.render = function(pitch, yaw, hfov, params) {
3826        var focal, i, s, roll = 0;
3827        if (params === undefined)
3828            params = {};
3829        if (params.roll)
3830            roll = params.roll;
3831
3832        // Apply pitch and roll transformation if applicable
3833        if (pose !== undefined) {
3834            var horizonPitch = pose[0],
3835                horizonRoll = pose[1];
3836
3837            // Calculate new pitch and yaw
3838            var orig_pitch = pitch,
3839                orig_yaw = yaw,
3840                x = Math.cos(horizonRoll) * Math.sin(pitch) * Math.sin(horizonPitch) +
3841                    Math.cos(pitch) * (Math.cos(horizonPitch) * Math.cos(yaw) +
3842                    Math.sin(horizonRoll) * Math.sin(horizonPitch) * Math.sin(yaw)),
3843                y = -Math.sin(pitch) * Math.sin(horizonRoll) +
3844                    Math.cos(pitch) * Math.cos(horizonRoll) * Math.sin(yaw),
3845                z = Math.cos(horizonRoll) * Math.cos(horizonPitch) * Math.sin(pitch) +
3846                    Math.cos(pitch) * (-Math.cos(yaw) * Math.sin(horizonPitch) +
3847                    Math.cos(horizonPitch) * Math.sin(horizonRoll) * Math.sin(yaw));
3848            pitch = Math.asin(Math.max(Math.min(z, 1), -1));
3849            yaw = Math.atan2(y, x);
3850
3851            // Calculate roll
3852            var v = [Math.cos(orig_pitch) * (Math.sin(horizonRoll) * Math.sin(horizonPitch) * Math.cos(orig_yaw) -
3853                    Math.cos(horizonPitch) * Math.sin(orig_yaw)),
3854                    Math.cos(orig_pitch) * Math.cos(horizonRoll) * Math.cos(orig_yaw),
3855                    Math.cos(orig_pitch) * (Math.cos(horizonPitch) * Math.sin(horizonRoll) * Math.cos(orig_yaw) +
3856                    Math.sin(orig_yaw) * Math.sin(horizonPitch))],
3857                w = [-Math.cos(pitch) * Math.sin(yaw), Math.cos(pitch) * Math.cos(yaw)];
3858            var roll_adj = Math.acos(Math.max(Math.min((v[0]*w[0] + v[1]*w[1]) /
3859                (Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]) *
3860                Math.sqrt(w[0]*w[0]+w[1]*w[1])), 1), -1));
3861            if (v[2] < 0)
3862                roll_adj = 2 * Math.PI - roll_adj;
3863            roll += roll_adj;
3864        }
3865
3866        // If no WebGL
3867        if (!gl && (imageType == 'multires' || imageType == 'cubemap')) {
3868            // Determine face transforms
3869            s = fallbackImgSize / 2;
3870            
3871            var transforms = {
3872                f: 'translate3d(-' + (s + 2) + 'px, -' + (s + 2) + 'px, -' + s + 'px)',
3873                b: 'translate3d(' + (s + 2) + 'px, -' + (s + 2) + 'px, ' + s + 'px) rotateX(180deg) rotateZ(180deg)',
3874                u: 'translate3d(-' + (s + 2) + 'px, -' + s + 'px, ' + (s + 2) + 'px) rotateX(270deg)',
3875                d: 'translate3d(-' + (s + 2) + 'px, ' + s + 'px, -' + (s + 2) + 'px) rotateX(90deg)',
3876                l: 'translate3d(-' + s + 'px, -' + (s + 2) + 'px, ' + (s + 2) + 'px) rotateX(180deg) rotateY(90deg) rotateZ(180deg)',
3877                r: 'translate3d(' + s + 'px, -' + (s + 2) + 'px, -' + (s + 2) + 'px) rotateY(270deg)'
3878            };
3879            focal = 1 / Math.tan(hfov / 2);
3880            var zoom = focal * canvas.clientWidth / 2 + 'px';
3881            var transform = 'perspective(' + zoom + ') translateZ(' + zoom + ') rotateX(' + pitch + 'rad) rotateY(' + yaw + 'rad) ';
3882            
3883            // Apply face transforms
3884            var faces = Object.keys(transforms);
3885            for (i = 0; i < 6; i++) {
3886                var face = world.querySelector('.pnlm-' + faces[i] + 'face');
3887                if (!face)
3888                    continue; // ignore missing face to support partial cubemap/fallback image
3889                face.style.webkitTransform = transform + transforms[faces[i]];
3890                face.style.transform = transform + transforms[faces[i]];
3891            }
3892            return;
3893        }
3894        
3895        if (imageType != 'multires') {
3896            // Calculate focal length from vertical field of view
3897            var vfov = 2 * Math.atan(Math.tan(hfov * 0.5) / (gl.drawingBufferWidth / gl.drawingBufferHeight));
3898            focal = 1 / Math.tan(vfov * 0.5);
3899
3900            // Pass psi, theta, roll, and focal length
3901            gl.uniform1f(program.psi, yaw);
3902            gl.uniform1f(program.theta, pitch);
3903            gl.uniform1f(program.rot, roll);
3904            gl.uniform1f(program.f, focal);
3905            
3906            if (dynamic === true) {
3907                // Update texture if dynamic
3908                if (imageType == 'equirectangular') {
3909                    gl.bindTexture(gl.TEXTURE_2D, program.texture);
3910                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
3911                }
3912            }
3913            
3914            // Draw using current buffer
3915            gl.drawArrays(gl.TRIANGLES, 0, 6);
3916        
3917        } else {
3918            // Create perspective matrix
3919            var perspMatrix = makePersp(hfov, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 100.0);
3920            
3921            // Find correct zoom level
3922            checkZoom(hfov);
3923            
3924            // Create rotation matrix
3925            var matrix = identityMatrix3();
3926            matrix = rotateMatrix(matrix, -roll, 'z');
3927            matrix = rotateMatrix(matrix, -pitch, 'x');
3928            matrix = rotateMatrix(matrix, yaw, 'y');
3929            matrix = makeMatrix4(matrix);
3930            
3931            // Set matrix uniforms
3932            gl.uniformMatrix4fv(program.perspUniform, false, new Float32Array(trans
vendor: 16,328 bytes, lines 3932-4334
3932poseMatrix4(perspMatrix)));
3933            gl.uniformMatrix4fv(program.cubeUniform, false, new Float32Array(transposeMatrix4(matrix)));
3934            
3935            // Find current nodes
3936            var rotPersp = rotatePersp(perspMatrix, matrix);
3937            program.nodeCache.sort(multiresNodeSort);
3938            if (program.nodeCache.length > 200 &&
3939                program.nodeCache.length > program.currentNodes.length + 50) {
3940                // Remove older nodes from cache
3941                var removed = program.nodeCache.splice(200, program.nodeCache.length - 200);
3942                for (var j = 0; j < removed.length; j++) {
3943                    // Explicitly delete textures
3944                    gl.deleteTexture(removed[j].texture);
3945                }
3946            }
3947            program.currentNodes = [];
3948            
3949            var sides = ['f', 'b', 'u', 'd', 'l', 'r'];
3950            for (s = 0; s < 6; s++) {
3951                var ntmp = new MultiresNode(vtmps[s], sides[s], 1, 0, 0, image.fullpath);
3952                testMultiresNode(rotPersp, ntmp, pitch, yaw, hfov);
3953            }
3954            
3955            program.currentNodes.sort(multiresNodeRenderSort);
3956            
3957            // Unqueue any pending requests for nodes that are no longer visible
3958            for (i = pendingTextureRequests.length - 1; i >= 0; i--) {
3959                if (program.currentNodes.indexOf(pendingTextureRequests[i].node) === -1) {
3960                    pendingTextureRequests[i].node.textureLoad = false;
3961                    pendingTextureRequests.splice(i, 1);
3962                }
3963            }
3964            
3965            // Allow one request to be pending, so that we can create a texture buffer for that in advance of loading actually beginning
3966            if (pendingTextureRequests.length === 0) {
3967                for (i = 0; i < program.currentNodes.length; i++) {
3968                    var node = program.currentNodes[i];
3969                    if (!node.texture && !node.textureLoad) {
3970                        node.textureLoad = true;
3971            
3972                        setTimeout(processNextTile, 0, node);
3973                        
3974                        // Only process one tile per frame to improve responsiveness
3975                        break;
3976                    }
3977                }
3978            }
3979            
3980            // Draw tiles
3981            multiresDraw();
3982        }
3983        
3984        if (params.returnImage !== undefined) {
3985            return canvas.toDataURL('image/png');
3986        }
3987    };
3988    
3989    /**
3990     * Check if images are loading.
3991     * @memberof Renderer
3992     * @instance
3993     * @returns {boolean} Whether or not images are loading.
3994     */
3995    this.isLoading = function() {
3996        if (gl && imageType == 'multires') {
3997            for ( var i = 0; i < program.currentNodes.length; i++ ) {
3998                if (!program.currentNodes[i].textureLoaded) {
3999                    return true;
4000                }
4001            }
4002        }
4003        return false;
4004    };
4005    
4006    /**
4007     * Retrieve renderer's canvas.
4008     * @memberof Renderer
4009     * @instance
4010     * @returns {HTMLElement} Renderer's canvas.
4011     */
4012    this.getCanvas = function() {
4013        return canvas;
4014    };
4015    
4016    /**
4017     * Sorting method for multires nodes.
4018     * @private
4019     * @param {MultiresNode} a - First node.
4020     * @param {MultiresNode} b - Second node.
4021     * @returns {number} Base tiles first, then higher timestamp first.
4022     */
4023    function multiresNodeSort(a, b) {
4024        // Base tiles are always first
4025        if (a.level == 1 && b.level != 1) {
4026            return -1;
4027        }
4028        if (b. level == 1 && a.level != 1) {
4029            return 1;
4030        }
4031        
4032        // Higher timestamp first
4033        return b.timestamp - a.timestamp;
4034    }
4035    
4036    /**
4037     * Sorting method for multires node rendering.
4038     * @private
4039     * @param {MultiresNode} a - First node.
4040     * @param {MultiresNode} b - Second node.
4041     * @returns {number} Lower zoom levels first, then closest to center first.
4042     */
4043    function multiresNodeRenderSort(a, b) {
4044        // Lower zoom levels first
4045        if (a.level != b.level) {
4046            return a.level - b.level;
4047        }
4048        
4049        // Lower distance from center first
4050        return a.diff - b.diff;
4051    }
4052    
4053    /**
4054     * Draws multires nodes.
4055     * @private
4056     */
4057    function multiresDraw() {
4058        if (!program.drawInProgress) {
4059            program.drawInProgress = true;
4060            gl.clear(gl.COLOR_BUFFER_BIT);
4061            for ( var i = 0; i < program.currentNodes.length; i++ ) {
4062                if (program.currentNodes[i].textureLoaded > 1) {
4063                    //var color = program.currentNodes[i].color;
4064                    //gl.uniform4f(program.colorUniform, color[0], color[1], color[2], 1.0);
4065                    
4066                    // Bind vertex buffer and pass vertices to WebGL
4067                    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertBuf);
4068                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(program.currentNodes[i].vertices), gl.STATIC_DRAW);
4069                    gl.vertexAttribPointer(program.vertPosLocation, 3, gl.FLOAT, false, 0, 0);
4070                    
4071                    // Prep for texture
4072                    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertTexCoordBuf);
4073                    gl.vertexAttribPointer(program.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
4074                    
4075                    // Bind texture and draw tile
4076                    gl.bindTexture(gl.TEXTURE_2D, program.currentNodes[i].texture); // Bind program.currentNodes[i].texture to TEXTURE0
4077                    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
4078                }
4079            }
4080            program.drawInProgress = false;
4081        }
4082    }
4083
4084    /**
4085     * Creates new multires node.
4086     * @constructor
4087     * @private
4088     * @param {number[]} vertices - Node's verticies.
4089     * @param {string} side - Node's cube face.
4090     * @param {number} level - Node's zoom level.
4091     * @param {number} x - Node's x position.
4092     * @param {number} y - Node's y position.
4093     * @param {string} path - Node's path.
4094     */
4095    function MultiresNode(vertices, side, level, x, y, path) {
4096        this.vertices = vertices;
4097        this.side = side;
4098        this.level = level;
4099        this.x = x;
4100        this.y = y;
4101        this.path = path.replace('%s',side).replace('%l',level).replace('%x',x).replace('%y',y);
4102    }
4103
4104    /**
4105     * Test if multires node is visible. If it is, add it to current nodes,
4106     * load its texture, and load appropriate child nodes.
4107     * @private
4108     * @param {number[]} rotPersp - Rotated perspective matrix.
4109     * @param {MultiresNode} node - Multires node to check.
4110     * @param {number} pitch - Pitch to check at.
4111     * @param {number} yaw - Yaw to check at.
4112     * @param {number} hfov - Horizontal field of view to check at.
4113     */
4114    function testMultiresNode(rotPersp, node, pitch, yaw, hfov) {
4115        if (checkSquareInView(rotPersp, node.vertices)) {
4116            // Calculate central angle between center of view and center of tile
4117            var v = node.vertices;
4118            var x = v[0] + v[3] + v[6] + v[ 9];
4119            var y = v[1] + v[4] + v[7] + v[10];
4120            var z = v[2] + v[5] + v[8] + v[11];
4121            var r = Math.sqrt(x*x + y*y + z*z);
4122            var theta = Math.asin(z / r);
4123            var phi = Math.atan2(y, x);
4124            var ydiff = phi - yaw;
4125            ydiff += (ydiff > Math.PI) ? -2 * Math.PI : (ydiff < -Math.PI) ? 2 * Math.PI : 0;
4126            ydiff = Math.abs(ydiff);
4127            node.diff = Math.acos(Math.sin(pitch) * Math.sin(theta) + Math.cos(pitch) * Math.cos(theta) * Math.cos(ydiff));
4128            
4129            // Add node to current nodes and load texture if needed
4130            var inCurrent = false;
4131            for (var k = 0; k < program.nodeCache.length; k++) {
4132                if (program.nodeCache[k].path == node.path) {
4133                    inCurrent = true;
4134                    program.nodeCache[k].timestamp = program.nodeCacheTimestamp++;
4135                    program.nodeCache[k].diff = node.diff;
4136                    program.currentNodes.push(program.nodeCache[k]);
4137                    break;
4138                }
4139            }
4140            if (!inCurrent) {
4141                //node.color = [Math.random(), Math.random(), Math.random()];
4142                node.timestamp = program.nodeCacheTimestamp++;
4143                program.currentNodes.push(node);
4144                program.nodeCache.push(node);
4145            }
4146            
4147            // TODO: Test error
4148            // Create child nodes
4149            if (node.level < program.level) {
4150                var cubeSize = image.cubeResolution * Math.pow(2, node.level - image.maxLevel);
4151                var numTiles = Math.ceil(cubeSize * image.invTileResolution) - 1;
4152                var doubleTileSize = cubeSize % image.tileResolution * 2;
4153                var lastTileSize = (cubeSize * 2) % image.tileResolution;
4154                if (lastTileSize === 0) {
4155                    lastTileSize = image.tileResolution;
4156                }
4157                if (doubleTileSize === 0) {
4158                    doubleTileSize = image.tileResolution * 2;
4159                }
4160                var f = 0.5;
4161                if (node.x == numTiles || node.y == numTiles) {
4162                    f = 1.0 - image.tileResolution / (image.tileResolution + lastTileSize);
4163                }
4164                var i = 1.0 - f;
4165                var children = [];
4166                var vtmp, ntmp;
4167                var f1 = f, f2 = f, f3 = f, i1 = i, i2 = i, i3 = i;
4168                // Handle non-symmetric tiles
4169                if (lastTileSize < image.tileResolution) {
4170                    if (node.x == numTiles && node.y != numTiles) {
4171                        f2 = 0.5;
4172                        i2 = 0.5;
4173                        if (node.side == 'd' || node.side == 'u') {
4174                            f3 = 0.5;
4175                            i3 = 0.5;
4176                        }
4177                    } else if (node.x != numTiles && node.y == numTiles) {
4178                        f1 = 0.5;
4179                        i1 = 0.5;
4180                        if (node.side == 'l' || node.side == 'r') {
4181                            f3 = 0.5;
4182                            i3 = 0.5;
4183                        }
4184                    }
4185                }
4186                // Handle small tiles that have fewer than four children
4187                if (doubleTileSize <= image.tileResolution) {
4188                    if (node.x == numTiles) {
4189                        f1 = 0;
4190                        i1 = 1;
4191                        if (node.side == 'l' || node.side == 'r') {
4192                            f3 = 0;
4193                            i3 = 1;
4194                        }
4195                    }
4196                    if (node.y == numTiles) {
4197                        f2 = 0;
4198                        i2 = 1;
4199                        if (node.side == 'd' || node.side == 'u') {
4200                            f3 = 0;
4201                            i3 = 1;
4202                        }
4203                    }
4204                }
4205                
4206                vtmp = [           v[0],             v[1],             v[2],
4207                        v[0]*f1+v[3]*i1,    v[1]*f+v[4]*i,  v[2]*f3+v[5]*i3,
4208                        v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
4209                          v[0]*f+v[9]*i, v[1]*f2+v[10]*i2, v[2]*f3+v[11]*i3
4210                ];
4211                ntmp = new MultiresNode(vtmp, node.side, node.level + 1, node.x*2, node.y*2, image.fullpath);
4212                children.push(ntmp);
4213                if (!(node.x == numTiles && doubleTileSize <= image.tileResolution)) {
4214                    vtmp = [v[0]*f1+v[3]*i1,    v[1]*f+v[4]*i,  v[2]*f3+v[5]*i3,
4215                                       v[3],             v[4],             v[5],
4216                              v[3]*f+v[6]*i,  v[4]*f2+v[7]*i2,  v[5]*f3+v[8]*i3,
4217                            v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3
4218                    ];
4219                    ntmp = new MultiresNode(vtmp, node.side, node.level + 1, node.x*2+1, node.y*2, image.fullpath);
4220                    children.push(ntmp);
4221                }
4222                if (!(node.x == numTiles && doubleTileSize <= image.tileResolution) &&
4223                    !(node.y == numTiles && doubleTileSize <= image.tileResolution)) {
4224                    vtmp = [v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
4225                              v[3]*f+v[6]*i,  v[4]*f2+v[7]*i2,  v[5]*f3+v[8]*i3,
4226                                       v[6],             v[7],             v[8],
4227                            v[9]*f1+v[6]*i1,   v[10]*f+v[7]*i, v[11]*f3+v[8]*i3
4228                    ];
4229                    ntmp = new MultiresNode(vtmp, node.side, node.level + 1, node.x*2+1, node.y*2+1, image.fullpath);
4230                    children.push(ntmp);
4231                }
4232                if (!(node.y == numTiles && doubleTileSize <= image.tileResolution)) {
4233                    vtmp = [  v[0]*f+v[9]*i, v[1]*f2+v[10]*i2, v[2]*f3+v[11]*i3,
4234                            v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
4235                            v[9]*f1+v[6]*i1,   v[10]*f+v[7]*i, v[11]*f3+v[8]*i3,
4236                                       v[9],            v[10],            v[11]
4237                    ];
4238                    ntmp = new MultiresNode(vtmp, node.side, node.level + 1, node.x*2, node.y*2+1, image.fullpath);
4239                    children.push(ntmp);
4240                }
4241                for (var j = 0; j < children.length; j++) {
4242                    testMultiresNode(rotPersp, children[j], pitch, yaw, hfov);
4243                }
4244            }
4245        }
4246    }
4247    
4248    /**
4249     * Creates cube vertex array.
4250     * @private
4251     * @returns {number[]} Cube vertex array.
4252     */
4253    function createCube() {
4254        return [-1,  1, -1,  1,  1, -1,  1, -1, -1, -1, -1, -1, // Front face
4255                 1,  1,  1, -1,  1,  1, -1, -1,  1,  1, -1,  1, // Back face
4256                -1,  1,  1,  1,  1,  1,  1,  1, -1, -1,  1, -1, // Up face
4257                -1, -1, -1,  1, -1, -1,  1, -1,  1, -1, -1,  1, // Down face
4258                -1,  1,  1, -1,  1, -1, -1, -1, -1, -1, -1,  1, // Left face
4259                 1,  1, -1,  1,  1,  1,  1, -1,  1,  1, -1, -1  // Right face
4260        ];
4261    }
4262    
4263    /**
4264     * Creates 3x3 identity matrix.
4265     * @private
4266     * @returns {number[]} Identity matrix.
4267     */
4268    function identityMatrix3() {
4269        return [
4270            1, 0, 0,
4271            0, 1, 0,
4272            0, 0, 1
4273        ];
4274    }
4275    
4276    /**
4277     * Rotates a 3x3 matrix.
4278     * @private
4279     * @param {number[]} m - Matrix to rotate.
4280     * @param {number[]} angle - Angle to rotate by in radians.
4281     * @param {string} axis - Axis to rotate about (`x`, `y`, or `z`).
4282     * @returns {number[]} Rotated matrix.
4283     */
4284    function rotateMatrix(m, angle, axis) {
4285        var s = Math.sin(angle);
4286        var c = Math.cos(angle);
4287        if (axis == 'x') {
4288            return [
4289                m[0], c*m[1] + s*m[2], c*m[2] - s*m[1],
4290                m[3], c*m[4] + s*m[5], c*m[5] - s*m[4],
4291                m[6], c*m[7] + s*m[8], c*m[8] - s*m[7]
4292            ];
4293        }
4294        if (axis == 'y') {
4295            return [
4296                c*m[0] - s*m[2], m[1], c*m[2] + s*m[0],
4297                c*m[3] - s*m[5], m[4], c*m[5] + s*m[3],
4298                c*m[6] - s*m[8], m[7], c*m[8] + s*m[6]
4299            ];
4300        }
4301        if (axis == 'z') {
4302            return [
4303                c*m[0] + s*m[1], c*m[1] - s*m[0], m[2],
4304                c*m[3] + s*m[4], c*m[4] - s*m[3], m[5],
4305                c*m[6] + s*m[7], c*m[7] - s*m[6], m[8]
4306            ];
4307        }
4308    }
4309    
4310    /**
4311     * Turns a 3x3 matrix into a 4x4 matrix.
4312     * @private
4313     * @param {number[]} m - Input matrix.
4314     * @returns {number[]} Expanded matrix.
4315     */
4316    function makeMatrix4(m) {
4317        return [
4318            m[0], m[1], m[2],    0,
4319            m[3], m[4], m[5],    0,
4320            m[6], m[7], m[8],    0,
4321               0,    0,    0,    1
4322        ];
4323    }
4324    
4325    /**
4326     * Transposes a 4x4 matrix.
4327     * @private
4328     * @param {number[]} m - Input matrix.
4329     * @returns {number[]} Transposed matrix.
4330     */
4331    function transposeMatrix4(m) {
4332        return [
4333            m[ 0], m[ 4], m[ 8], m[12],
4334            m[ 1], m[ 5], m[ 9], m[13],
4335            m[ 2], m[ 6], m[10], m[14],
4336            m[ 3], m[ 7], m[11], m[15]
4337        ];
4338    }
4339    
4340    /**
4341     * Creates a perspective matrix.
4342     * @private
4343     * @param {number} hfov - Desired horizontal field of view.
4344     * @param {number} aspect - Desired aspect ratio.
4345     * @param {number} znear - Near distance.
4346     * @param {number} zfar - Far distance.
4347     * @returns {number[]} Generated perspective matrix.
4348     */
4349    function makePersp(hfov, aspect, znear, zfar) {
4350        var fovy = 2 * Math.atan(Math.tan(hfov/2) * gl.drawingBufferHeight / gl.drawingBufferWidth);
4351        var f = 1 / Math.tan(fovy/2);
4352        return [
4353            f/aspect,   0,  0,  0,
4354                   0,   f,  0,  0,
4355                   0,   0,  (zfar+znear)/(znear-zfar), (2*zfar*znear)/(znear-zfar),
4356                   0,   0, -1,  0
4357        ];
4358    }
4359    
4360    /**
4361     * Processes a loaded texture image into a WebGL texture.
4362     * @private
4363     * @param {Image} img - Input image.
4364     * @param {WebGLTexture} tex - Texture to bind image to.
4365     */
4366    function processLoadedTexture(img, tex) {
4367        gl.bindTexture(gl.TEXTURE_2D, tex);
4368        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);
4369        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
4370        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
4371        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
4372        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
4373        gl.bindTexture(gl.TEXTURE_2D, null);
4374    }
4375    
4376    var pendingTextureRequests = [];
4377
4378    // Based on http://blog.tojicode.com/2012/03/javascript-memory-optimization-and.html
4379    var loadTexture = (function() {
4380        var cacheTop = 4;   // Maximum number of concurrents loads
4381        var textureImageCache = {};
4382        var crossOrigin;
4383
4384        function TextureImageLoader() {
4385            var self = this;
4386            this.texture = this.callback = null;
4387            this.image = new Image();
4388            this.image.crossOrigin = crossOrigin ? crossOrigin : 'anonymous';
4389            var loadFn = (function() {
4390                if (self.image.width > 0 && self.image.height > 0) { // ignore missing tile to supporting partial image
4391                    processLoadedTexture(self.image, self.texture);
4392                    self.callback(self.texture, true);
4393                } else {
4394                    self.callback(self.texture, false);
4395                }
4396                releaseTextureImageLoader(self);
4397            });
4398            this.image.addEventListener('load', loadFn);
4399            this.image.addEventListener('error', loadFn); // ignore missing tile file to support partial image, otherwise retry loop causes high CPU load
4400        }
4401
4402        TextureImageLoader.prototype.loadTexture = function(src, texture, callback) {
4403            this.texture = texture;
4404            this.callback = callback;
4405            this.image.src = src;
4406        };
4407
4408        function PendingTextureRequest(node, src, texture, callback) {
4409            this.node = node;
4410            this.src = src;
4411            this.texture = texture;
4412            this.callback = callback;
4413        }
4414
4415        function releaseTextureImageLoader(til) {
4416            if (pendingTextureRequests.length) {
4417                var req = pendingTextureRequests.shift();
4418                til.loadTexture(req.src, req.texture, req.callback);
4419            } else
4420                textureImageCache[cacheTop++] = til;
4421        }
4422
4423        for (var i = 0; i < cacheTop; i++)
4424            textureImageCache[i] = new TextureImageLoader();
4425
4426        return function(node, src, callback, _crossOrigin) {
4427            crossOrigin = _crossOrigin;
4428            var texture = gl.createTexture();
4429            if (cacheTop)
4430                textureImageCache[--cacheTop].loadTexture(src, texture, callback);
4431            else
4432                pendingTextureRequests.push(new PendingTextureRequest(node, src, texture, callback));
4433            return texture;
4434        };
4435    })();
4436
4437    /**
4438     * Loads image and creates texture for a multires node / tile.
4439     * @private
4440     * @param {MultiresNode} node - Input node.
4441     */
4442    function processNextTile(node) {
4443        loadTexture(node, node.path + '.' + image.extension, function(texture, loaded) {
4444            node.texture = texture;
4445            node.textureLoaded = loaded ? 2 : 1;
4446        }, globalParams.crossOrigin);
4447    }
4448    
4449    /**
4450     * Finds and applies optimal multires zoom level.
4451     * @private
4452     * @param {number} hfov - Horizontal field of view to check at.
4453     */
4454    function checkZoom(hfov) {
4455        // Find optimal level
4456        var newLevel = 1;
4457        while ( newLevel < image.maxLevel &&
4458            gl.drawingBufferWidth >
4458 image.tileResolution *
4459            Math.pow(2, newLevel - 1) * Math.tan(hfov / 2) * 0.707 ) {
4460            newLevel++;
4461        }
4462        
4463        // Apply change
4464        program.level = newLevel;
4465    }
4466    
4467    /**
4468     * Rotates perspective matrix.
4469     * @private
4470     * @param {number[]} p - Perspective matrix.
4471     * @param {number[]} r - Rotation matrix.
4472     * @returns {number[]} Rotated matrix.
4473     */
4474    function rotatePersp(p, r) {
4475        return [
4476            p[ 0]*r[0], p[ 0]*r[1], p[ 0]*r[ 2],     0,
4477            p[ 5]*r[4], p[ 5]*r[5], p[ 5]*r[ 6],     0,
4478            p[10]*r[8], p[10]*r[9], p[10]*r[10], p[11],
4479                 -r[8],      -r[9],      -r[10],     0
4480        ];
4481    }
4482    
4483    /**
4484     * Applies rotated perspective matrix to a 3-vector
4485     * (last element is inverted).
4486     * @private
4487     * @param {number[]} m - Rotated perspective matrix.
4488     * @param {number[]} v - Input 3-vector.
4489     * @returns {number[]} Resulting 4-vector.
4490     */
4491    function applyRotPerspToVec(m, v) {
4492        return [
4493                    m[ 0]*v[0] + m[ 1]*v[1] + m[ 2]*v[2],
4494                    m[ 4]*v[0] + m[ 5]*v[1] + m[ 6]*v[2],
4495            m[11] + m[ 8]*v[0] + m[ 9]*v[1] + m[10]*v[2],
4496                 1/(m[12]*v[0] + m[13]*v[1] + m[14]*v[2])
4497        ];
4498    }
4499    
4500    /**
4501     * Checks if a vertex is visible.
4502     * @private
4503     * @param {number[]} m - Rotated perspective matrix.
4504     * @param {number[]} v - Input vertex.
4505     * @returns {number} 1 or -1 if the vertex is or is not visible,
4506     *      respectively.
4507     */
4508    function checkInView(m, v) {
4509        var vpp = applyRotPerspToVec(m, v);
4510        var winX = vpp[0]*vpp[3];
4511        var winY = vpp[1]*vpp[3];
4512        var winZ = vpp[2]*vpp[3];
4513        var ret = [0, 0, 0];
4514        
4515        if ( winX < -1 )
4516            ret[0] = -1;
4517        if ( winX > 1 )
4518            ret[0] = 1;
4519        if ( winY < -1 )
4520            ret[1] = -1;
4521        if ( winY > 1 )
4522            ret[1] = 1;
4523        if ( winZ < -1 || winZ > 1 )
4524            ret[2] = 1;
4525        return ret;
4526    }
4527    
4528    /**
4529     * Checks if a square (tile) is visible.
4530     * @private
4531     * @param {number[]} m - Rotated perspective matrix.
4532     * @param {number[]} v - Square's vertex array.
4533     * @returns {boolean} Whether or not the square is visible.
4534     */
4535    function checkSquareInView(m, v) {
4536        var check1 = checkInView(m, v.slice(0, 3));
4537        var check2 = checkInView(m, v.slice(3, 6));
4538        var check3 = checkInView(m, v.slice(6, 9));
4539        var check4 = checkInView(m, v.slice(9, 12));
4540        var testX = check1[0] + check2[0] + check3[0] + check4[0];
4541        if ( testX == -4 || testX == 4 )
4542            return false;
4543        var testY = check1[1] + check2[1] + check3[1] + check4[1];
4544        if ( testY == -4 || testY == 4 )
4545            return false;
4546        var testZ = check1[2] + check2[2] + check3[2] + check4[2];
4547        return testZ != 4;
4548        
4549
4550    }
4551
4552    /**
4553     * On iOS (iPhone 5c, iOS 10.3), this WebGL error occurs when the canvas is
4554     * too big. Unfortuately, there's no way to test for this beforehand, so we
4555     * reduce the canvas size if this error is thrown.
4556     * @private
4557     */
4558    function handleWebGLError1286() {
4559        console.log('Reducing canvas size due to error 1286!');
4560        canvas.width = Math.round(canvas.width / 2);
4561        canvas.height = Math.round(canvas.height / 2);
4562    }
4563}
4564
4565// Vertex shader for equirectangular and cube
4566var v = [
4567'attribute vec2 a_texCoord;',
4568'varying vec2 v_texCoord;',
4569
4570'void main() {',
4571    // Set position
4572    'gl_Position = vec4(a_texCoord, 0.0, 1.0);',
4573    
4574    // Pass the coordinates to the fragment shader
4575    'v_texCoord = a_texCoord;',
4576'}'
4577].join('');
4578
4579// Vertex shader for multires
4580var vMulti = [
4581'attribute vec3 a_vertCoord;',
4582'attribute vec2 a_texCoord;',
4583
4584'uniform mat4 u_cubeMatrix;',
4585'uniform mat4 u_perspMatrix;',
4586
4587'varying mediump vec2 v_texCoord;',
4588
4589'void main(void) {',
4590    // Set position
4591    'gl_Position = u_perspMatrix * u_cubeMatrix * vec4(a_vertCoord, 1.0);',
4592    
4593    // Pass the coordinates to the fragment shader
4594    'v_texCoord = a_texCoord;',
4595'}'
4596].join('');
4597
4598// Fragment shader
4599var fragEquiCubeBase = [
4600'precision highp float;', // mediump looks bad on some mobile devices
4601
4602'uniform float u_aspectRatio;',
4603'uniform float u_psi;',
4604'uniform float u_theta;',
4605'uniform float u_f;',
4606'uniform float u_h;',
4607'uniform float u_v;',
4608'uniform float u_vo;',
4609'uniform float u_rot;',
4610
4611'const float PI = 3.14159265358979323846264;',
4612
4613// Texture
4614'uniform sampler2D u_image0;',
4615'uniform sampler2D u_image1;',
4616'uniform bool u_splitImage;',
4617'uniform samplerCube u_imageCube;',
4618
4619// Coordinates passed in from vertex shader
4620'varying vec2 v_texCoord;',
4621
4622// Background color (display for partial panoramas)
4623'uniform vec4 u_backgroundColor;',
4624
4625'void main() {',
4626    // Map canvas/camera to sphere
4627    'float x = v_texCoord.x * u_aspectRatio;',
4628    'float y = v_texCoord.y;',
4629    'float sinrot = sin(u_rot);',
4630    'float cosrot = cos(u_rot);',
4631    'float rot_x = x * cosrot - y * sinrot;',
4632    'float rot_y = x * sinrot + y * cosrot;',
4633    'float sintheta = sin(u_theta);',
4634    'float costheta = cos(u_theta);',
4635    'float a = u_f * costheta - rot_y * sintheta;',
4636    'float root = sqrt(rot_x * rot_x + a * a);',
4637    'float lambda = atan(rot_x / root, a / root) + u_psi;',
4638    'float phi = atan((rot_y * costheta + u_f * sintheta) / root);',
4639].join('\n');
4640
4641// Fragment shader
4642var fragCube = fragEquiCubeBase + [
4643    // Look up color from texture
4644    'float cosphi = cos(phi);',
4645    'gl_FragColor = textureCube(u_imageCube, vec3(cosphi*sin(lambda), sin(phi), cosphi*cos(lambda)));',
4646'}'
4647].join('\n');
4648
4649// Fragment shader
4650var fragEquirectangular = fragEquiCubeBase + [
4651    // Wrap image
4652    'lambda = mod(lambda + PI, PI * 2.0) - PI;',
4653
4654    // Map texture to sphere
4655    'vec2 coord = vec2(lambda / PI, phi / (PI / 2.0));',
4656
4657    // Look up color from texture
4658    // Map from [-1,1] to [0,1] and flip y-axis
4659    'if(coord.x < -u_h || coord.x > u_h || coord.y < -u_v + u_vo || coord.y > u_v + u_vo)',
4660        'gl_FragColor = u_backgroundColor;',
4661    'else {',
4662        'if(u_splitImage) {',
4663            // Image was split into two textures to work around texture size limits
4664            'if(coord.x < 0.0)',
4665                'gl_FragColor = texture2D(u_image0, vec2((coord.x + u_h) / u_h, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
4666            'else',
4667                'gl_FragColor = texture2D(u_image1, vec2((coord.x + u_h) / u_h - 1.0, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
4668        '} else {',
4669            'gl_FragColor = texture2D(u_image0, vec2((coord.x + u_h) / (u_h * 2.0), (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
4670        '}',
4671    '}',
4672'}'
4673].join('\n');
4674
4675// Fragment shader
4676var fragMulti = [
4677'varying mediump vec2 v_texCoord;',
4678'uniform sampler2D u_sampler;',
4679//'uniform mediump vec4 u_color;',
4680
4681'void main(void) {',
4682    // Look up color from texture
4683    'gl_FragColor = texture2D(u_sampler, v_texCoord);',
4684//    'gl_FragColor = u_color;',
4685'}'
4686].join('');
4687
4688return {
4689    renderer: function(container, image, imagetype, dynamic) {
4690        return new Renderer(container, image, imagetype, dynamic);
4691    }
4692};
4693
4694})(window, document);
4695// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/admin/lib/video.js?ver=1 
4696/**
4697 * @license
4698 * Video.js 7.18.1 <http://videojs.com/>
4699 * Copyright Brightcove, Inc. <https://www.brightcove.com/>
4700 * Available under Apache License Version 2.0
4701 * <https://github.com/videojs/video.js/blob/main/LICENSE>
4702 *
4703 * Includes vtt.js <https://github.com/mozilla/vtt.js>
4704 * Available under Apache License Version 2.0
4705 * <https://github.com/mozilla/vtt.js/blob/main/LICENSE>
4706 */
4707 !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).videojs=t()}(this,function(){"use strict";for(var e,u="7.18.1",i={},a=function(e,t){return i[e]=i[e]||[],t&&(i[e]=i[e].concat(t)),i[e]},n=function(e,t){t=a(e).indexOf(t);return!(t<=-1)&&(i[e]=i[e].slice(),i[e].splice(t,1),!0)},l={prefixed:!0},t=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror","fullscreen"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror","-webkit-full-screen"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror","-moz-full-screen"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError","-ms-fullscreen"]],r=t[0],s=0;s<t.length;s++)if(t[s][1]in document){e=t[s];break}if(e){for(var o=0;o<e.length;o++)l[r[o]]=e[o];l.prefixed=e[0]!==r[0]}var c=[],d=function(a,s){return function(e,t,i){var n,r=s.levels[t],t=new RegExp("^("+r+")$");"log"!==e&&i.unshift(e.toUpperCase()+":"),i.unshift(a+":"),c&&(c.push([].concat(i)),n=c.length-1e3,c.splice(0,0<n?n:0)),!window.console||(n=!(n=window.console[e])&&"debug"===e?window.console.info||window.console.log:n)&&r&&t.test(e)&&n[Array.isArray(i)?"apply":"call"](window.console,i)}};var h=function t(i){function n(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];a("log",r,t)}var r="info",a=d(i,n);return n.createLogger=function(e){return t(i+": "+e)},n.levels={all:"debug|log|warn|error",off:"",debug:"debug|log|warn|error",info:"log|warn|error",warn:"warn|error",error:"error",DEFAULT:r},n.level=function(e){if("string"==typeof e){if(!n.levels.hasOwnProperty(e))throw new Error('"'+e+'" in not a valid log level');r=e}return r},(n.history=function(){return c?[].concat(c):[]}).filter=function(t){return(c||[]).filter(function(e){return new RegExp(".*"+t+".*").test(e[0])})},n.history.clear=function(){c&&(c.length=0)},n.history.disable=function(){null!==c&&(c.length=0,c=null)},n.history.enable=function(){null===c&&(c=[])},n.error=function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];return a("error",r,t)},n.warn=function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];return a("warn",r,t)},n.debug=function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];return a("debug",r,t)},n}("VIDEOJS"),p=h.createLogger,f="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function m(e,t){return e(t={exports:{}},t.exports),t.exports}var g=m(function(e){function t(){return e.exports=t=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var i,n=arguments[t];for(i in n)Object.prototype.hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e},t.apply(this,arguments)}
4707e.exports=t}),y=Object.prototype.toString,v=function(e){return T(e)?Object.keys(e):[]};function _(t,i){v(t).forEach(function(e){return i(t[e],e)})}function b(i){for(var e=arguments.length,t=new Array(1<e?e-1:0),n=1;n<e;n++)t[n-1]=arguments[n];return Object.assign?g.apply(void 0,[i].concat(t)):(t.forEach(function(e){e&&_(e,function(e,t){i[t]=e})}),i)}function T(e){return!!e&&"object"==typeof e}function S(e){return T(e)&&"[object Object]"===y.call(e)&&e.constructor===Object}function w(e,t){if(!e||!t)return"";if("function"!=typeof window.getComputedStyle)return"";var i;try{i=window.getComputedStyle(e)}catch(e){return""}return i?i.getPropertyValue(t)||i[t]:""}var E=window.navigator&&window.navigator.userAgent||"",k=/AppleWebKit\/([\d.]+)/i.exec(E),C=k?parseFloat(k.pop()):null,I=/iPod/i.test(E),x=(jt=E.match(/OS (\d+)_/i))&&jt[1]?jt[1]:null,A=/Android/i.test(E),P=function(){var e=E.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);if(!e)return null;var t=e[1]&&parseFloat(e[1]),i=e[2]&&parseFloat(e[2]);return t&&i?parseFloat(e[1]+"."+e[2]):t||null}(),L=A&&P<5&&C<537,D=/Firefox/i.test(E),O=/Edg/i.test(E),R=!O&&(/Chrome/i.test(E)||/CriOS/i.test(E)),M=(zt=E.match(/(Chrome|CriOS)\/(\d+)/))&&zt[2]?parseFloat(zt[2]):null,N=Xt=!(Xt=(Xt=/MSIE\s(\d+)\.\d/.exec(E))&&parseFloat(Xt[1]))&&/Trident\/7.0/i.test(E)&&/rv:11.0/.test(E)?11:Xt,U=/Safari/i.test(E)&&!R&&!A&&!O,B=/Windows/i.test(E),F=Boolean(X()&&("ontouchstart"in window||window.navigator.maxTouchPoints||window.DocumentTouch&&window.document instanceof window.DocumentTouch)),j=/iPad/i.test(E)||U&&F&&!/iPhone/i.test(E),H=/iPhone/i.test(E)&&!j,q=H||j||I,V=(U||q)&&!R,W=Object.freeze({__proto__:null,IS_IPOD:I,IOS_VERSION:x,IS_ANDROID:A,ANDROID_VERSION:P,IS_NATIVE_ANDROID:L,IS_FIREFOX:D,IS_EDGE:O,IS_CHROME:R,CHROME_VERSION:M,IE_VERSION:N,IS_SAFARI:U,IS_WINDOWS:B,TOUCH_ENABLED:F,IS_IPAD:j,IS_IPHONE:H,IS_IOS:q,IS_ANY_SAFARI:V});function G(e){return"string"==typeof e&&Boolean(e.trim())}function z(e){if(0<=e.indexOf(" "))throw new Error("class has illegal whitespace characters")}function X(){return document===window.document}function K(e){return T(e)&&1===e.nodeType}function Y(){try{return window.parent!==window.self}catch(e){return!0}}function Q(i){return function(e,t){if(!G(e))return document[i](null);t=K(t=G(t)?document.querySelector(t):t)?t:document;return t[i]&&t[i](e)}}function $(e,i,t,n){void 0===e&&(e="div"),void 0===i&&(i={}),void 0===t&&(t={});var r=document.createElement(e);return Object.getOwnPropertyNames(i).forEach(function(e){var t=i[e];-1!==e.indexOf("aria-")||"role"===e||"type"===e?(h.warn("Setting attributes in the second argument of createEl()\nhas been deprecated. Use the third argument instead.\ncreateEl(type, properties, attributes). Attempting to set "+e+" to "+t+"."),r.setAttribute(e,t)):"textContent"===e?J(r,t):r[e]===t&&"tabIndex"!==e||(r[e]=t)}),Object.getOwnPropertyNames(t).forEach(function(e){r.setAttribute(e,t[e])}),n&&ye(r,n),r}function J(e,t){return"undefined"==typeof e.textContent?e.innerText=t:e.textContent=t,e}function Z(e,t){t.firstChild?t.insertBefore(e,t.firstChild):t.appendChild(e)}function ee(e,t){return z(t),e.classList?e.classList.contains(t):new RegExp("(^|\\s)"+t+"($|\\s)").test(e.className)}function te(e,t){return e.classList?e.classList.add(t):ee(e,t)||(e.className=(e.className+" "+t).trim()),e}function ie(e,t){return e?(e.classList?e.classList.remove(t):(z(t),e.className=e.className.split(/\s+/).filter(function(e){return e!==t}).join(" ")),e):(h.warn("removeClass was called with an element that doesn't exist"),null)}function ne(e,t,i){var n=ee(e,t);if((i="boolean"!=typeof(i="function"==typeof i?i(e,t):i)?!n:i)!==n)return(i?te:ie)(e,t),e}function re(i,n){Object.getOwnPropertyNames(n).forEach(function(e){var t=n[e];null===t||"undefined"==typeof t||!1===t?i.removeAttribute(e):i.setAttribute(e,!0===t?"":t)})}function ae(e){var t={},i=",autoplay,controls,playsinline,loop,muted,default,defaultMuted,";if(e&&e.attributes&&0<e.attributes.length)for(var n=e.attributes,r=n.length-1;0<=r;r--){var a=n[r].name,s=n[r].value;"boolean"!=typeof e[a]&&-1===i.indexOf(","+a+",")||(s=null!==s),t[a]=s}return t}function se(e,t){return e.getAttribute(t)}function oe(e,t,i){e.setAttribute(t,i)}function ue(e,t){e.removeAttribute(t)}function le(){document.body.focus(),document.onselectstart=function(){return!1}}function ce(){document.onselectstart=function(){return!0}}function de(e){if(e&&e.getBoundingClientRect&&e.parentNode){var t=e.getBoundingClientRect(),i={};return["bottom","height","left","right","top","width"].forEach(function(e){void 0!==t[e]&&(i[e]=t[e])}),i.height||(i.height=parseFloat(w(e,"height"))),i.width||(i.width=parseFloat(w(e,"width"))),i}}function he(e){if(!e||e&&!e.offsetParent)return{left:0,top:0,width:0,height:0};for(var t=e.offsetWidth,i=e.offsetHeight,n=0,r=0;e.offsetParent&&e!==document[l.fullscreenElement];)n+=e.offsetLeft,r+=e.offsetTop,e=e.offsetParent;return{left:n,top:r,width:t,height:i}}function pe(e,t){var i={x:0,y:0};if(q)for(var n=e;n&&"html"!==n.nodeName.toLowerCase();){var r,a=w(n,"transform");
4707/^matrix/.test(a)?(r=a.slice(7,-1).split(/,\s/).map(Number),i.x+=r[4],i.y+=r[5]):/^matrix3d/.test(a)&&(a=a.slice(9,-1).split(/,\s/).map(Number),i.x+=a[12],i.y+=a[13]),n=n.parentNode}var s={},o=he(t.target),u=he(e),l=u.width,c=u.height,e=t.offsetY-(u.top-o.top),o=t.offsetX-(u.left-o.left);return t.changedTouches&&(o=t.changedTouches[0].pageX-u.left,e=t.changedTouches[0].pageY+u.top,q&&(o-=i.x,e-=i.y)),s.y=1-Math.max(0,Math.min(1,e/c)),s.x=Math.max(0,Math.min(1,o/l)),s}function fe(e){return T(e)&&3===e.nodeType}function me(e){for(;e.firstChild;)e.removeChild(e.firstChild);return e}function ge(e){return"function"==typeof e&&(e=e()),(Array.isArray(e)?e:[e]).map(function(e){return K(e="function"==typeof e?e():e)||fe(e)?e:"string"==typeof e&&/\S/.test(e)?document.createTextNode(e):void 0}).filter(function(e){return e})}function ye(t,e){return ge(e).forEach(function(e){return t.appendChild(e)}),t}function ve(e,t){return ye(me(e),t)}function _e(e){return void 0===e.button&&void 0===e.buttons||(0===e.button&&void 0===e.buttons||("mouseup"===e.type&&0===e.button&&0===e.buttons||0===e.button&&1===e.buttons))}var be,Te=Q("querySelector"),Se=Q("querySelectorAll"),we=Object.freeze({__proto__:null,isReal:X,isEl:K,isInFrame:Y,createEl:$,textContent:J,prependTo:Z,hasClass:ee,addClass:te,removeClass:ie,toggleClass:ne,setAttributes:re,getAttributes:ae,getAttribute:se,setAttribute:oe,removeAttribute:ue,blockTextSelection:le,unblockTextSelection:ce,getBoundingClientRect:de,findPosition:he,getPointerPosition:pe,isTextNode:fe,emptyEl:me,normalizeContent:ge,appendContent:ye,insertContent:ve,isSingleLeftClick:_e,$:Te,$$:Se}),Ee=!1,ke=function(){if(!1!==be.options.autoSetup){var e=Array.prototype.slice.call(document.getElementsByTagName("video")),t=Array.prototype.slice.call(document.getElementsByTagName("audio")),i=Array.prototype.slice.call(document.getElementsByTagName("video-js")),n=e.concat(t,i);if(n&&0<n.length)for(var r=0,a=n.length;r<a;r++){var s=n[r];if(!s||!s.getAttribute){Ce(1);break}void 0===s.player&&null!==s.getAttribute("data-setup")&&be(s)}else Ee||Ce(1)}};function Ce(e,t){X()&&(t&&(be=t),window.setTimeout(ke,e))}function Ie(){Ee=!0,window.removeEventListener("load",Ie)}X()&&("complete"===document.readyState?Ie():window.addEventListener("load",Ie));function xe(e){var t=document.createElement("style");return t.className=e,t}function Ae(e,t){e.styleSheet?e.styleSheet.cssText=t:e.textContent=t}var Pe=3;window.WeakMap||(ui=function(){function e(){this.vdata="vdata"+Math.floor(window.performance&&window.performance.now()||Date.now()),this.data={}}var t=e.prototype;return t.set=function(e,t){var i=e[this.vdata]||Pe++;return e[this.vdata]||(e[this.vdata]=i),this.data[i]=t,this},t.get=function(e){var t=e[this.vdata];if(t)return this.data[t];h("We have no data for this element",e)},t.has=function(e){return e[this.vdata]in this.data},t.delete=function(e){var t=e[this.vdata];t&&(delete this.data[t],delete e[this.vdata])},e}());var Le,De=new(window.WeakMap?WeakMap:ui);function Oe(e,t){var i;De.has(e)&&(0===(i=De.get(e)).handlers[t].length&&(delete i.handlers[t],e.removeEventListener?e.removeEventListener(t,i.dispatcher,!1):e.detachEvent&&e.detachEvent("on"+t,i.dispatcher)),Object.getOwnPropertyNames(i.handlers).length<=0&&(delete i.handlers,delete i.dispatcher,delete i.disabled),0===Object.getOwnPropertyNames(i).length&&De.delete(e))}function Re(t,i,e,n){e.forEach(function(e){t(i,e,n)})}function Me(e){if(e.fixed_)return e;function t(){return!0}function i(){return!1}if(!e||!e.isPropagationStopped||!e.isImmediatePropagationStopped){var n,r,a,s=e||window.event;for(n in e={},s)"layerX"!==n&&"layerY"!==n&&"keyLocation"!==n&&"webkitMovementX"!==n&&"webkitMovementY"!==n&&("returnValue"===n&&s.preventDefault||(e[n]=s[n]));e.target||(e.target=e.srcElement||document),e.relatedTarget||(e.relatedTarget=e.fromElement===e.target?e.toElement:e.fromElement),e.preventDefault=function(){s.preventDefault&&s.preventDefault(),e.returnValue=!1,s.returnValue=!1,e.defaultPrevented=!0},e.defaultPrevented=!1,e.stopPropagation=function(){s.stopPropagation&&s.stopPropagation(),e.cancelBubble=!0,s.cancelBubble=!0,e.isPropagationStopped=t},e.isPropagationStopped=i,e.stopImmediatePropagation=function(){s.stopImmediatePropagation&&s.stopImmediatePropagation(),e.isImmediatePropagationStopped=t,e.stopPropagation()},e.isImmediatePropagationStopped=i,null!==e.clientX&&void 0!==e.clientX&&(r=d
4707ocument.documentElement,a=document.body,e.pageX=e.clientX+(r&&r.scrollLeft||a&&a.scrollLeft||0)-(r&&r.clientLeft||a&&a.clientLeft||0),e.pageY=e.clientY+(r&&r.scrollTop||a&&a.scrollTop||0)-(r&&r.clientTop||a&&a.clientTop||0)),e.which=e.charCode||e.keyCode,null!==e.button&&void 0!==e.button&&(e.button=1&e.button?0:4&e.button?1:2&e.button?2:0)}return e.fixed_=!0,e}var Ne=function(){if("boolean"!=typeof Le){Le=!1;try{var e=Object.defineProperty({},"passive",{get:function(){Le=!0}});window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(e){}}return Le},Ue=["touchstart","touchmove"];function Be(s,e,t){if(Array.isArray(e))return Re(Be,s,e,t);De.has(s)||De.set(s,{});var o=De.get(s);o.handlers||(o.handlers={}),o.handlers[e]||(o.handlers[e]=[]),t.guid||(t.guid=Pe++),o.handlers[e].push(t),o.dispatcher||(o.disabled=!1,o.dispatcher=function(e,t){if(!o.disabled){e=Me(e);var i=o.handlers[e.type];if(i)for(var n=i.slice(0),r=0,a=n.length;r<a&&!e.isImmediatePropagationStopped();r++)try{n[r].call(s,e,t)}catch(e){h.error(e)}}}),1===o.handlers[e].length&&(s.addEventListener?(t=!1,Ne()&&-1<Ue.indexOf(e)&&(t={passive:!0}),s.addEventListener(e,o.dispatcher,t)):s.attachEvent&&s.attachEvent("on"+e,o.dispatcher))}function Fe(e,t,i){if(De.has(e)){var n=De.get(e);if(n.handlers){if(Array.isArray(t))return Re(Fe,e,t,i);var r=function(e,t){n.handlers[t]=[],Oe(e,t)};if(void 0!==t){var a=n.handlers[t];if(a)if(i){if(i.guid)for(var s=0;s<a.length;s++)a[s].guid===i.guid&&a.splice(s--,1);Oe(e,t)}else r(e,t)}else for(var o in n.handlers)Object.prototype.hasOwnProperty.call(n.handlers||{},o)&&r(e,o)}}}function je(e,t,i){var n=De.has(e)?De.get(e):{},r=e.parentNode||e.ownerDocument;return"string"==typeof t?t={type:t,target:e}:t.target||(t.target=e),t=Me(t),n.dispatcher&&n.dispatcher.call(e,t,i),r&&!t.isPropagationStopped()&&!0===t.bubbles?je.call(null,r,t,i):!r&&!t.defaultPrevented&&t.target&&t.target[t.type]&&(De.has(t.target)||De.set(t.target,{}),r=De.get(t.target),t.target[t.type]&&(r.disabled=!0,"function"==typeof t.target[t.type]&&t.target[t.type](),r.disabled=!1)),!t.defaultPrevented}function He(e,t,i){if(Array.isArray(t))return Re(He,e,t,i);function n(){Fe(e,t,n),i.apply(this,arguments)}n.guid=i.guid=i.guid||Pe++,Be(e,t,n)}function qe(e,t,i){function n(){Fe(e,t,n),i.apply(this,arguments)}n.guid=i.guid=i.guid||Pe++,Be(e,t,n)}function Ve(e,t,i){return t.guid||(t.guid=Pe++),(e=t.bind(e)).guid=i?i+"_"+t.guid:t.guid,e}function We(t,i){var n=window.performance.now();return function(){var e=window.performance.now();i<=e-n&&(t.apply(void 0,arguments),n=e)}}function Ge(n,r,a,s){var o;function e(){var e=this,t=arguments,i=function(){i=o=null,a||n.apply(e,t)};!o&&a&&n.apply(e,t),s.clearTimeout(o),o=s.setTimeout(i,r)}return void 0===s&&(s=window),e.cancel=function(){s.clearTimeout(o),o=null},e}function ze(){}var Xe,Ke=Object.freeze({__proto__:null,fixEvent:Me,on:Be,off:Fe,trigger:je,one:He,any:qe});ze.prototype.allowedEvents_={},ze.prototype.addEventListener=ze.prototype.on=function(e,t){var i=this.addEventListener;this.addEventListener=function(){},Be(this,e,t),this.addEventListener=i},ze.prototype.removeEventListener=ze.prototype.off=function(e,t){Fe(this,e,t)},ze.prototype.one=function(e,t){var i=this.addEventListener;this.addEventListener=function(){},He(this,e,t),this.addEventListener=i},ze.prototype.any=function(e,t){var i=this.addEventListener;this.addEventListener=function(){},qe(this,e,t),this.addEventListener=i},ze.prototype.dispatchEvent=ze.prototype.trigger=function(e){var t=e.type||e;e=Me(e="string"==typeof e?{type:t}:e),this.allowedEvents_[t]&&this["on"+t]&&this["on"+t](e),je(this,e)},ze.prototype.queueTrigger=function(e){var t=this;Xe=Xe||new Map;var i=e.type||e,n=Xe.get(this);n||(n=new Map,Xe.set(this,n));var r=n.get(i);n.delete(i),window.clearTimeout(r);r=window.setTimeout(function(){0===n.size&&(n=null,Xe.delete(t)),t.trigger(e)},0);n.set(i,r)};function Ye(e){return"function"==typeof e.name?e.name():"string"==typeof e.name?e.name:e.name_||(e.constructor&&e.constructor.name?e.constructor.name:typeof e)}function Qe(e){return"string"==typeof e&&/\S/.test(e)||Array.isArray(e)&&!!e.length}function $e(e,t,i){if(!e||!e.nodeName&&!it(e))throw new Error("Invalid target for "+Ye(t)+"#"+i+"; must be a DOM node or evented object.")}function Je(e,t,i){if(!Qe(e))throw new Error("Invalid event type for "+Ye(t)+"#"+i+"; must be a non-empty string or array.")}function Ze(e,t,i){if("function"!=typeof e)throw new Error("Invalid listener for "+Ye(t)+"#"+i+"; must be a function.")}function et(e,t,i){var n,r,a=t.length<3||t[0]===e||t[0]===e.eventBusEl_,t=a?(n=e.eventBusEl_,3<=t.length&&t.shift(),r=t[0],t[1]):(n=t[0],r=t[1],t[2]);return $e(n,e,i),Je(r,e,i),Ze(t,e,i),{isTargetingSelf:a,target:n,type:r,listener:t=Ve(e,t)}}function tt(e,t,i,n){$e(e,e,t),e.nodeName?Ke[t](e,i,n):e[t](i,n)}var it=function(t){return t instanceof ze||!!t.eventBusEl_&&["on","one","off","trigger"].every(function(e){return"function"==typeof t[e]}
4707)},nt={on:function(){for(var e=this,t=arguments.length,i=new Array(t),n=0;n<t;n++)i[n]=arguments[n];var r,a=et(this,i,"on"),s=a.isTargetingSelf,o=a.target,u=a.type,l=a.listener;tt(o,"on",u,l),s||((r=function(){return e.off(o,u,l)}).guid=l.guid,(s=function(){return e.off("dispose",r)}).guid=l.guid,tt(this,"on","dispose",r),tt(o,"on","dispose",s))},one:function(){for(var r=this,e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];var n=et(this,t,"one"),a=n.isTargetingSelf,s=n.target,o=n.type,u=n.listener;a?tt(s,"one",o,u):((a=function e(){r.off(s,o,e);for(var t=arguments.length,i=new Array(t),n=0;n<t;n++)i[n]=arguments[n];u.apply(null,i)}).guid=u.guid,tt(s,"one",o,a))},any:function(){for(var r=this,e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];var n=et(this,t,"any"),a=n.isTargetingSelf,s=n.target,o=n.type,u=n.listener;a?tt(s,"any",o,u):((a=function e(){r.off(s,o,e);for(var t=arguments.length,i=new Array(t),n=0;n<t;n++)i[n]=arguments[n];u.apply(null,i)}).guid=u.guid,tt(s,"any",o,a))},off:function(e,t,i){!e||Qe(e)?Fe(this.eventBusEl_,e,t):(t=t,$e(e=e,this,"off"),Je(t,this,"off"),Ze(i,this,"off"),i=Ve(this,i),this.off("dispose",i),e.nodeName?(Fe(e,t,i),Fe(e,"dispose",i)):it(e)&&(e.off(t,i),e.off("dispose",i)))},trigger:function(e,t){$e(this.eventBusEl_,this,"trigger");var i=e&&"string"!=typeof e?e.type:e;if(!Qe(i)){i="Invalid event type for "+Ye(this)+"#trigger; must be a non-empty string or object with a type key that has a non-empty value.";if(!e)throw new Error(i);(this.log||h).error(i)}return je(this.eventBusEl_,e,t)}};function rt(e,t){t=(t=void 0===t?{}:t).eventBusKey;if(t){if(!e[t].nodeName)throw new Error('The eventBusKey "'+t+'" does not refer to an element.');e.eventBusEl_=e[t]}else e.eventBusEl_=$("span",{className:"vjs-event-bus"});return b(e,nt),e.eventedCallbacks&&e.eventedCallbacks.forEach(function(e){e()}),e.on("dispose",function(){e.off(),[e,e.el_,e.eventBusEl_].forEach(function(e){e&&De.has(e)&&De.delete(e)}),window.setTimeout(function(){e.eventBusEl_=null},0)}),e}var at={state:{},setState:function(e){var i,n=this;return _(e="function"==typeof e?e():e,function(e,t){n.state[t]!==e&&((i=i||{})[t]={from:n.state[t],to:e}),n.state[t]=e}),i&&it(this)&&this.trigger({changes:i,type:"statechanged"}),i}};function st(e,t){return b(e,at),e.state=b({},e.state,t),"function"==typeof e.handleStateChanged&&it(e)&&e.on("statechanged",e.handleStateChanged),e}function ot(e){return"string"!=typeof e?e:e.replace(/./,function(e){return e.toLowerCase()})}function ut(e){return"string"!=typeof e?e:e.replace(/./,function(e){return e.toUpperCase()})}function lt(){for(var i={},e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.forEach(function(e){e&&_(e,function(e,t){S(e)?(S(i[t])||(i[t]={}),i[t]=lt(i[t],e)):i[t]=e})}),i}var ct=window.Map||function(){function e(){this.map_={}}var t=e.prototype;return t.has=function(e){return e in this.map_},t.delete=function(e){var t=this.has(e);return delete this.map_[e],t},t.set=function(e,t){return this.map_[e]=t,this},t.forEach=function(e,t){for(var i in this.map_)e.call(t,this.map_[i],i,this)},e}(),dt=window.Set||function(){function e(){this.set_={}}var t=e.prototype;return t.has=function(e){return e in this.set_},t.delete=function(e){var t=this.has(e);return delete this.set_[e],t},t.add=function(e){return this.set_[e]=1,this},t.forEach=function(e,t){for(var i in this.set_)e.call(t,i,i,this)},e}(),ht=m(function(e,t){function i(e){if(!e||"object"!=typeof e||(t=e.which||e.keyCode||e.charCode)&&(e=t),"number"==typeof e)return o[e];var t=String(e),e=n[t.toLowerCase()];return e||((e=r[t.toLowerCase()])?e:1===t.length?t.charCodeAt(0):void 0)}i.isEventKey=function(e,t){if(e&&"object"==typeof e){var i=e.which||e.keyCode||e.charCode;if(null==i)return!1;if("string"==typeof t){e=n[t.toLowerCase()];if(e)return e===i;if(e=r[t.toLowerCase()])return e===i}else if("number"==typeof t)return t===i;return!1}};for(var n=(t=e.exports=i).code=t.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,"pause/break":19,"caps lock":20,esc:27,space:32,"page up":33,"page down":34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,delete:46,command:91,"left command":91,"right command":93,"numpad *":106,"numpad +":107,"numpad -":109,"numpad .":110,"numpad /":111,"num lock":144,"scroll lock":145,"my computer":182,"my calculator":183,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222},r=t.aliases={windows:91,"⇧":16,"⌥":18,"⌃":17,"⌘":91,ctl:17,control:17,option:18,pause:19,break:19,caps:20,return:13,escape:27,spc:32,spacebar:32,pgup:33,pgdn:34,ins:45,del:46,cmd:91},a=97;a<123;a++)n[String.fromCharCode(a)]=a-32;for(var a=48;a<58;a++)n[a-48]=a;for(a=1;a<13;a++)n["f"+a]=a+111;for(a=0;a<10;a++)n["numpad "+a]=a+96;var s,o=t.names=t.title={};for(a in n)o[n[a]]=a;for(s in r)n[s]=r[s]});ht.code,ht.codes,ht.aliases,ht.names,ht.title;var pt=function(){function s(e,t,i){!e&&this.play?this.player_=e=this:this.player_=e,this.isDisposed_=!1,this.parentComponent_=null,this.options_=lt({},this.options_),t=this.options_=lt(this.options_,t),this.id_=t.id||t.el&&t.el.id,this.id_||(e=e&&e.id&&e.id()||"no_player",this.id_=e+"_component_"+Pe++),this.name_=t.name||null,t.el?this.el_=t.el:!1!==t.createEl&&(this.el_=this.createEl()),!1!==t.evented&&(rt(this,{eventBusKey:this.el_?"el_":null}),this.handleLanguagechange=this.handleLanguagechange.bind(this),this.on(this.player_,"languagechange",this.handleLanguagechange)),st(this,this.constructor.defaultState),this.children_=[],this.childIndex_={},this.childNameIndex_={},this.setTimeoutIds_=new dt,this.setIntervalIds_=new dt,this.rafIds_=new dt,this.namedRafs_=new ct,(this.clearingTimersOnDispose_=!1)!==t.initChildren&&this.initChildren(),this.ready(i),!1!==t.reportTouchActivity&&this.enableTouchActivity()}var e=s.prototype;return e.dispose=function(){if(!this.isDisposed_){if(this.readyQueue_&&(this.readyQueue_.length=0),this.trigger({type:"dispose",bubbles:!1}),this.isDisposed_=!0,this.children_)for(var e=this.children_.length-1;0<=e;e--)this.children_[e].dispose&&this.children_[e].dispose();this.children_=null,this.childIndex_=null,this.childNameIndex_=null,this.parentComponent_=null,this.el_&&(this.el_.parentNode&&this.el_.parentNode.removeChild(this.el_),this.el_=null),this.player_=null}},e.isDisposed=function(){return Boolean(this.isDisposed_)},e.player=function(){return this.player_},e.options=function(e){return e&&(this.options_=lt(this.options_,e)),this.options_},e.el=function(){return this.el_},e.createEl=function(e,t,i){return $(e,t,i)},e.localize=function(e,i,t){void 0===t&&(t=e);var n=this.player_.language&&this.player_.language(),r=this.player_.languages&&this.player_.languages(),a=r&&r[n],n=n&&n.split("-")[0],n=r&&r[n],t=t;return a&&a[e]?t=a[e]:n&&n[e]&&(t=n[e]),t=i?t.replace(/\{(\d+)\}/g,function(e,t){t=i[t-1];return"undefined"==typeof t?e:t}):t},e.handleLanguagechange=function(){},e.contentEl=function(){return this.contentEl_||this.el_},e.id=function(){return this.id_},e.name=function(){return this.name_},e.children=function(){return this.children_},e.getChildById=function(e){return this.childIndex_[e]},e.getChild=function(e){if(e)return this.childNameIndex_[e]},e.getDescendant=function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];for(var t=t.reduce(function(e,t){return e.concat(t)},[]),n=this,r=0;r<t.length;r++)if(!(n=n.getChild(t[r]))||!n.getChild)return;return n},e.addChild=function(e,t,i){if(void 0===t&&(t={}),void 0===i&&(i=this.children_.length),"string"==typeof e){var n=ut(e),r=t.componentClass||n;t.name=n;var a=s.getComponent(r);if(!a)throw new Error("Component "+r+" does not exist");if("function"!=typeof a)return null;a=new a(this.player_||this,t)}else a=e;return a.parentComponent_&&a.parentComponent_.removeChild(a),this.children_.splice(i,0,a),a.parentComponent_=this,"function"==typeof a.id&&(this.childIndex_[a.id()]=a),(n=n||a.name&&ut(a.name()))&&(this.childNameIndex_[n]=a,this.childNameIndex_[ot(n)]=a),"function"==typeof a.el&&a.el()&&(n=null,this.children_[i+1]&&(this.children_[i+1].el_?n=this.children_[i+1].el_:K(this.children_[i+1])&&(n=this.children_[i+1])),this.contentEl().insertBefore(a.el(),n)),a},e.removeChild=function(e){if((e="string"==typeof e?this.getChild(e):e)&&this.children_){for(var t,i=!1,n=this.children_.length-1;0<=n;n--)if(this.children_[n]===e){i=!0,this.children_.splice(n,1);break}i&&(e.parentComponent_=null,this.childIndex_[e.id()]=null,this.childNameIndex_[ut(e.name())]=null,this.childNameIndex_[ot(e.name())]=null,(t=e.el())&&t.parentNode===this.contentEl()&&this.contentEl().removeChild(e.el()))}},e.initChildren=function(){var i,t,e,n=this,r=this.options_.children;r&&(i=this.options_,t=s.getComponent("Tech"),(e=Array.isArray(r)?r:Object.keys(r)).concat(Object.keys(this.options_).filter(function(t){return!e.s
4707ome(function(e){return"string"==typeof e?t===e:t===e.name})})).map(function(e){var t,e="string"==typeof e?r[t=e]||n.options_[t]||{}:(t=e.name,e);return{name:t,opts:e}}).filter(function(e){e=s.getComponent(e.opts.componentClass||ut(e.name));return e&&!t.isTech(e)}).forEach(function(e){var t=e.name,e=e.opts;!1!==(e=void 0!==i[t]?i[t]:e)&&((e=!0===e?{}:e).playerOptions=n.options_.playerOptions,(e=n.addChild(t,e))&&(n[t]=e))}))},e.buildCSSClass=function(){return""},e.ready=function(e,t){if(void 0===t&&(t=!1),e)return this.isReady_?void(t?e.call(this):this.setTimeout(e,1)):(this.readyQueue_=this.readyQueue_||[],void this.readyQueue_.push(e))},e.triggerReady=function(){this.isReady_=!0,this.setTimeout(function(){var e=this.readyQueue_;this.readyQueue_=[],e&&0<e.length&&e.forEach(function(e){e.call(this)},this),this.trigger("ready")},1)},e.$=function(e,t){return Te(e,t||this.contentEl())},e.$$=function(e,t){return Se(e,t||this.contentEl())},e.hasClass=function(e){return ee(this.el_,e)},e.addClass=function(e){te(this.el_,e)},e.removeClass=function(e){ie(this.el_,e)},e.toggleClass=function(e,t){ne(this.el_,e,t)},e.show=function(){this.removeClass("vjs-hidden")},e.hide=function(){this.addClass("vjs-hidden")},e.lockShowing=function(){this.addClass("vjs-lock-showing")},e.unlockShowing=function(){this.removeClass("vjs-lock-showing")},e.getAttribute=function(e){return se(this.el_,e)},e.setAttribute=function(e,t){oe(this.el_,e,t)},e.removeAttribute=function(e){ue(this.el_,e)},e.width=function(e,t){return this.dimension("width",e,t)},e.height=function(e,t){return this.dimension("height",e,t)},e.dimensions=function(e,t){this.width(e,!0),this.height(t)},e.dimension=function(e,t,i){if(void 0!==t)return-1!==(""+(t=null===t||t!=t?0:t)).indexOf("%")||-1!==(""+t).indexOf("px")?this.el_.style[e]=t:this.el_.style[e]="auto"===t?"":t+"px",void(i||this.trigger("componentresize"));if(!this.el_)return 0;t=this.el_.style[e],i=t.indexOf("px");return-1!==i?parseInt(t.slice(0,i),10):parseInt(this.el_["offset"+ut(e)],10)},e.currentDimension=function(e){var t=0;if("width"!==e&&"height"!==e)throw new Error("currentDimension only accepts width or height value");return t=w(this.el_,e),0!==(t=parseFloat(t))&&!isNaN(t)||(e="offset"+ut(e),t=this.el_[e]),t},e.currentDimensions=function(){return{width:this.currentDimension("width"),height:this.currentDimension("height")}},e.currentWidth=function(){return this.currentDimension("width")},e.currentHeight=function(){return this.currentDimension("height")},e.focus=function(){this.el_.focus()},e.blur=function(){this.el_.blur()},e.handleKeyDown=function(e){this.player_&&(ht.isEventKey(e,"Tab")||e.stopPropagation(),this.player_.handleKeyDown(e))},e.handleKeyPress=function(e){this.handleKeyDown(e)},e.emitTapEvents=function(){var i,t=0,n=null;this.on("touchstart",function(e){1===e.touches.length&&(n={pageX:e.touches[0].pageX,pageY:e.touches[0].pageY},t=window.performance.now(),i=!0)}),this.on("touchmove",function(e){var t;1<e.touches.length?i=!1:n&&(t=e.touches[0].pageX-n.pageX,e=e.touches[0].pageY-n.pageY,10<Math.sqrt(t*t+e*e)&&(i=!1))});function e(){i=!1}this.on("touchleave",e),this.on("touchcancel",e),this.on("touchend",function(e){!(n=null)===i&&window.performance.now()-t<200&&(e.preventDefault(),this.trigger("tap"))})},e.enableTouchActivity=function(){var t,i,e;this.player()&&this.player().reportUserActivity&&(t=Ve(this.player(),this.player().reportUserActivity),this.on("touchstart",function(){t(),this.clearInterval(i),i=this.setInterval(t,250)}),e=function(e){t(),this.clearInterval(i)},this.on("touchmove",t),this.on("touchend",e),this.on("touchcancel",e))},e.setTimeout=function(e,t){var i,n=this;return e=Ve(this,e),this.clearTimersOnDispose_(),i=window.setTimeout(function(){n.setTimeoutIds_.has(i)&&n.setTimeoutIds_.delete(i),e()},t),this.setTimeoutIds_.add(i),i},e.clearTimeout=function(e){return this.setTimeoutIds_.has(e)&&(this.setTimeoutIds_.delete(e),window.clearTimeout(e)),e},e.setInterval=function(e,t){e=Ve(this,e),this.clearTimersOnDispose_();t=window.setInterval(e,t);return this.setIntervalIds_.add(t),t},e.clearInterval=function(e){return this.setIntervalIds_.has(e)&&(this.setIntervalIds_.delete(e),window.clearInterval(e)),e},e.requestAnimationFrame=function(e){var t,i=this;return this.supportsRaf_?(this.clearTimersOnDispose_(),e=Ve(this,e),t=window.requestAnimationFrame(function(){i.rafIds_.has(t)&&i.rafIds_.delete(t),e()}),this.rafIds_.add(t),t):this.setTimeout(e,1e3/60)},e.requestNamedAnimationFrame=function(e,t){var i=this;if(!this.namedRafs_.has(e)){this.clearTimersOnDispose_(),t=Ve(this,t);var n=this.requestAnimationFrame(function(){t(),i.namedRafs_.has(e)&&i.namedRafs_.delete(e)});return this.namedRafs_.set(e,n),e}},e.cancelNamedAnimationFrame=function(e){this.namedRafs_.has(e)&&(this.cancelAnimationFrame(this.namedRafs_.get(e)),this.namedRafs_.delete(e))},e.cancelAnimationFrame=function(e){return this.supportsRaf_?(this.rafIds_.has(e)&&(this.rafIds_.delete(e),window.cancelAnimationFrame(e)),e):this.clearTimeout(e)},e.clearTimersOnDispose_=function(){var n=this;this.clearingTimersOnDispose_||(this.clearingTimersOnDispose_=!0,this.one("dispose",function(){[["namedRafs_","cancelNamedAnimationFrame"],["rafIds_","cancelAnimationFrame"],["setTimeoutIds_","clearTimeout"],["setIntervalIds_","clearInterval"]].forEac
vendor: 9,904 bytes, line 4707
4707h(function(e){var t=e[0],i=e[1];n[t].forEach(function(e,t){return n[i](t)})}),n.clearingTimersOnDispose_=!1}))},s.registerComponent=function(e,t){if("string"!=typeof e||!e)throw new Error('Illegal component name, "'+e+'"; must be a non-empty string.');var i=s.getComponent("Tech"),n=i&&i.isTech(t),i=s===t||s.prototype.isPrototypeOf(t.prototype);if(n||!i){var r=n?"techs must be registered using Tech.registerTech()":"must be a Component subclass";throw new Error('Illegal component, "'+e+'"; '+r+".")}e=ut(e),s.components_||(s.components_={});r=s.getComponent("Player");if("Player"===e&&r&&r.players){var a=r.players,r=Object.keys(a);if(a&&0<r.length&&r.map(function(e){return a[e]}).every(Boolean))throw new Error("Can not register Player component after player has been created.")}return s.components_[e]=t,s.components_[ot(e)]=t},s.getComponent=function(e){if(e&&s.components_)return s.components_[e]},s}();pt.prototype.supportsRaf_="function"==typeof window.requestAnimationFrame&&"function"==typeof window.cancelAnimationFrame,pt.registerComponent("Component",pt);var ft=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e};var mt=function(e,t){e.prototype=Object.create(t.prototype),(e.prototype.constructor=e).__proto__=t};function gt(e,t,i,n){return function(e,t,i){if("number"!=typeof t||t<0||i<t)throw new Error("Failed to execute '"+e+"' on 'TimeRanges': The index provided ("+t+") is non-numeric or out of bounds (0-"+i+").")}(e,n,i.length-1),i[n][t]}function yt(e){var t=void 0===e||0===e.length?{length:0,start:function(){throw new Error("This TimeRanges object is empty")},end:function(){throw new Error("This TimeRanges object is empty")}}:{length:e.length,start:gt.bind(null,"start",0,e),end:gt.bind(null,"end",1,e)};return window.Symbol&&window.Symbol.iterator&&(t[window.Symbol.iterator]=function(){return(e||[]).values()}),t}function vt(e,t){return Array.isArray(e)?yt(e):void 0===e||void 0===t?yt():yt([[e,t]])}function _t(e,t){var i,n,r=0;if(!t)return 0;e&&e.length||(e=vt(0,0));for(var a=0;a<e.length;a++)i=e.start(a),r+=(n=t<(n=e.end(a))?t:n)-i;return r/t}function bt(e){if(e instanceof bt)return e;"number"==typeof e?this.code=e:"string"==typeof e?this.message=e:T(e)&&("number"==typeof e.code&&(this.code=e.code),b(this,e)),this.message||(this.message=bt.defaultMessages[this.code]||"")}bt.prototype.code=0,bt.prototype.message="",bt.prototype.status=null,bt.errorTypes=["MEDIA_ERR_CUSTOM","MEDIA_ERR_ABORTED","MEDIA_ERR_NETWORK","MEDIA_ERR_DECODE","MEDIA_ERR_SRC_NOT_SUPPORTED","MEDIA_ERR_ENCRYPTED"],bt.defaultMessages={1:"You aborted the media playback",2:"A network error caused the media download to fail part-way.",3:"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.",4:"The media could not be loaded, either because the server or network failed or because the format is not supported.",5:"The media is encrypted and we do not have the keys to decrypt it."};for(var Tt=0;Tt<bt.errorTypes.length;Tt++)bt[bt.errorTypes[Tt]]=Tt,bt.prototype[bt.errorTypes[Tt]]=Tt;var St=function(e,t){var i,n=null;try{i=JSON.parse(e,t)}catch(e){n=e}return[n,i]};function wt(e){return null!=e&&"function"==typeof e.then}function Et(e){wt(e)&&e.then(null,function(e){})}function kt(n){return["kind","label","language","id","inBandMetadataTrackDispatchType","mode","src"].reduce(function(e,t,i){return n[t]&&(e[t]=n[t]),e},{cues:n.cues&&Array.prototype.map.call(n.cues,function(e){return{startTime:e.startTime,endTime:e.endTime,text:e.text,id:e.id}})})}var Ct=function(e){var t=e.$$("track"),i=Array.prototype.map.call(t,function(e){return e.track});return Array.prototype.map.call(t,function(e){var t=kt(e.track);return e.src&&(t.src=e.src),t}).concat(Array.prototype.filter.call(e.textTracks(),function(e){return-1===i.indexOf(e)}).map(kt))},It=function(e,i){return e.forEach(function(e){var t=i.addRemoteTextTrack(e).track;!e.src&&e.cues&&e.cues.forEach(function(e){return t.addCue(e)})}),i.textTracks()},xt="vjs-modal-dialog",At=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.handleKeyDown_=function(e){return i.handleKeyDown(e)},i.close_=function(e){return i.close(e)},i.opened_=i.hasBeenOpened_=i.hasBeenFilled_=!1,i.closeable(!i.options_.uncloseable),i.content(i.options_.content),i.contentEl_=$("div",{className:xt+"-content"},{role:"document"}),i.descEl_=$("p",{className:xt+"-description vjs-control-text",id:i.el().getAttribute("aria-describedby")}),J(i.descEl_,i.description()),i.el_.appendChild(i.descEl_),i.el_.appendChild(i.contentEl_),i}mt(e,n);var t=e.prototype;return t.createEl=function(){return n.prototype.createEl.call(this,"div",{className:this.buildCSSClass(),tabIndex:-1},{"aria-describedby":this.id()+"_description","aria-hidden":"true","aria-label":this.label(),role:"dialog"})},t.dispose=function(){this.contentEl_=null,this.descEl_=null,this.previouslyActiveEl_=null,n.prototype.dispose.call(this)},t.buildCSSClass=function(){return xt+" vjs-hidden "+n.prototype.buildCSSClass.call(this)},t.label=function(){return this.localize(this.options_.label||"Modal Window")},t.description=function(){var e=this.options_.description||this.localize("This is a modal window.");return this.closeable()&&(e+=" "+this.localize("This modal can be closed by pressing the Escape key or activating the close button.")),e},t.open=function(){var e;this.opened_||(e=this.player(),this.trigger("beforemodalopen"),this.opened_=!0,!this.options_.fillAlways&&(this.hasBeenOpened_||this.hasBeenFilled_)||this.fill(),this.wasPlaying_=!e.paused(),this.options_.pauseOnOpen&&this.wasPlaying_&&e.pause(),this.on("keydown",this.handleKeyDown_),this.hadControls_=e.controls(),e.controls(!1),this.show(),this.conditionalFocus_(),this.el().setAttribute("aria-hidden","false"),this.trigger("modalopen"),this.hasBeenOpened_=!0)},t.opened=function(e){return"boolean"==typeof e&&this[e?"open":"close"](),this.opened_},t.close=function(){var e;this.opened_&&(e=this.player(),this.trigger("beforemodalclose"),this.opened_=!1,this.wasPlaying_&&this.options_.pauseOnOpen&&e.play(),this.off("keydown",this.handleKeyDown_),this.hadControls_&&e.controls(!0),this.hide(),this.el().setAttribute("aria-hidden","true"),this.trigger("modalclose"),this.conditionalBlur_(),this.options_.temporary&&this.dispose())},t.closeable=function(e){var t,i;return"boolean"==typeof e&&(t=this.closeable_=!!e,i=this.getChild("closeButton"),t&&!i&&(e=this.contentEl_,this.contentEl_=this.el_,i=this.addChild("closeButton",{controlText:"Close Modal Dialog"}),this.contentEl_=e,this.on(i,"close",this.close_)),!t&&i&&(this.off(i,"close",this.close_),this.removeChild(i),i.dispose())),this.closeable_},t.fill=function(){this.fillWith(this.content())},t.fillWith=function(e){var t=this.contentEl(),i=t.parentNode,n=t.nextSibling;this.trigger("beforemodalfill"),this.hasBeenFilled_=!0,i.removeChild(t),this.empty(),ve(t,e),this.trigger("modalfill"),n?i.insertBefore(t,n):i.appendChild(t);t=this.getChild("closeButton");t&&i.appendChild(t.el_)},t.empty=function(){this.trigger("beforemodalempty"),me(this.contentEl()),this.trigger("modalempty")},t.content=function(e){return"undefined"!=typeof e&&(this.content_=e),this.content_},t.conditionalFocus_=function(){var e=document.activeElement,t=this.player_.el_;this.previouslyActiveEl_=null,!t.contains(e)&&t!==e||(this.previouslyActiveEl_=e,this.focus())},t.conditionalBlur_=function(){this.previouslyActiveEl_&&(this.previouslyActiveEl_.focus(),this.previouslyActiveEl_=null)},t.handleKeyDown=function(e){if(e.stopPropagation(),ht.isEventKey(e,"Escape")&&this.closeable())return e.preventDefault(),void this.close();if(ht.isEventKey(e,"Tab")){for(var t,i=this.focusableEls_(),n=this.el_.querySelector(":focus"),r=0;r<i.length;r++)if(n===i[r]){t=r;break}document.activeElement===this.el_&&(t=0),e.shiftKey&&0===t?(i[i.length-1].focus(),e.preventDefault()):e.shiftKey||t!==i.length-1||(i[0].focus(),e.preventDefault())}},t.focusableEls_=function(){var e=this.el_.querySelectorAll("*");return Array.prototype.filter.call(e,function(e){return(e instanceof window.HTMLAnchorElement||e instanceof window.HTMLAreaElement)&&e.hasAttribute("href")||(e instanceof window.HTMLInputElement||e instanceof window.HTMLSelectElement||e instanceof window.HTMLTextAreaElement||e instanceof window.HTMLButtonElement)&&!e.hasAttribute("disabled")||e instanceof window.HTMLIFrameElement||e instanceof window.HTMLObjectElement||e instanceof window.HTMLEmbedElement||e.hasAttribute("tabindex")&&-1!==e.getAttribute("tabindex")||e.hasAttribute("contenteditable")})},e}(pt);At.prototype.options_={pauseOnOpen:!0,temporary:!0},pt.registerComponent("ModalDialog",At);var Pt,Lt=function(n){function e(e){var t;void 0===e&&(e=[]),(t=n.call(this)||this).tracks_=[],Object.defineProperty(ft(t),"length",{get:function(){return this.tracks_.length}});for(var i=0;i<e.length;i++)t.addTrack(e[i]);return t}mt(e,n);var t=e.prototype;return t.addTrack=function(e){var t=this,i=this.tracks_.length;""+i in this||Object.defineProperty(this,i,{get:function(){return this.tracks_[i]}}),-1===this.tracks_.indexOf(e)&&(this.tracks_.push(e),this.trigger({track:e,type:"addtrack",target:this})),e.labelchange_=function(){t.trigger({track:e,type:"labelchange",target:t})},it(e)&&e.addEventListener("labelchange",e.labelchange_)},t.removeTrack=function(e){for(var t,i=0,n=this.length;i<n;i++)if(this[i]===e){(t=this[i]).off&&t.off(),this.tracks_.splice(i,1);break}t&&this.trigger({track:t,type:"removetrack",target:this})},t.getTrackById=function(e){for(var t=null,i=0,n=this.length;i<n;i++){var r=this[i];if(r.id===e){t=r;break}}return t},e}(ze);for(Pt in Lt.prototype.allowedEvents_={change:"change",addtrack:"addtrack",removetrack:"removetrack",labelchange:"labelchange"},Lt.prototype.allowedEvents_)Lt.prototype["on"+Pt]=null;function Dt(e,t){for(var i=0;i<e.length;
4707i++)Object.keys(e[i]).length&&t.id!==e[i].id&&(e[i].enabled=!1)}function Ot(e,t){for(var i=0;i<e.length;i++)Object.keys(e[i]).length&&t.id!==e[i].id&&(e[i].selected=!1)}function Rt(e){var t=["protocol","hostname","port","pathname","search","hash","host"],i=document.createElement("a");i.href=e;for(var n={},r=0;r<t.length;r++)n[t[r]]=i[t[r]];return"http:"===n.protocol&&(n.host=n.host.replace(/:80$/,"")),"https:"===n.protocol&&(n.host=n.host.replace(/:443$/,"")),n.protocol||(n.protocol=window.location.protocol),n.host||(n.host=window.location.host),n}function Mt(e){var t;return e.match(/^https?:\/\//)||((t=document.createElement("a")).href=e,e=t.href),e}function Nt(e){if("string"==typeof e){e=/^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/.exec(e);if(e)return e.pop().toLowerCase()}return""}function Ut(e,t){return void 0===t&&(t=window.location),(":"===(e=Rt(e)).protocol?t:e).protocol+e.host!==t.protocol+t.host}var Bt=function(n){function e(e){for(var t,i=(e=void 0===e?[]:e).length-1;0<=i;i--)if(e[i].enabled){Dt(e,e[i]);break}return(t=n.call(this,e)||this).changing_=!1,t}mt(e,n);var t=e.prototype;return t.addTrack=function(e){var t=this;e.enabled&&Dt(this,e),n.prototype.addTrack.call(this,e),e.addEventListener&&(e.enabledChange_=function(){t.changing_||(t.changing_=!0,Dt(t,e),t.changing_=!1,t.trigger("change"))},e.addEventListener("enabledchange",e.enabledChange_))},t.removeTrack=function(e){n.prototype.removeTrack.call(this,e),e.removeEventListener&&e.enabledChange_&&(e.removeEventListener("enabledchange",e.enabledChange_),e.enabledChange_=null)},e}(Lt),Ft=function(n){function e(e){for(var t,i=(e=void 0===e?[]:e).length-1;0<=i;i--)if(e[i].selected){Ot(e,e[i]);break}return(t=n.call(this,e)||this).changing_=!1,Object.defineProperty(ft(t),"selectedIndex",{get:function(){for(var e=0;e<this.length;e++)if(this[e].selected)return e;return-1},set:function(){}}),t}mt(e,n);var t=e.prototype;return t.addTrack=function(e){var t=this;e.selected&&Ot(this,e),n.prototype.addTrack.call(this,e),e.addEventListener&&(e.selectedChange_=function(){t.changing_||(t.changing_=!0,Ot(t,e),t.changing_=!1,t.trigger("change"))},e.addEventListener("selectedchange",e.selectedChange_))},t.removeTrack=function(e){n.prototype.removeTrack.call(this,e),e.removeEventListener&&e.selectedChange_&&(e.removeEventListener("selectedchange",e.selectedChange_),e.selectedChange_=null)},e}(Lt),k=function(i){function e(){return i.apply(this,arguments)||this}mt(e,i);var t=e.prototype;return t.addTrack=function(e){var t=this;i.prototype.addTrack.call(this,e),this.queueChange_||(this.queueChange_=function(){return t.queueTrigger("change")}),this.triggerSelectedlanguagechange||(this.triggerSelectedlanguagechange_=function(){return t.trigger("selectedlanguagechange")}),e.addEventListener("modechange",this.queueChange_);-1===["metadata","chapters"].indexOf(e.kind)&&e.addEventListener("modechange",this.triggerSelectedlanguagechange_)},t.removeTrack=function(e){i.prototype.removeTrack.call(this,e),e.removeEventListener&&(this.queueChange_&&e.removeEventListener("modechange",this.queueChange_),this.selectedlanguagechange_&&e.removeEventListener("modechange",this.triggerSelectedlanguagechange_))},e}(Lt),jt=function(){function e(e){void 0===e&&(e=[]),this.trackElements_=[],Object.defineProperty(this,"length",{get:function(){return this.trackElements_.length}});for(var t=0,i=e.length;t<i;t++)this.addTrackElement_(e[t])}var t=e.prototype;return t.addTrackElement_=function(e){var t=this.trackElements_.length;""+t in this||Object.defineProperty(this,t,{get:function(){return this.trackElements_[t]}}),-1===this.trackElements_.indexOf(e)&&this.trackElements_.push(e)},t.getTrackElementByTrack_=function(e){for(var t,i=0,n=this.trackElements_.length;i<n;i++)if(e===this.trackElements_[i].track){t=this.trackElements_[i];break}return t},t.removeTrackElement_=function(e){for(var t=0,i=this.trackElements_.length;t<i;t++)if(e===this.trackElements_[t]){this.trackElements_[t].track&&"function"==typeof this.trackElements_[t].track.off&&this.trackElements_[t].track.off(),"function"==typeof this.trackElements_[t].off&&this.trackElements_[t].off(),this.trackElements_.splice(t,1);break}},e}(),Ht=function(){function t(e){t.prototype.setCues_.call(this,e),Object.defineProperty(this,"length",{get:function(){return this.length_}})}var e=t.prototype;return e.setCues_=function(e){var t=this.length||0,i=0,n=e.length;this.cues_=e,this.length_=e.length;function r(e){""+e in this||Object.defineProperty(this,""+e,{get:function(){return this.cues_[e]}})}if(t<n)for(i=t;i<n;i++)r.call(this,i)},e.getCueById=function(e){for(var t=null,i=0,n=this.length;i<n;i++){var r=this[i];if(r.id===e){t=r;break}}return t},t}(),qt={alternative:"alternative",captions:"captions",main:"main",sign:"sign",subtitles:"subtitles",commentary:"commentary"},Vt={alternative:"alternative",descriptions:"descriptions",main:"main","main-desc":"main-desc",translation:"translation",commentary:"commentary"},Wt={subtitles:"subtitles",captions:"captions",descriptions:"descriptions",chapters:"chapters",metadata:"metadata"},Gt={disabled:"disabled",hidden:"hidden",showing:"showing"},C=function(a){function e(e){void 0===e&&(e={});var t,i=a.call(this)||this,n={id:e.id||"vjs_track_"+Pe++,kind:e.kind||"",language:e.language||""},r=e.label||"";for(t in n)!function(e){Object.defineProperty(ft(i),e,{get:function(){return n[e]},set:function(){}})}(t);return Object.defineProperty(ft(i),"label",{get:function(){return r},set:function(e){e!==r&&(r=e,this.trigger("labelchange"))}}),i}return mt(e,a),e}(ze),zt=Object.freeze({__proto__:null,parseUrl:Rt,getAbsoluteURL:Mt,getFileExtension:Nt,isCrossOrigin:Ut}),Xt="undefined"!=typeof window?window:"undefined"!=typeof f?f:"undefined"!=typeof self?self:{},Kt=Xt,Yt=function(e){if(!e)return!1;var t=Qt.call(e);return"[object Function]"===t||"function"==typeof e&&"[object RegExp]"!==t||"undefined"!=typeof window&&(e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt)},Qt=Object.prototype.toString;ei.httpHandler=function(n,r){return void 0===r&&(r=!1),function(e,t,i){if(e)n(e);else if(400<=t.statusCode&&t.statusCode<=599){e=i;if(r)if(Kt.TextDecoder){t=function(e){void 0===e&&(e="");return e.toLowerCase().split(";").reduce(function(e,t){var i=t.split("="),t=i[0],i=i[1];return"charset"===t.trim()?i.trim():e},"utf-8")}(t.headers&&t.headers["content-type"]);try{e=new TextDecoder(t).decode(i)}catch(e){}}else e=String.fromCharCode.apply(null,new Uint8Array(i));n({cause:e})}else n(null,i)}};
4708 /**
4709    * @license
4710    * slighly modified parse-headers 2.0.2 <https://github.com/kesla/parse-headers/>
4711    * Copyright (c) 2014 David Björklund
4712    * Available under the MIT license
4713    * <https://github.com/kesla/parse-headers/blob/master/LICENCE>
4714    */
4715 var $t=function(e){var n={};return e&&e.trim().split("\n").forEach(function(e){var t=e.indexOf(":"),i=e.slice(0,t).trim().toLowerCase(),t=e.slice(t+1).trim();"undefined"==typeof n[i]?n[i]=t:Array.isArray(n[i])?n[i].push(t):n[i]=[n[i],t]}),n},Jt=ei,I=ei;function Zt(e,t,i){var n=e;
4715return Yt(t)?(i=t,"string"==typeof e&&(n={uri:e})):n=g({},t,{uri:e}),n.callback=i,n}function ei(e,t,i){return ti(t=Zt(e,t,i))}function ti(n){if("undefined"==typeof n.callback)throw new Error("callback argument missing");var r=!1,a=function(e,t,i){r||(r=!0,n.callback(e,t,i))};function s(){var e=void 0,e=l.response||l.responseText||function(e){try{if("document"===e.responseType)return e.responseXML;var t=e.responseXML&&"parsererror"===e.responseXML.documentElement.nodeName;if(""===e.responseType&&!t)return e.responseXML}catch(e){}return null}(l);if(m)try{e=JSON.parse(e)}catch(e){}return e}function t(e){return clearTimeout(u),(e=!(e instanceof Error)?new Error(""+(e||"Unknown XMLHttpRequest Error")):e).statusCode=0,a(e,g)}function e(){if(!o){clearTimeout(u);var e=n.useXDR&&void 0===l.status?200:1223===l.status?204:l.status,t=g,i=null;return 0!==e?(t={body:s(),statusCode:e,method:d,headers:{},url:c,rawRequest:l},l.getAllResponseHeaders&&(t.headers=$t(l.getAllResponseHeaders()))):i=new Error("Internal XMLHttpRequest Error"),a(i,t,t.body)}}var i,o,u,l=n.xhr||null,c=(l=l||new(n.cors||n.useXDR?ei.XDomainRequest:ei.XMLHttpRequest)).url=n.uri||n.url,d=l.method=n.method||"GET",h=n.body||n.data,p=l.headers=n.headers||{},f=!!n.sync,m=!1,g={body:void 0,headers:{},statusCode:0,method:d,url:c,rawRequest:l};if("json"in n&&!1!==n.json&&(m=!0,p.accept||p.Accept||(p.Accept="application/json"),"GET"!==d&&"HEAD"!==d&&(p["content-type"]||p["Content-Type"]||(p["Content-Type"]="application/json"),h=JSON.stringify(!0===n.json?h:n.json))),l.onreadystatechange=function(){4===l.readyState&&setTimeout(e,0)},l.onload=e,l.onerror=t,l.onprogress=function(){},l.onabort=function(){o=!0},l.ontimeout=t,l.open(d,c,!f,n.username,n.password),f||(l.withCredentials=!!n.withCredentials),!f&&0<n.timeout&&(u=setTimeout(function(){var e;o||(o=!0,l.abort("timeout"),(e=new Error("XMLHttpRequest timeout")).code="ETIMEDOUT",t(e))},n.timeout)),l.setRequestHeader)for(i in p)p.hasOwnProperty(i)&&l.setRequestHeader(i,p[i]);else if(n.headers&&!function(e){for(var t in e)if(e.hasOwnProperty(t))return;return 1}(n.headers))throw new Error("Headers cannot be set on an XDomainRequest object");return"responseType"in n&&(l.responseType=n.responseType),"beforeSend"in n&&"function"==typeof n.beforeSend&&n.beforeSend(l),l.send(h||null),l}ei.XMLHttpRequest=Kt.XMLHttpRequest||function(){},ei.XDomainRequest="withCredentials"in new ei.XMLHttpRequest?ei.XMLHttpRequest:Kt.XDomainRequest,function(e,t){for(var i=0;i<e.length;i++)t(e[i])}(["get","put","post","patch","head","delete"],function(n){ei["delete"===n?"del":n]=function(e,t,i){return(t=Zt(e,t,i)).method=n.toUpperCase(),ti(t)}}),Jt.default=I;function ii(e,t){var i=new window.WebVTT.Parser(window,window.vttjs,window.WebVTT.StringDecoder()),n=[];i.oncue=function(e){t.addCue(e)},i.onparsingerror=function(e){n.push(e)},i.onflush=function(){t.trigger({type:"loadeddata",target:t})},i.parse(e),0<n.length&&(window.console&&window.console.groupCollapsed&&window.console.groupCollapsed("Text Track parsing errors for "+t.src),n.forEach(function(e){return h.error(e)}),window.console&&window.console.groupEnd&&window.console.groupEnd()),i.flush()}function ni(e,n){var t={uri:e};(e=Ut(e))&&(t.cors=e),(e="use-credentials"===n.tech_.crossOrigin())&&(t.withCredentials=e),Jt(t,Ve(this,function(e,t,i){return e?h.error(e,t):(n.loaded_=!0,void("function"!=typeof window.WebVTT?n.tech_&&n.tech_.any(["vttjsloaded","vttjserror"],function(e){return"vttjserror"!==e.type?ii(i,n):void h.error("vttjs failed to load, stopping trying to process "+n.src)}):ii(i,n)))}))}var ri=function(u){function e(e){var t;if(!(e=void 0===e?{}:e).tech)throw new Error("A tech was not provided.");var e=lt(e,{kind:Wt[e.kind]||"subtitles",language:e.language||e.srclang||""}),i=Gt[e.mode]||"disabled",n=e.default;"metadata"!==e.kind&&"chapters"!==e.kind||(i="hidden"),(t=u.call(this,e)||this).tech_=e.tech,t.cues_=[],t.activeCues_=[],t.preload_=!1!==t.tech_.preloadTextTracks;var r=new Ht(t.cues_),s=new Ht(t.activeCues_),o=!1,a=Ve(ft(t),function(){this.tech_.isReady_&&!this.tech_.isDisposed()&&(this.activeCues=this.activeCues,o&&(this.trigger("cuechange"),o=!1))});return t.tech_.one("dispose",function(){t.tech_.off("timeupdate",a)}),"disabled"!==i&&t.tech_.on("timeupdate",a),Object.defineProperties(ft(t),{default:{get:function(){return n},set:function(){}},mode:{get:function(){return i},set:function(e){Gt[e]&&i!==e&&(i=e,this.preload_||"disabled"===i||
vendor: 6,806 bytes, line 4715
47150!==this.cues.length||ni(this.src,this),this.tech_.off("timeupdate",a),"disabled"!==i&&this.tech_.on("timeupdate",a),this.trigger("modechange"))}},cues:{get:function(){return this.loaded_?r:null},set:function(){}},activeCues:{get:function(){if(!this.loaded_)return null;if(0===this.cues.length)return s;for(var e=this.tech_.currentTime(),t=[],i=0,n=this.cues.length;i<n;i++){var r=this.cues[i];(r.startTime<=e&&r.endTime>=e||r.startTime===r.endTime&&r.startTime<=e&&r.startTime+.5>=e)&&t.push(r)}if(o=!1,t.length!==this.activeCues_.length)o=!0;else for(var a=0;a<t.length;a++)-1===this.activeCues_.indexOf(t[a])&&(o=!0);return this.activeCues_=t,s.setCues_(this.activeCues_),s},set:function(){}}}),e.src?(t.src=e.src,t.preload_||(t.loaded_=!0),(t.preload_||"subtitles"!==e.kind&&"captions"!==e.kind)&&ni(t.src,ft(t))):t.loaded_=!0,t}mt(e,u);var t=e.prototype;return t.addCue=function(e){var t=e;if(window.vttjs&&!(e instanceof window.vttjs.VTTCue)){for(var i in t=new window.vttjs.VTTCue(e.startTime,e.endTime,e.text),e)i in t||(t[i]=e[i]);t.id=e.id,t.originalCue_=e}for(var n=this.tech_.textTracks(),r=0;r<n.length;r++)n[r]!==this&&n[r].removeCue(t);this.cues_.push(t),this.cues.setCues_(this.cues_)},t.removeCue=function(e){for(var t=this.cues_.length;t--;){var i=this.cues_[t];if(i===e||i.originalCue_&&i.originalCue_===e){this.cues_.splice(t,1),this.cues.setCues_(this.cues_);break}}},e}(C);ri.prototype.allowedEvents_={cuechange:"cuechange"};x=function(n){function e(e){var t=lt(e=void 0===e?{}:e,{kind:Vt[e.kind]||""}),e=n.call(this,t)||this,i=!1;return Object.defineProperty(ft(e),"enabled",{get:function(){return i},set:function(e){"boolean"==typeof e&&e!==i&&(i=e,this.trigger("enabledchange"))}}),t.enabled&&(e.enabled=t.enabled),e.loaded_=!0,e}return mt(e,n),e}(C),U=function(n){function e(e){var t=lt(e=void 0===e?{}:e,{kind:qt[e.kind]||""}),e=n.call(this,t)||this,i=!1;return Object.defineProperty(ft(e),"selected",{get:function(){return i},set:function(e){"boolean"==typeof e&&e!==i&&(i=e,this.trigger("selectedchange"))}}),t.selected&&(e.selected=t.selected),e}return mt(e,n),e}(C),j=function(r){function e(e){var t;void 0===e&&(e={});var i=r.call(this)||this,n=new ri(e);return i.kind=n.kind,i.src=n.src,i.srclang=n.language,i.label=n.label,i.default=n.default,Object.defineProperties(ft(i),{readyState:{get:function(){return t}},track:{get:function(){return n}}}),t=0,n.addEventListener("loadeddata",function(){t=2,i.trigger({type:"load",target:ft(i)})}),i}return mt(e,r),e}(ze);j.prototype.allowedEvents_={load:"load"},j.NONE=0,j.LOADING=1,j.LOADED=2,j.ERROR=3;var ai={audio:{ListClass:Bt,TrackClass:x,capitalName:"Audio"},video:{ListClass:Ft,TrackClass:U,capitalName:"Video"},text:{ListClass:k,TrackClass:ri,capitalName:"Text"}};Object.keys(ai).forEach(function(e){ai[e].getterName=e+"Tracks",ai[e].privateName=e+"Tracks_"});var si={remoteText:{ListClass:k,TrackClass:ri,capitalName:"RemoteText",getterName:"remoteTextTracks",privateName:"remoteTextTracks_"},remoteTextEl:{ListClass:jt,TrackClass:j,capitalName:"RemoteTextTrackEls",getterName:"remoteTextTrackEls",privateName:"remoteTextTrackEls_"}},oi=g({},ai,si);si.names=Object.keys(si),ai.names=Object.keys(ai),oi.names=[].concat(si.names).concat(ai.names);var ui="undefined"!=typeof f?f:"undefined"!=typeof window?window:{},li="undefined"!=typeof document?document:(li=ui["__GLOBAL_DOCUMENT_CACHE@4"])||(ui["__GLOBAL_DOCUMENT_CACHE@4"]={}),Xt=li,ci=Object.create||function(e){if(1!==arguments.length)throw new Error("Object.create shim only accepts one parameter.");return di.prototype=e,new di};function di(){}function hi(e,t){this.name="ParsingError",this.code=e.code,this.message=t||e.message}function pi(e){function t(e,t,i,n){return 3600*(0|e)+60*(0|t)+(0|i)+(0|n)/1e3}e=e.match(/^(\d+):(\d{1,2})(:\d{1,2})?\.(\d{3})/);return e?e[3]?t(e[1],e[2],e[3].replace(":",""),e[4]):59<e[1]?t(e[1],e[2],0,e[4]):t(0,e[1],e[2],e[4]):null}function fi(){this.values=ci(null)}function mi(e,t,i,n){var r,a,s=n?e.split(n):[e];for(r in s)"string"==typeof s[r]&&(2===(a=s[r].split(i)).length&&t(a[0],a[1]))}function gi(t,e,s){var i=t;function n(){var e=pi(t);if(null===e)throw new hi(hi.Errors.BadTimeStamp,"Malformed timestamp: "+i);return t=t.replace(/^[^\sa-zA-Z-]+/,""),e}function r(){t=t.replace(/^\s+/,"")}if(r(),e.startTime=n(),r(),"--\x3e"!==t.substr(0,3))throw new hi(hi.Errors.BadTimeStamp,"Malformed time stamp (time stamps must be separated by '--\x3e'): "+i);t=t.substr(3),r(),e.endTime=n(),r(),function(e,t){var a=new fi;mi(e,function(e,t){switch(e){case"region":for(var i=s.length-1;0<=i;i--)if(s[i].id===t){a.set(e,s[i].region);break}break;case"vertical":a.alt(e,t,["rl","lr"]);break;case"line":var n=t.split(","),r=n[0];a.integer(e,r),a.percent(e,r)&&a.set("snapToLines",!1),a.alt(e,r,["auto"]),2===n.length&&a.alt("lineAlign",n[1],["start","center","end"]);break;case"position":n=t.split(","),a.percent(e,n[0]),2===n.length&&a.alt("positionAlign",n[1],["start","center","end"]);break;case"size":a.percent(e,t);break;case"align":a.alt(e,t,["start","center","end","left","right"])}},/:/,/\s/),t.region=a.get("region",null),t.vertical=a.get("vertical","");try{t.line=a.get("line","auto")}catch(e){}t.lineAlign=a.get("lineAlign","start"),t.snapToLines=a.get("snapToLines",!0),t.size=a.get("size",100);try{t.align=a.get("align","center")}catch(e){t.align=a.get("align","middle")}try{t.position=a.get("position","auto")}catch(e){t.position=a.get("position",{start:0,left:0,center:50,middle:50,end:100,right:100},t.align)}t.positionAlign=a.get("positionAlign",{start:"start",left:"start",center:"center",middle:"center",end:"end",right:"end"},t.align)}(t,e)}((hi.prototype=ci(Error.prototype)).constructor=hi).Errors={BadSignature:{code:0,message:"Malformed WebVTT signature."},BadTimeStamp:{code:1,message:"Malformed time stamp."}},fi.prototype={set:function(e,t){this.get(e)||""===t||(this.values[e]=t)},get:function(e,t,i){return i?this.has(e)?this.values[e]:t[i]:this.has(e)?this.values[e]:t},has:function(e){return e in this.values},alt:function(e,t,i){for(var n=0;n<i.length;++n)if(t===i[n]){this.set(e,t);break}},integer:function(e,t){/^-?\d+$/.test(t)&&this.set(e,parseInt(t,10))},percent:function(e,t){return!!(t.match(/^([\d]{1,3})(\.[\d]*)?%$/)&&0<=(t=parseFloat(t))&&t<=100)&&(this.set(e,t),!0)}};var yi=Xt.createElement&&Xt.createElement("textarea"),vi={c:"span",i:"i",b:"b",u:"u",ruby:"ruby",rt:"rt",v:"span",lang:"span"},_i={white:"rgba(255,255,255,1)",lime:"rgba(0,255,0,1)",cyan:"rgba(0,255,255,1)",red:"rgba(255,0,0,1)",yellow:"rgba(255,255,0,1)",magenta:"rgba(255,0,255,1)",blue:"rgba(0,0,255,1)",black:"rgba(0,0,0,1)"},bi={v:"title",lang:"lang"},Ti={rt:"ruby"};function Si(e,t){for(var i,n,r,a,s,o,u,l,c,d,h=e.document.createElement("div"),p=h,f=[];null!==(i=function(){if(!t)return null;var e=t.match(/^([^<]*)(<[^>
4715]*>?)?/);return e=e[1]||e[2],t=t.substr(e.length),e}());)"<"!==i[0]?p.appendChild(e.document.createTextNode((s=i,yi.innerHTML=s,s=yi.textContent,yi.textContent="",s))):"/"!==i[1]?(a=pi(i.substr(1,i.length-2)))?(n=e.document.createProcessingInstruction("timestamp",a),p.appendChild(n)):(r=i.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/))&&(l=r[1],c=r[3],d=void 0,d=vi[l],(n=d?(d=e.document.createElement(d),(l=bi[l])&&c&&(d[l]=c.trim()),d):null)&&(o=p,Ti[(u=n).localName]&&Ti[u.localName]!==o.localName||(r[2]&&((a=r[2].split(".")).forEach(function(e){var t=/^bg_/.test(e),e=t?e.slice(3):e;_i.hasOwnProperty(e)&&(e=_i[e],n.style[t?"background-color":"color"]=e)}),n.className=a.join(" ")),f.push(r[1]),p.appendChild(n),p=n))):f.length&&f[f.length-1]===i.substr(2).replace(">","")&&(f.pop(),p=p.parentNode);return h}var wi=[[1470,1470],[1472,1472],[1475,1475],[1478,1478],[1488,1514],[1520,1524],[1544,1544],[1547,1547],[1549,1549],[1563,1563],[1566,1610],[1645,1647],[1649,1749],[1765,1766],[1774,1775],[1786,1805],[1807,1808],[1810,1839],[1869,1957],[1969,1969],[1984,2026],[2036,2037],[2042,2042],[2048,2069],[2074,2074],[2084,2084],[2088,2088],[2096,2110],[2112,2136],[2142,2142],[2208,2208],[2210,2220],[8207,8207],[64285,64285],[64287,64296],[64298,64310],[64312,64316],[64318,64318],[64320,64321],[64323,64324],[64326,64449],[64467,64829],[64848,64911],[64914,64967],[65008,65020],[65136,65140],[65142,65276],[67584,67589],[67592,67592],[67594,67637],[67639,67640],[67644,67644],[67647,67669],[67671,67679],[67840,67867],[67872,67897],[67903,67903],[67968,68023],[68030,68031],[68096,68096],[68112,68115],[68117,68119],[68121,68147],[68160,68167],[68176,68184],[68192,68223],[68352,68405],[68416,68437],[68440,68466],[68472,68479],[68608,68680],[126464,126467],[126469,126495],[126497,126498],[126500,126500],[126503,126503],[126505,126514],[126516,126519],[126521,126521],[126523,126523],[126530,126530],[126535,126535],[126537,126537],[126539,126539],[126541,126543],[126545,126546],[126548,126548],[126551,126551],[126553,126553],[126555,126555],[126557,126557],[126559,126559],[126561,126562],[126564,126564],[126567,126570],[126572,126578],[126580,126583],[126585,126588],[126590,126590],[126592,126601],[126603,126619],[126625,126627],[126629,126633],[126635,126651],[1114109,1114109]];function Ei(e){var t=[],i="";if(!e||!e.childNodes)return"ltr";function a(e,t){for(var i=t.childNodes.length-1;0<=i;i--)e.push(t.childNodes[i])}for(a(t,e);i=function e(t){if(!t||!t.length)return null;var i=t.pop(),n=i.textContent||i.innerText;if(n){var r=n.match(/^.*(\n|\r)/);return r?r[t.length=0]:n}return"ruby"===i.tagName?e(t):i.childNodes?(a(t,i),e(t)):void 0}(t);)for(var n=0;n<i.length;n++)if(function(e){for(var t=0;t<wi.length;t++){var i=wi[t];if(e>=i[0]&&e<=i[1])return 1}}(i.charCodeAt(n)))return"rtl";return"ltr"}function ki(){}function Ci(e,t,i){ki.call(this),this.cue=t,this.cueDiv=Si(e,t.text);var n={color:"rgba(255, 255, 255, 1)",backgroundColor:"rgba(0, 0, 0, 0.8)",position:"relative",left:0,right:0,top:0,bottom:0,display:"inline",writingMode:""===t.vertical?"horizontal-tb":"lr"===t.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext"};this.applyStyles(n,this.cueDiv),this.div=e.document.createElement("div"),n={direction:Ei(this.cueDiv),writingMode:""===t.vertical?"horizontal-tb":"lr"===t.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext",textAlign:"middle"===t.align?"center":t.align,font:i.font,whiteSpace:"pre-line",position:"absolute"},this.applyStyles(n),this.div.appendChild(this.cueDiv);var r=0;switch(t.positionAlign){case"start":r=t.position;break;case"center":r=t.position-t.size/2;break;case"end":r=t.position-t.size}""===t.vertical?this.applyStyles({left:this.formatStyle(r,"%"),width:this.formatStyle(t.size,"%")}):this.applyStyles({top:this.formatStyle(r,"%"),height:this.formatStyle(t.size,"%")}),this.move=function(e){this.applyStyles({top:this.formatStyle(e.top,"px"),bottom:this.formatStyle(e.bottom,"px"),left:this.formatStyle(e.left,"px"),right:this.formatStyle(e.right,"px"),height:this.formatStyle(e.height,"px"),width:this.formatStyle(e.width,"px")}
vendor: 4,315 bytes, line 4715
4715)}}function Ii(e){var t,i,n,r;e.div&&(t=e.div.offsetHeight,i=e.div.offsetWidth,n=e.div.offsetTop,r=(r=e.div.childNodes)&&(r=r[0])&&r.getClientRects&&r.getClientRects(),e=e.div.getBoundingClientRect(),r=r?Math.max(r[0]&&r[0].height||0,e.height/r.length):0),this.left=e.left,this.right=e.right,this.top=e.top||n,this.height=e.height||t,this.bottom=e.bottom||n+(e.height||t),this.width=e.width||i,this.lineHeight=void 0!==r?r:e.lineHeight}function xi(e,t,o,u){var i,n=new Ii(t),r=t.cue,a=function(e){if("number"==typeof e.line&&(e.snapToLines||0<=e.line&&e.line<=100))return e.line;if(!e.track||!e.track.textTrackList||!e.track.textTrackList.mediaElement)return-1;for(var t=e.track,i=t.textTrackList,n=0,r=0;r<i.length&&i[r]!==t;r++)"showing"===i[r].mode&&n++;return-1*++n}(r),s=[];if(r.snapToLines){switch(r.vertical){case"":s=["+y","-y"],i="height";break;case"rl":s=["+x","-x"],i="width";break;case"lr":s=["-x","+x"],i="width"}var l=n.lineHeight,c=l*Math.round(a),d=o[i]+l,h=s[0];Math.abs(c)>d&&(c=c<0?-1:1,c*=Math.ceil(d/l)*l),a<0&&(c+=""===r.vertical?o.height:o.width,s=s.reverse()),n.move(h,c)}else{var p=n.lineHeight/o.height*100;switch(r.lineAlign){case"center":a-=p/2;break;case"end":a-=p}switch(r.vertical){case"":t.applyStyles({top:t.formatStyle(a,"%")});break;case"rl":t.applyStyles({left:t.formatStyle(a,"%")});break;case"lr":t.applyStyles({right:t.formatStyle(a,"%")})}s=["+y","-x","+x","-y"],n=new Ii(t)}n=function(e,t){for(var i,n=new Ii(e),r=1,a=0;a<t.length;a++){for(;e.overlapsOppositeAxis(o,t[a])||e.within(o)&&e.overlapsAny(u);)e.move(t[a]);if(e.within(o))return e;var s=e.intersectPercentage(o);s<r&&(i=new Ii(e),r=s),e=new Ii(n)}return i||n}(n,s);t.move(n.toCSSCompatValues(o))}function Ai(){}ki.prototype.applyStyles=function(e,t){for(var i in t=t||this.div,e)e.hasOwnProperty(i)&&(t.style[i]=e[i])},ki.prototype.formatStyle=function(e,t){return 0===e?0:e+t},(Ci.prototype=ci(ki.prototype)).constructor=Ci,Ii.prototype.move=function(e,t){switch(t=void 0!==t?t:this.lineHeight,e){case"+x":this.left+=t,this.right+=t;break;case"-x":this.left-=t,this.right-=t;break;case"+y":this.top+=t,this.bottom+=t;break;case"-y":this.top-=t,this.bottom-=t}},Ii.prototype.overlaps=function(e){return this.left<e.right&&this.right>e.left&&this.top<e.bottom&&this.bottom>e.top},Ii.prototype.overlapsAny=function(e){for(var t=0;t<e.length;t++)if(this.overlaps(e[t]))return!0;return!1},Ii.prototype.within=function(e){return this.top>=e.top&&this.bottom<=e.bottom&&this.left>=e.left&&this.right<=e.right},Ii.prototype.overlapsOppositeAxis=function(e,t){switch(t){case"+x":return this.left<e.left;case"-x":return this.right>e.right;case"+y":return this.top<e.top;case"-y":return this.bottom>e.bottom}},Ii.prototype.intersectPercentage=function(e){return Math.max(0,Math.min(this.right,e.right)-Math.max(this.left,e.left))*Math.max(0,Math.min(this.bottom,e.bottom)-Math.max(this.top,e.top))/(this.height*this.width)},Ii.prototype.toCSSCompatValues=function(e){return{top:this.top-e.top,bottom:e.bottom-this.bottom,left:this.left-e.left,right:e.right-this.right,height:this.height,width:this.width}},Ii.getSimpleBoxPosition=function(e){var t=e.div?e.div.offsetHeight:e.tagName?e.offsetHeight:0,i=e.div?e.div.offsetWidth:e.tagName?e.offsetWidth:0,n=e.div?e.div.offsetTop:e.tagName?e.offsetTop:0;return{left:(e=e.div?e.div.getBoundingClientRect():e.tagName?e.getBoundingClientRect():e).left,right:e.right,top:e.top||n,height:e.height||t,bottom:e.bottom||n+(e.height||t),width:e.width||i}},Ai.StringDecoder=function(){return{decode:function(e){if(!e)return"";if("string"!=typeof e)throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(e))}}},Ai.convertCueToDOMTree=function(e,t){return e&&t?Si(e,t):null};Ai.processCues=function(n,r,e){if(!n||!r||!e)return null;for(;e.firstChild;)e.removeChild(e.firstChild);var a=n.document.createElement("div");if(a.style.position="absolute",a.style.left="0",a.style.right="0",a.style.top="0",a.style.bottom="0",a.style.margin="1.5%",e.appendChild(a),function(e){for(var t=0;t<e.length;t++)if(e[t].hasBeenReset||!e[t].displayState)return 1}(r)){var s=[],o=Ii.getSimpleBoxPosition(a),u={font:Math.round(.05*o.height*100)/100+"px sans-serif"};!function(){for(var e,t,i=0;i<r.length;i++)t=r[i],e=new Ci(n,t,u),a.appendChild(e.div),xi(0,e,o,s),t.dis
vendor: 3,752 bytes, line 4715
4715playState=e.div,s.push(Ii.getSimpleBoxPosition(e))}()}else for(var t=0;t<r.length;t++)a.appendChild(r[t].displayState)},(Ai.Parser=function(e,t,i){i||(i=t,t={}),t=t||{},this.window=e,this.vttjs=t,this.state="INITIAL",this.buffer="",this.decoder=i||new TextDecoder("utf8"),this.regionList=[]}).prototype={reportOrThrowError:function(e){if(!(e instanceof hi))throw e;this.onparsingerror&&this.onparsingerror(e)},parse:function(e){var n=this;function t(){for(var e=n.buffer,t=0;t<e.length&&"\r"!==e[t]&&"\n"!==e[t];)++t;var i=e.substr(0,t);return"\r"===e[t]&&++t,"\n"===e[t]&&++t,n.buffer=e.substr(t),i}function i(e){e.match(/X-TIMESTAMP-MAP/)?mi(e,function(e,t){var i;"X-TIMESTAMP-MAP"===e&&(t=t,i=new fi,mi(t,function(e,t){switch(e){case"MPEGT":i.integer(e+"S",t);break;case"LOCA":i.set(e+"L",pi(t))}},/[^\d]:/,/,/),n.ontimestampmap&&n.ontimestampmap({MPEGTS:i.get("MPEGTS"),LOCAL:i.get("LOCAL")}))},/=/):mi(e,function(e,t){var r;"Region"===e&&(t=t,r=new fi,mi(t,function(e,t){switch(e){case"id":r.set(e,t);break;case"width":r.percent(e,t);break;case"lines":r.integer(e,t);break;case"regionanchor":case"viewportanchor":var i=t.split(",");if(2!==i.length)break;var n=new fi;if(n.percent("x",i[0]),n.percent("y",i[1]),!n.has("x")||!n.has("y"))break;r.set(e+"X",n.get("x")),r.set(e+"Y",n.get("y"));break;case"scroll":r.alt(e,t,["up"])}},/=/,/\s/),r.has("id")&&((t=new(n.vttjs.VTTRegion||n.window.VTTRegion)).width=r.get("width",100),t.lines=r.get("lines",3),t.regionAnchorX=r.get("regionanchorX",0),t.regionAnchorY=r.get("regionanchorY",100),t.viewportAnchorX=r.get("viewportanchorX",0),t.viewportAnchorY=r.get("viewportanchorY",100),t.scroll=r.get("scroll",""),n.onregion&&n.onregion(t),n.regionList.push({id:r.get("id"),region:t})))},/:/)}e&&(n.buffer+=n.decoder.decode(e,{stream:!0}));try{if("INITIAL"===n.state){if(!/\r\n|\n/.test(n.buffer))return this;var r,a=(r=t()).match(/^WEBVTT([ \t].*)?$/);if(!a||!a[0])throw new hi(hi.Errors.BadSignature);n.state="HEADER"}for(var s=!1;n.buffer;){if(!/\r\n|\n/.test(n.buffer))return this;switch(s?s=!1:r=t(),n.state){case"HEADER":/:/.test(r)?i(r):r||(n.state="ID");continue;case"NOTE":r||(n.state="ID");continue;case"ID":if(/^NOTE($|[ \t])/.test(r)){n.state="NOTE";break}if(!r)continue;n.cue=new(n.vttjs.VTTCue||n.window.VTTCue)(0,0,"");try{n.cue.align="center"}catch(e){n.cue.align="middle"}if(n.state="CUE",-1===r.indexOf("--\x3e")){n.cue.id=r;continue}case"CUE":try{gi(r,n.cue,n.regionList)}catch(e){n.reportOrThrowError(e),n.cue=null,n.state="BADCUE";continue}n.state="CUETEXT";continue;case"CUETEXT":var o=-1!==r.indexOf("--\x3e");if(!r||o&&(s=!0)){n.oncue&&n.oncue(n.cue),n.cue=null,n.state="ID";continue}n.cue.text&&(n.cue.text+="\n"),n.cue.text+=r.replace(/\u2028/g,"\n").replace(/u2029/g,"\n");continue;case"BADCUE":r||(n.state="ID");continue}}}catch(e){n.reportOrThrowError(e),"CUETEXT"===n.state&&n.cue&&n.oncue&&n.oncue(n.cue),n.cue=null,n.state="INITIAL"===n.state?"BADWEBVTT":"BADCUE"}return this},flush:function(){var t=this;try{if(t.buffer+=t.decoder.decode(),!t.cue&&"HEADER"!==t.state||(t.buffer+="\n\n",t.parse()),"INITIAL"===t.state)throw new hi(hi.Errors.BadSignature)}catch(e){t.reportOrThrowError(e)}return t.onflush&&t.onflush(),this}};var Pi=Ai,Li={"":1,lr:1,rl:1},Di={start:1,center:1,end:1,left:1,right:1,auto:1,"line-left":1,"line-right":1};function Oi(e){return"string"==typeof e&&(!!Di[e.toLowerCase()]&&e.toLowerCase())}function Ri(e,t,i){this.hasBeenReset=!1;var n="",r=!1,a=e,s=t,o=i,u=null,l="",c=!0,d="auto",h="start",p="auto",f="auto",m=100,g="center";Object.defineProperties(this,{id:{enumerable:!0,get:function(){return n},set:function(e){n=""+e}},pauseOnExit:{enumerable:!0,get:function(){return r},set:function(e){r=!!e}},startTime:{enumerable:!0,get:function(){return a}
vendor: 2,805 bytes, line 4715
4715,set:function(e){if("number"!=typeof e)throw new TypeError("Start time must be set to a number.");a=e,this.hasBeenReset=!0}},endTime:{enumerable:!0,get:function(){return s},set:function(e){if("number"!=typeof e)throw new TypeError("End time must be set to a number.");s=e,this.hasBeenReset=!0}},text:{enumerable:!0,get:function(){return o},set:function(e){o=""+e,this.hasBeenReset=!0}},region:{enumerable:!0,get:function(){return u},set:function(e){u=e,this.hasBeenReset=!0}},vertical:{enumerable:!0,get:function(){return l},set:function(e){e="string"==typeof(e=e)&&(!!Li[e.toLowerCase()]&&e.toLowerCase());if(!1===e)throw new SyntaxError("Vertical: an invalid or illegal direction string was specified.");l=e,this.hasBeenReset=!0}},snapToLines:{enumerable:!0,get:function(){return c},set:function(e){c=!!e,this.hasBeenReset=!0}},line:{enumerable:!0,get:function(){return d},set:function(e){if("number"!=typeof e&&"auto"!==e)throw new SyntaxError("Line: an invalid number or illegal string was specified.");d=e,this.hasBeenReset=!0}},lineAlign:{enumerable:!0,get:function(){return h},set:function(e){e=Oi(e);e&&(h=e,this.hasBeenReset=!0)}},position:{enumerable:!0,get:function(){return p},set:function(e){if(e<0||100<e)throw new Error("Position must be between 0 and 100.");p=e,this.hasBeenReset=!0}},positionAlign:{enumerable:!0,get:function(){return f},set:function(e){e=Oi(e);e&&(f=e,this.hasBeenReset=!0)}},size:{enumerable:!0,get:function(){return m},set:function(e){if(e<0||100<e)throw new Error("Size must be between 0 and 100.");m=e,this.hasBeenReset=!0}},align:{enumerable:!0,get:function(){return g},set:function(e){e=Oi(e);if(!e)throw new SyntaxError("align: an invalid or illegal alignment string was specified.");g=e,this.hasBeenReset=!0}}}),this.displayState=void 0}Ri.prototype.getCueAsHTML=function(){return WebVTT.convertCueToDOMTree(window,this.text)};var Mi=Ri,Ni={"":!0,up:!0};function Ui(e){return"number"==typeof e&&0<=e&&e<=100}function Bi(){var t=100,i=3,n=0,r=100,a=0,s=100,o="";Object.defineProperties(this,{width:{enumerable:!0,get:function(){return t},set:function(e){if(!Ui(e))throw new Error("Width must be between 0 and 100.");t=e}},lines:{enumerable:!0,get:function(){return i},set:function(e){if("number"!=typeof e)throw new TypeError("Lines must be set to a number.");i=e}},regionAnchorY:{enumerable:!0,get:function(){return r},set:function(e){if(!Ui(e))throw new Error("RegionAnchorX must be between 0 and 100.");r=e}},regionAnchorX:{enumerable:!0,get:function(){return n},set:function(e){if(!Ui(e))throw new Error("RegionAnchorY must be between 0 and 100.");n=e}},viewportAnchorY:{enumerable:!0,get:function(){return s},set:function(e){if(!Ui(e))throw new Error("ViewportAnchorY must be between 0 and 100.");s=e}},viewportAnchorX:{enumerable:!0,get:function(){return a}
vendor: 8,367 bytes, line 4715
4715,set:function(e){if(!Ui(e))throw new Error("ViewportAnchorX must be between 0 and 100.");a=e}},scroll:{enumerable:!0,get:function(){return o},set:function(e){e="string"==typeof(e=e)&&(!!Ni[e.toLowerCase()]&&e.toLowerCase());!1===e||(o=e)}}})}var Fi=m(function(e){e=e.exports={WebVTT:Pi,VTTCue:Mi,VTTRegion:Bi};Kt.vttjs=e,Kt.WebVTT=e.WebVTT;var t=e.VTTCue,i=e.VTTRegion,n=Kt.VTTCue,r=Kt.VTTRegion;e.shim=function(){Kt.VTTCue=t,Kt.VTTRegion=i},e.restore=function(){Kt.VTTCue=n,Kt.VTTRegion=r},Kt.VTTCue||e.shim()});Fi.WebVTT,Fi.VTTCue,Fi.VTTRegion;var ji=function(n){function i(t,e){var i;return void 0===e&&(e=function(){}),(t=void 0===t?{}:t).reportTouchActivity=!1,(i=n.call(this,null,t,e)||this).onDurationChange_=function(e){return i.onDurationChange(e)},i.trackProgress_=function(e){return i.trackProgress(e)},i.trackCurrentTime_=function(e){return i.trackCurrentTime(e)},i.stopTrackingCurrentTime_=function(e){return i.stopTrackingCurrentTime(e)},i.disposeSourceHandler_=function(e){return i.disposeSourceHandler(e)},i.hasStarted_=!1,i.on("playing",function(){this.hasStarted_=!0}),i.on("loadstart",function(){this.hasStarted_=!1}),oi.names.forEach(function(e){e=oi[e];t&&t[e.getterName]&&(i[e.privateName]=t[e.getterName])}),i.featuresProgressEvents||i.manualProgressOn(),i.featuresTimeupdateEvents||i.manualTimeUpdatesOn(),["Text","Audio","Video"].forEach(function(e){!1===t["native"+e+"Tracks"]&&(i["featuresNative"+e+"Tracks"]=!1)}),!1===t.nativeCaptions||!1===t.nativeTextTracks?i.featuresNativeTextTracks=!1:!0!==t.nativeCaptions&&!0!==t.nativeTextTracks||(i.featuresNativeTextTracks=!0),i.featuresNativeTextTracks||i.emulateTextTracks(),i.preloadTextTracks=!1!==t.preloadTextTracks,i.autoRemoteTextTracks_=new oi.text.ListClass,i.initTrackListeners(),t.nativeControlsForTouch||i.emitTapEvents(),i.constructor&&(i.name_=i.constructor.name||"Unknown Tech"),i}mt(i,n);var e=i.prototype;return e.triggerSourceset=function(e){var t=this;this.isReady_||this.one("ready",function(){return t.setTimeout(function(){return t.triggerSourceset(e)},1)}),this.trigger({src:e,type:"sourceset"})},e.manualProgressOn=function(){this.on("durationchange",this.onDurationChange_),this.manualProgress=!0,this.one("ready",this.trackProgress_)},e.manualProgressOff=function(){this.manualProgress=!1,this.stopTrackingProgress(),this.off("durationchange",this.onDurationChange_)},e.trackProgress=function(e){this.stopTrackingProgress(),this.progressInterval=this.setInterval(Ve(this,function(){var e=this.bufferedPercent();this.bufferedPercent_!==e&&this.trigger("progress"),1===(this.bufferedPercent_=e)&&this.stopTrackingProgress()}),500)},e.onDurationChange=function(e){this.duration_=this.duration()},e.buffered=function(){return vt(0,0)},e.bufferedPercent=function(){return _t(this.buffered(),this.duration_)},e.stopTrackingProgress=function(){this.clearInterval(this.progressInterval)},e.manualTimeUpdatesOn=function(){this.manualTimeUpdates=!0,this.on("play",this.trackCurrentTime_),this.on("pause",this.stopTrackingCurrentTime_)},e.manualTimeUpdatesOff=function(){this.manualTimeUpdates=!1,this.stopTrackingCurrentTime(),this.off("play",this.trackCurrentTime_),this.off("pause",this.stopTrackingCurrentTime_)},e.trackCurrentTime=function(){this.currentTimeInterval&&this.stopTrackingCurrentTime(),this.currentTimeInterval=this.setInterval(function(){this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},250)},e.stopTrackingCurrentTime=function(){this.clearInterval(this.currentTimeInterval),this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},e.dispose=function(){this.clearTracks(ai.names),this.manualProgress&&this.manualProgressOff(),this.manualTimeUpdates&&this.manualTimeUpdatesOff(),n.prototype.dispose.call(this)},e.clearTracks=function(e){var r=this;(e=[].concat(e)).forEach(function(e){for(var t=r[e+"Tracks"]()||[],i=t.length;i--;){var n=t[i];"text"===e&&r.removeRemoteTextTrack(n),t.removeTrack(n)}})},e.cleanupAutoTextTracks=function(){for(var e=this.autoRemoteTextTracks_||[],t=e.length;t--;){var i=e[t];this.removeRemoteTextTrack(i)}},e.reset=function(){},e.crossOrigin=function(){},e.setCrossOrigin=function(){},e.error=function(e){return void 0!==e&&(this.error_=new bt(e),this.trigger("error")),this.error_},e.played=function(){return this.hasStarted_?vt(0,0):vt()},e.play=function(){},e.setScrubbing=function(){},e.scrubbing=function(){},e.setCurrentTime=function(){this.manualTimeUpdates&&this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},e.initTrackListeners=function(){var r=this;ai.names.forEach(function(e){function t(){r.trigger(e+"trackchange")}var i=ai[e],n=r[i.getterName]();n.addEventListener("removetrack",t),n.addEventListener("addtrack",t),r.on("dispose",function(){n.removeEventListener("removetrack",t),n.removeEventListener("addtrack",t)})})},e.addWebVttScript_=function(){var e,t=this;window.WebVTT||(document.body.contains(this.el())?!this.options_["vtt.js"]&&S(Fi)&&0<Object.keys(Fi).length?this.trigger("vttjsloaded"):((e=document.createElement("script")).src=this.options_["vtt.js"]||"https://vjs.zencdn.net/vttjs/0.14.1/vtt.min.js",e.onload=function(){t.trigger("vttjsloaded")},e.onerror=function(){t.trigger("vttjserror")},this.on("dispose",function(){e.onload=null,e.onerror=null}),window.WebVTT=!0,this.el().parentNode.appendChild(e)):this.ready(this.addWebVttScript_))},e.emulateTextTracks=function(){function t(e){return n.addTrack(e.track)}function i(e){return n.removeTrack(e.track)}var e=this,n=this.textTracks(),r=this.remoteTextTracks();r.on("addtrack",t),r.on("removetrack",i),this.addWebVttScript_();function a(){return e.trigger("texttrackchange")}function s(){a();for(var e=0;e<n.length;e++){var t=n[e];t.removeEventListener("cuechange",a),"showing"===t.mode&&t.addEventListener("cuechange",a)}}s(),n.addEventListener("change",s),n.addEventListener("addtrack",s),n.addEventListener("removetrack",s),this.on("dispose",function(){r.off("addtrack",t),r.off("removetrack",i),n.removeEventListener("change",s),n.removeEventListener("addtrack",s),n.removeEventListener("removetrack",s);for(var e=0;e<n.length;e++)n[e].removeEventListener("cuechange",a)})},e.addTextTrack=function(e,t,i){if(!e)throw new Error("TextTrack kind is required but was not provided");return function(e,t,i,n,r){void 0===r&&(r={});var a=e.textTracks();return r.kind=t,i&&(r.label=i),n&&(r.language=n),r.tech=e,r=new oi.text.TrackClass(r),a.addTrack(r),r}(this,e,t,i)},e.createRemoteTextTrack=function(e){e=lt(e,{tech:this});return new si.remoteTextEl.TrackClass(e)},e.addRemoteTextTrack=function(e,t){var i=this,n=this.createRemoteTextTrack(e=void 0===e?{}:e);return!0!==t&&!1!==t&&(h.warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js'),t=!0),this.remoteTextTrackEls().addTrackElement_(n),this.remoteTextTracks().addTrack(n.track),!0!==t&&this.ready(function(){return i.autoRemoteTextTracks_.addTrack(n.track)}),n},e.removeRemoteTextTrack=function(e){var t=this.remoteTextTrackEls().getTrackElementByTrack_(e);this.remoteTextTrackEls().removeTrackElement_(t),this.remoteTextTracks().removeTrack(e),this.autoRemoteTextTracks_.removeTrack(e)},e.getVideoPlaybackQuality=function(){return{}},e.requestPictureInPicture=function(){var e=this.options_.Promise||window.Promise;if(e)return e.reject()},e.disablePictureInPicture=function(){return!0},e.setDisablePictureInPicture=function(){},e.setPoster=function(){},e.playsinline=function(){},e.setPlaysinline=function(){},e.overrideNativeAudioTracks=function(){},e.overrideNativeVideoTracks=function(){},e.canPlayType=function(){return""},i.canPlayType=function(){return""},i.canPlaySource=function(e,t){return i.canPlayType(e.type)},i.isTech=function(e){return e.prototype instanceof i||e instanceof i||e===i},i.registerTech=function(e,t){if(i.techs_||(i.techs_={}),!i.isTech(t))throw new Error("Tech "+e+" must be a Tech");if(!i.canPlayType)throw new Error("Techs must have a static canPlayType method on them");if(!i.canPlaySource)throw new Error("Techs must have a static canPlaySource method on them");return e=ut(e),i.techs_[e]=t,i.techs_[ot(e)]=t,"Tech"!==e&&i.defaultTechOrder_.push(e),t},i.getTech=function(e){if(e)return i.techs_&&i.techs_[e]?i.techs_[e]:(e=ut(e),window&&window.videojs&&window.videojs[e]?(h.warn("The "+e+" tech w
4715as added to the videojs object when it should be registered using videojs.registerTech(name, tech)"),window.videojs[e]):void 0)},i}(pt);oi.names.forEach(function(e){var t=oi[e];ji.prototype[t.getterName]=function(){return this[t.privateName]=this[t.privateName]||new t.ListClass,this[t.privateName]}}),ji.prototype.featuresVolumeControl=!0,ji.prototype.featuresMuteControl=!0,ji.prototype.featuresFullscreenResize=!1,ji.prototype.featuresPlaybackRate=!1,ji.prototype.featuresProgressEvents=!1,ji.prototype.featuresSourceset=!1,ji.prototype.featuresTimeupdateEvents=!1,ji.prototype.featuresNativeTextTracks=!1,ji.withSourceHandlers=function(r){r.registerSourceHandler=function(e,t){var i=(i=r.sourceHandlers)||(r.sourceHandlers=[]);void 0===t&&(t=i.length),i.splice(t,0,e)},r.canPlayType=function(e){for(var t,i=r.sourceHandlers||[],n=0;n<i.length;n++)if(t=i[n].canPlayType(e))return t;return""},r.selectSourceHandler=function(e,t){for(var i=r.sourceHandlers||[],n=0;n<i.length;n++)if(i[n].canHandleSource(e,t))return i[n];return null},r.canPlaySource=function(e,t){var i=r.selectSourceHandler(e,t);return i?i.canHandleSource(e,t):""};["seekable","seeking","duration"].forEach(function(e){var t=this[e];"function"==typeof t&&(this[e]=function(){return this.sourceHandler_&&this.sourceHandler_[e]?this.sourceHandler_[e].apply(this.sourceHandler_,arguments):t.apply(this,arguments)})},r.prototype),r.prototype.setSource=function(e){var t=r.selectSourceHandler(e,this.options_);t||(r.nativeSourceHandler?t=r.nativeSourceHandler:h.error("No source handler found for the current source.")),this.disposeSourceHandler(),this.off("dispose",this.disposeSourceHandler_),t!==r.nativeSourceHandler&&(this.currentSource_=e),this.sourceHandler_=t.handleSource(e,this,this.options_),this.one("dispose",this.disposeSourceHandler_)},r.prototype.disposeSourceHandler=function(){this.currentSource_&&(this.clearTracks(["audio","video"]),this.currentSource_=null),this.cleanupAutoTextTracks(),this.sourceHandler_&&(this.sourceHandler_.dispose&&this.sourceHandler_.dispose(),this.sourceHandler_=null)}},pt.registerComponent("Tech",ji),ji.registerTech("Tech",ji),ji.defaultTechOrder_=[];var Hi={},qi={},Vi={};function Wi(e,t,i){e.setTimeout(function(){return function i(n,e,r,a,s,o){void 0===n&&(n={});void 0===e&&(e=[]);void 0===s&&(s=[]);void 0===o&&(o=!1);var t=e,e=t[0],u=t.slice(1);if("string"==typeof e)i(n,Hi[e],r,a,s,o);else if(e){var l=Qi(a,e);if(!l.setSource)return s.push(l),i(n,u,r,a,s,o);l.setSource(b({},n),function(e,t){return e?i(n,u,r,a,s,o):(s.push(l),void i(t,n.type===t.type?u:Hi[t.type],r,a,s,o))})}else u.length?i(n,u,r,a,s,o):o?r(n,s):i(n,Hi["*"],r,a,s,!0)}(t,Hi[t.type],i,e)},1)}function Gi(e,t,i,n){void 0===n&&(n=null);var r="call"+ut(i),r=e.reduce(Yi(r),n),n=r===Vi,r=n?null:t[i](r);return function(e,t,i,n){for(var r=e.length-1;0<=r;r--){var a=e[r];a[t]&&a[t](n,i)}}(e,i,r,n),r}var zi={buffered:1,currentTime:1,duration:1,muted:1,played:1,paused:1,seekable:1,volume:1,ended:1},Xi={setCurrentTime:1,setMuted:1,setVolume:1},Ki={play:1,pause:1};function Yi(i){return function(e,t){return e===Vi?Vi:t[i]?t[i](e):e}}function Qi(e,t){var i=qi[e.id()],n=null;if(null==i)return n=t(e),qi[e.id()]=[[t,n]],n;for(var r=0;r<i.length;r++){var a=i[r],s=a[0],a=a[1];s===t&&(n=a)}return null===n&&(n=t(e),i.push([t,n])),n}function $i(e){return e=Nt(e=void 0===e?"":e),Zi[e.toLowerCase()]||""}function Ji(e){var t;return e=Array.isArray(e)?(t=[],e.forEach(function(e){e=Ji(e),Array.isArray(e)?t=t.concat(e):T(e)&&t.push(e)}),t):"string"==typeof e&&e.trim()?[en({src:e})]:T(e)&&"string"==typeof e.src&&e.src&&e.src.trim()?[en(e)]:[]}var Zi={opus:"video/ogg",ogv:"video/ogg",mp4:"video/mp4",mov:"video/mp4",m4v:"video/mp4",mkv:"video/x-matroska",m4a:"audio/mp4",mp3:"audio/mpeg",aac:"audio/aac",caf:"audio/x-caf",flac:"audio/flac",oga:"audio/ogg",wav:"audio/wav",m3u8:"application/x-mpegURL",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",png:"image/png",svg:"image/svg+xml",webp:"image/webp"};function en(e){var t;return e.type||(t=$i(e.src))&&(e.type=t),e}I=function(u){function e(e,t,i){var n=lt({createEl:!1},t),i=u.call(this,e,n,i)||this;if(t.playerOptions.sources&&0!==t.playerOptions.sources.length)e.src(t.playerOptions.sources);else for(var r=0,a=t.playerOptions.techOrder;r<a.length;r++){var s=ut(a[r]),o=ji.getTech(s);if((o=!s?pt.getComponent(s):o)&&o.isSupported()){e.loadTech_(s);break}}return i}return mt(e,u),e}(pt);pt.registerComponent("MediaLoader",I);C=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.handleMouseOver_=function(e){return i.handleMouseOver(e)},i.handleMouseOut_=function(e){return i.handleMouseOut(e)},i.handleClick_=function(e){return i.handleClick(e)},i.handleKeyDown_=function(e){return i.handleKeyDown(e)},i.emitTapEvents(),i.enable(),i}mt(e,n);var t=e.prototype;return t.createEl=function(e,t,i){void 0===e&&(e="div"),void 0===t&&(t={}),void 0===i&&(i={}),t=b({className:this.buildCSSClass(),tabIndex:0},t),"button"===e&&h.error("Creating a ClickableComponent with an HTML element of "+e+" is not supported; use a Button instead."),i=b({role:"button"},i),this.tabIndex_=t.tabIndex;i=$(e,t,i);return i.appendChild($("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),this.createControlTextEl(i),i},t.dispose=function(){this.controlTextEl_=null,n.prototype.dispose.call(this)},t.createControlTextEl=function(e){return this.controlTextEl_=$("span",{className:"vjs-control-text"},{"aria-live":"polite"}),e&&e.appendChild(this.controlTextEl_),this.controlText(this.controlText_,e),this.controlTextEl_},t.controlText=function(e,t){if(void 0===t&&(t=this.el()),void 0===e)return this.controlText_||"Need Text";var i=this.localize(e);this.controlText_=e,J(this.controlTextEl_,i),this.nonIconControl||this.player_.options_.noUITitleAttributes||t.setAttribute("title",i)},t.buildCSSClass=function(){return"vjs-control vjs-button "+n.prototype.buildCSSClass.call(this)},t.enable=function(){this.enabled_||(this.enabled_=!0,this.removeClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","false"),"undefined"!=typeof this.tabIndex_&&this.el_.setAttribute("tabIndex",this.tabIndex_),this.on(["tap","click"],this.handleClick_),this.on("keydown",this.handleKeyDown_))},t.disable=function(){this.enabled_=!1,this.addClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","true"),"undefined"!=typeof this.tabIndex_&&this.el_.removeAttribute("tabIndex"),this.off("mouseover",this.handleMouseOver_),this.off("mouseout",this.handleMouseOut_),this.off(["tap","click"],this.handleClick_),this.off("keydown",this.handleKeyDown_)},t.handleLanguagechange=function(){this.controlText(this.controlText_)},t.handleClick=function(e){this.options_.clickHandler&&this.options_.clickHandler.call(this,arguments)},t.handleKeyDown=function(e){ht.isEventKey(e,"Space")||ht.isEventKey(e,"Enter")?(e.preventDefault(),e.stopPropagation(),this.trigger("click")):n.prototype.handleKeyDown.call(this,e)},e}(pt);pt.registerComponent("ClickableComponent",C),pt.registerComponent("PosterImage",function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.update(),i.update_=function(e){return i.update(e)},e.on("posterchange",i.update_),i}mt(e,n);var t=e.prototype;return t.dispose=function(){this.player().off("posterchange",this.update_),n.prototype.dispose.call(this)},t.createEl=function(){return $("div",{className:"vjs-poster",tabIndex:-1})},t.update=function(e){var t=this.player().poster();this.setSrc(t),t?this.show():this.hide()},t.setSrc=function(e){this.el_.style.backgroundImage=e?'url("'+e+'")':""},t.handleClick=function(e){var t;this.player_.controls()&&(t=this.player_.usingPlugin("eme")&&this.player_.eme.sessions&&0<this.player_.eme.sessions.length,!this.player_.tech(!0)||(N||O)&&t||this.player_.tech(!0).focus(),this.player_.paused()?Et(this.player_.play()):this.player_.pause())},e}(C));var tn="#222",nn={monospace:"monospace",sansSerif:"sans-serif",serif:"serif",monospaceSansSerif:'"Andale Mono", "Lucida Console", monospace',monospaceSerif:'"Courier New", monospace',proportionalSansSerif:"sans-serif",proportionalSerif:"serif",casual:'"Comic Sans MS", Impact, fantasy',
4715script:'"Monotype Corsiva", cursive',smallcaps:'"Andale Mono", "Lucida Console", monospace, sans-serif'};function rn(e,t){var i;if(4===e.length)i=e[1]+e[1]+e[2]+e[2]+e[3]+e[3];else{if(7!==e.length)throw new Error("Invalid color code provided, "+e+"; must be formatted as e.g. #f0e or #f604e2.");i=e.slice(1)}return"rgba("+parseInt(i.slice(0,2),16)+","+parseInt(i.slice(2,4),16)+","+parseInt(i.slice(4,6),16)+","+t+")"}function an(e,t,i){try{e.style[t]=i}catch(e){return}}pt.registerComponent("TextTrackDisplay",function(a){function e(i,e,t){function n(e){return r.updateDisplay(e)}var r=a.call(this,i,e,t)||this;return i.on("loadstart",function(e){return r.toggleDisplay(e)}),i.on("texttrackchange",n),i.on("loadedmetadata",function(e){return r.preselectTrack(e)}),i.ready(Ve(ft(r),function(){if(i.tech_&&i.tech_.featuresNativeTextTracks)this.hide();else{i.on("fullscreenchange",n),i.on("playerresize",n),window.addEventListener("orientationchange",n),i.on("dispose",function(){return window.removeEventListener("orientationchange",n)});for(var e=this.options_.playerOptions.tracks||[],t=0;t<e.length;t++)this.player_.addRemoteTextTrack(e[t],!0);this.preselectTrack()}})),r}mt(e,a);var t=e.prototype;return t.preselectTrack=function(){for(var e,t,i,n={captions:1,subtitles:1},r=this.player_.textTracks(),a=this.player_.cache_.selectedLanguage,s=0;s<r.length;s++){var o=r[s];a&&a.enabled&&a.language&&a.language===o.language&&o.kind in n?i=o.kind!==a.kind&&i||o:a&&!a.enabled?t=e=i=null:o.default&&("descriptions"!==o.kind||e?o.kind in n&&!t&&(t=o):e=o)}i?i.mode="showing":t?t.mode="showing":e&&(e.mode="showing")},t.toggleDisplay=function(){this.player_.tech_&&this.player_.tech_.featuresNativeTextTracks?this.hide():this.show()},t.createEl=function(){return a.prototype.createEl.call(this,"div",{className:"vjs-text-track-display"},{translate:"yes","aria-live":"off","aria-atomic":"true"})},t.clearDisplay=function(){"function"==typeof window.WebVTT&&window.WebVTT.processCues(window,[],this.el_)},t.updateDisplay=function(){var e=this.player_.textTracks(),t=this.options_.allowMultipleShowingTracks;if(this.clearDisplay(),t){for(var i=[],n=0;n<e.length;++n){var r=e[n];"showing"===r.mode&&i.push(r)}this.updateForTrack(i)}else{for(var a=null,s=null,o=e.length;o--;){var u=e[o];"showing"===u.mode&&("descriptions"===u.kind?a=u:s=u)}s?("off"!==this.getAttribute("aria-live")&&this.setAttribute("aria-live","off"),this.updateForTrack(s)):a&&("assertive"!==this.getAttribute("aria-live")&&this.setAttribute("aria-live","assertive"),this.updateForTrack(a))}},t.updateDisplayState=function(e){for(var t=this.player_.textTrackSettings.getValues(),i=e.activeCues,n=i.length;n--;){var r,a=i[n];a&&(r=a.displayState,t.color&&(r.firstChild.style.color=t.color),t.textOpacity&&an(r.firstChild,"color",rn(t.color||"#fff",t.textOpacity)),t.backgroundColor&&(r.firstChild.style.backgroundColor=t.backgroundColor),t.backgroundOpacity&&an(r.firstChild,"backgroundColor",rn(t.backgroundColor||"#000",t.backgroundOpacity)),t.windowColor&&(t.windowOpacity?an(r,"backgroundColor",rn(t.windowColor,t.windowOpacity)):r.style.backgroundColor=t.windowColor),t.edgeStyle&&("dropshadow"===t.edgeStyle?r.firstChild.style.textShadow="2px 2px 3px #222, 2px 2px 4px #222, 2px 2px 5px "+tn:"raised"===t.edgeStyle?r.firstChild.style.textShadow="1px 1px #222, 2px 2px #222, 3px 3px "+tn:"depressed"===t.edgeStyle?r.firstChild.style.textShadow="1px 1px #ccc, 0 1px #ccc, -1px -1px #222, 0 -1px "+tn:"uniform"===t.edgeStyle&&(r.firstChild.style.textShadow="0 0 4px #222, 0 0 4px #222, 0 0 4px #222, 0 0 4px "+tn)),t.fontPercent&&1!==t.fontPercent&&(a=window.parseFloat(r.style.fontSize),r.style.fontSize=a*t.fontPercent+"px",r.style.height="auto",r.style.top="auto"),t.fontFamily&&"default"!==t.fontFamily&&("small-caps"===t.fontFamily?r.firstChild.style.fontVariant="small-caps":r.firstChild.style.fontFamily=nn[t.fontFamily]))}},t.updateForTrack=function(e){if(Array.isArray(e)||(e=[e]),"function"==typeof window.WebVTT&&!e.every(function(e){return!e.activeCues})){for(var t=[],i=0;i<e.length;++i)for(var n=e[i],r=0;r<n.activeCues.length;++r)t.push(n.activeCues[r]);window.WebVTT.processCues(window,t,this.el_);for(var a=0;a<e.length;++a){for(var s=e[a],o=0;o<s.activeCues.length;++o){var u=s.activeCues[o].displayState;te(u,"vjs-text-track-cue"),te(u,"vjs-text-track-cue-"+(s.language||a)),s.language&&oe(u,"lang",s.language)}this.player_.textTrackSettings&&this.updateDisplayState(s)}}},e}(pt)),pt.registerComponent("LoadingSpinner",function(i){function e(){return i.apply(this,arguments)||this}return mt(e,i),e.prototype.createEl=function(){var e=this.player_.isAudio(),t=this.localize(e?"Audio Player":"
4715Video Player"),e=$("span",{className:"vjs-control-text",textContent:this.localize("{1} is loading.",[t])}),t=i.prototype.createEl.call(this,"div",{className:"vjs-loading-spinner",dir:"ltr"});return t.appendChild(e),t},e}(pt));var sn=function(t){function e(){return t.apply(this,arguments)||this}mt(e,t);var i=e.prototype;return i.createEl=function(e,t,i){void 0===t&&(t={}),void 0===i&&(i={});i=$("button",t=b({className:this.buildCSSClass()},t),i=b({type:"button"},i));return i.appendChild($("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),this.createControlTextEl(i),i},i.addChild=function(e,t){void 0===t&&(t={});var i=this.constructor.name;return h.warn("Adding an actionable (user controllable) child to a Button ("+i+") is not supported; use a ClickableComponent instead."),pt.prototype.addChild.call(this,e,t)},i.enable=function(){t.prototype.enable.call(this),this.el_.removeAttribute("disabled")},i.disable=function(){t.prototype.disable.call(this),this.el_.setAttribute("disabled","disabled")},i.handleKeyDown=function(e){ht.isEventKey(e,"Space")||ht.isEventKey(e,"Enter")?e.stopPropagation():t.prototype.handleKeyDown.call(this,e)},e}(C);pt.registerComponent("Button",sn);Bt=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.mouseused_=!1,i.on("mousedown",function(e){return i.handleMouseDown(e)}),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-big-play-button"},t.handleClick=function(e){var t=this.player_.play();if(this.mouseused_&&e.clientX&&e.clientY){var i=this.player_.usingPlugin("eme")&&this.player_.eme.sessions&&0<this.player_.eme.sessions.length;return Et(t),void(!this.player_.tech(!0)||(N||O)&&i||this.player_.tech(!0).focus())}var i=this.player_.getChild("controlBar"),n=i&&i.getChild("playToggle");n?(i=function(){return n.focus()},wt(t)?t.then(i,function(){}):this.setTimeout(i,1)):this.player_.tech(!0).focus()},t.handleKeyDown=function(e){this.mouseused_=!1,n.prototype.handleKeyDown.call(this,e)},t.handleMouseDown=function(e){this.mouseused_=!0},e}(sn);Bt.prototype.controlText_="Play Video",pt.registerComponent("BigPlayButton",Bt),pt.registerComponent("CloseButton",function(i){function e(e,t){e=i.call(this,e,t)||this;return e.controlText(t&&t.controlText||e.localize("Close")),e}mt(e,i);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-close-button "+i.prototype.buildCSSClass.call(this)},t.handleClick=function(e){this.trigger({type:"close",bubbles:!1})},t.handleKeyDown=function(e){ht.isEventKey(e,"Esc")?(e.preventDefault(),e.stopPropagation(),this.trigger("click")):i.prototype.handleKeyDown.call(this,e)},e}(sn));Ft=function(n){function e(e,t){var i=n.call(this,e,t=void 0===t?{}:t)||this;return t.replay=void 0===t.replay||t.replay,i.on(e,"play",function(e){return i.handlePlay(e)}),i.on(e,"pause",function(e){return i.handlePause(e)}),t.replay&&i.on(e,"ended",function(e){return i.handleEnded(e)}),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-play-control "+n.prototype.buildCSSClass.call(this)},t.handleClick=function(e){this.player_.paused()?Et(this.player_.play()):this.player_.pause()},t.handleSeeked=function(e){this.removeClass("vjs-ended"),this.player_.paused()?this.handlePause(e):this.handlePlay(e)},t.handlePlay=function(e){this.removeClass("vjs-ended"),this.removeClass("vjs-paused"),this.addClass("vjs-playing"),this.controlText("Pause")},t.handlePause=function(e){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.controlText("Play")},t.handleEnded=function(e){var t=this;this.removeClass("vjs-playing"),this.addClass("vjs-ended"),this.controlText("Replay"),this.one(this.player_,"seeked",function(e){return t.handleSeeked(e)})},e}(sn);Ft.prototype.controlText_="Play",pt.registerComponent("PlayToggle",Ft);function on(e,t){e=e<0?0:e;var i=Math.floor(e%60),n=Math.floor(e/60%60),r=Math.floor(e/3600),a=Math.floor(t/60%60),t=Math.floor(t/3600);return(r=0<(r=isNaN(e)||e===1/0?n=i="-":r)||0<t?r+":":"")+(n=((r||10<=a)&&n<10?"0"+n:n)+":")+(i=i<10?"0"+i:i)}var un=on;function ln(e,t){return un(e,t=void 0===t?e:t)}k=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on(e,["timeupdate","ended"],function(e){return i.updateContent(e)}),i.updateTextNode_(),i}mt(e,n);var t=e.prototype;return t.createEl=function(){var e=this.buildCSSClass(),t=n.prototype.createEl.call(this,"div",{className:e+" vjs-time-control vjs-control"}),i=$("span",{className:"vjs-control-text",textContent:this.localize(this.labelText_)+" "},{role:"presentation"});return t.appendChild(i),this.contentEl_=$("span",{className:e+"-display"},{"aria-live":"off",role:"presentation"}),t.appendChild(this.contentEl_),t},t.dispose=function(){this.contentEl_=null,this.textNode_=null,n.prototype.dispose.call(this)},t.updateTextNode_=function(e){var t=this;e=ln(e=void 0===e?0:e),this.formattedTime_!==e&&(this.formattedTime_=e,this.requestNamedAnimationFrame("TimeDisplay#updateTextNode_",function(){var e;t.contentEl_&&((e=t.textNode_)&&t.contentEl_.firstChild!==e&&(e=null,h.warn("TimeDisplay#updateTextnode_: Prevented replacement of text node element since it was no longer a child of this node. Appending a new node instead.")),t.textNode_=document.createTextNode(t.formattedTime_),t.textNode_&&(e?t.contentEl_.replaceChild(t.textNode_,e):t.contentEl_.appendChild(t.textNode_)))}))},t.updateContent=function(e){},e}(pt);k.prototype.labelText_="Time",k.prototype.controlText_="Time",pt.registerComponent("TimeDisplay",k);jt=function(e){function t(){return e.apply(this,arguments)||this}mt(t,e);var i=t.prototype;return i.buildCSSClass=function(){return"vjs-current-time"},i.updateContent=function(e){var t=this.player_.ended()?this.player_.duration():this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime();this.updateTextNode_(t)},t}(k);jt.prototype.labelText_="Current Time",jt.prototype.controlText_="Current Time",pt.registerComponent("CurrentTimeDisplay",jt);j=function(n){function e(e,t){var i=n.call(this,e,t)||this,t=function(e){return i.updateContent(e)};return i.on(e,"durationchange",t),i.on(e,"loadstart",t),i.on(e,"loadedmetadata",t),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-duration"},t.updateContent=function(e){var t=this.player_.duration();this.updateTextNode_(t)},e}(k);j.prototype.labelText_="Duration",j.prototype.controlText_="Duration",pt.registerComponent("DurationDisplay",j),pt.registerComponent("TimeDivider",function(n){function e(){return n.apply(this,arguments)||this}return mt(e,n),e.prototype.createEl=function(){var e=n.prototype.createEl.call(this,"div",{className:"vjs-time-control vjs-time-divider"},{"aria-hidden":!0}),t=n.prototype.createEl.call(this,"div"),i=n.prototype.createEl.call(this,"span",{textContent:"/"});return t.appendChild(i),e.appendChild(t),e},e}(pt));f=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on(e,"durationchange",function(e){return i.updateContent(e)}),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-remaining-time"},t.createEl=function(){var e=n.prototype.createEl.call(this);return!1!==this.options_.displayNegative&&e.insertBefore($("span",{},{"aria-hidden":!0},"-"),this.contentEl_),e},t.updateContent=function(e){var t;"number"==typeof this.player_.duration()&&(t=this.player_.ended()?0:this.player_.remainingTimeDisplay?this.player_.remainingTimeDisplay():this.player_.remainingTime(),this.updateTextNode_(t))},e}(k);f.prototype.labelText_="Remaining Time",f.prototype.controlText_="Remaining Time",pt.registerComponent("RemainingTimeDisplay",f),pt.registerComponent("LiveDisplay",function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.updateShowing(),i.on(i.player(),"durationchange",function(e){return i.updateShowing(e)}),i}mt(e,n);var t=e.prototype;return t.createEl=function(){var e=n.prototype.createEl.call(this,"div",{className:"vjs-live-control vjs-control"});return this.contentEl_=$("div",{className:"vjs-live-display"},{"aria-live":"off"}),this.contentEl_.appendChild($("span",{className:"vjs-control-text",textContent:this.localize("Stream Type")+" "})),this.contentEl_.appendChild(document.createTextNode(this.localize("LIVE"))),e.appendChild(this.contentEl_),e},t.dispose=function(){this.contentEl_=null,n.prototype.dispose.call(this)},t.updateShowing=function(e){this.player().duration()===1/0?this.show():this.hide()},e}(pt));ui=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.updateLiveEdgeStatus(),i.player_.liveTracker&&(i.updateLiveEdgeStatusHandler_=function(e){return i.updateLiveEdgeStatus(e)},i.on(i.player_.liveTracker,"liveedgechange",i.updateLiveEdgeStatusHandler_)),i}mt(e,n);var t=e.prototype;return t.createEl=function(){var e=n.prototype.createEl.call(this,"button",{className:"vjs-seek-to-live-control vjs-control"});return this.textEl_=$("span",{className:"vjs-seek-to-live-text",textContent:this.localize("LIVE")},{"aria-hidden":"true"}),e.appendChild(this.textEl_),e},t.updateLiveEdgeStatus=function(){!this.player_.liveTracker||this.player_.liveTracker.atLiveEdge()?(this.setAttribute("aria-disabled",!0),this.addClass("vjs-at-live-edge"),this.controlText("Seek to live, currently playing live")):(this.setAttribute("aria-disabled",!1),this.removeClass("vjs-at-live-edge"),this.controlText("Seek to live, currently behind live"))},t.handleClick=function(){this.player_.liveTracker.seekToLiveEdge()},t.dispose=function(){this.player_.liveTracker&&this.off(this.player_.liveTracker,"liveedgechange",this.updateLiveEdgeStatusHandler_),this.textEl_=null,n.prototype.dispose.call(this)},e}(sn);ui.prototype.controlText_="Seek to live, currently playing live",pt.registerComponent("SeekToLive",ui);function cn(e,t,i){return e=Number(e),Math.min(i,Math.max(t,isNaN(e)?t:e))}li=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.handleMouseDown_=function(e){return i.handleMouseDown(e)},i.handleMouseUp_=function(e){return i.handleMouseUp(e)},i.handleKeyDown_=function(e){return i.handleKeyDown(e)},i.handleClick_=function(e){return i.handleClick(e)},i.handleMouseMove_=function(e){return i.handleMouseMove(e)},i.update_=function(e){return i.update(e)},i.bar=i.getChild(i.options_.barName),i.vertical(!!i.options_.vertical),i.enable(),i}mt(e,n);var t=e.prototype;return t.enabled=function(){return this.enabled_},t.enable=function(){this.enabled()||(this.on("mousedown",this.handleMouseDown_),this.on("touchstart",this.handleMouseDown_),this.on("keydown",this.handleKeyDown_),this.on("click",this.handleClick_),this.on(this.player_,"controlsvisible",this.update),this.playerEvent&&this.on(this.player_,this.playerEvent,this.update),this.removeClass("disabled"),this.setAttribute("tabindex",0),this.enabled_=!0)},t.disable=function(){var e;this.enabled()&&(e=this.bar.el_.ownerDocument,this.off("mousedown",this.handleMouseDown_),this.off("touchstart",this.handleMouseDown_),this.off("keydown",this.handleKeyDown_),this.off("click",this.handleClick_),this.off(this.player_,"controlsvisible",this.update_),this.off(e,"mousemove",this.handleMouseMove_),this.off(e,"mouseup",this.handleMouseUp_),this.off(e,"touchmove",this.handleMouseMove_),this.off(e,"touchend",this.handleMouseUp_),this.removeAttribute("tabindex"),this.addClass("disabled"),this.playerEvent&&this.off(this.player_,this.playerEvent,this.update),this.enabled_=!1)},t.createEl=function(e,t,i){return void 0===i&&(i={}),(t=void 0===t?{}:t).className=t.className+" vjs-slider",t=b({tabIndex:0},t),i=b({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},i),n.prototype.createEl.call(this,e,t,i)},t.handleMouseDown=function(e){var t=this.bar.el_.ownerDocument;"mousedown"===e.type&&e.preventDefault(),"touchstart"!==e.type||R||e.preventDefault(),le(),this.addClass("vjs-sliding"),this.trigger("slideractive"),this.on(t,"mousemove",this.handleMouseMove_),this.on(t,"mouseup",this.handleMouseUp_),this.on(t,"touchmove",this.handleMouseMove_),this.on(t,"touchend",this.handleMouseUp_),this.handleMouseMove(e,!0)},t.handleMouseMove=function(e){},t.handleMouseUp=function(){var e=this.bar.el_.ownerDocument;ce(),this.removeClass("vjs-sliding"),this.trigger("sliderinactive"),this.off(e,"mousemove",this.handleMouseMove_),this.off(e,"mouseup",this.handleMouseUp_),this.off(e,"touchmove",this.handleMouseMove_),this.off(e,"touchend",this.handleMouseUp_),this.update()},t.update=function(){var t=this;if(this.el_&&this.bar){var i=this.getProgress();return i===this.progress_?i:(this.progress_=i,this.requestNamedAnimationFrame("Slider#update",function(){var e=t.vertical()?"height":"width";t.bar.el().style[e]=(100*i).toFixed(2)+"%"}),i)}},t.getProgress=function(){return Number(cn(this.getPercent(),0,1).toFixed(4))},t.calculateDistance=function(e){e=pe(this.el_,e);return this.vertical()?e.y:e.x},t.handleKeyDown=function(e){ht.isEventKey(e,"Left")||ht.isEventKey(e,"Down")?(e.preventDefault(),e.stopPropagation(),this.stepBack()):ht.isEventKey(e,"Right")||ht.isEventKey(e,"Up")?(e.preventDefault(),e.stopPropagation(),this.stepForward()):n.prototype.handleKeyDown.call(this,e)},t.handleClick=function(e){e.stopPropagation(),e.preventDefault()},t.vertical=function(e){if(void 0===e)return this.vertical_||!1;this.vertical_=!!e,this.vertical_?this.addClass("vjs-slider-vertical"):this.addClass("vjs-slider-horizontal")},e}(pt);pt.registerComponent("Slider",li);
4715function dn(e,t){return cn(e/t*100,0,100).toFixed(2)+"%"}pt.registerComponent("LoadProgressBar",function(r){function e(e,t){var i=r.call(this,e,t)||this;return i.partEls_=[],i.on(e,"progress",function(e){return i.update(e)}),i}mt(e,r);var t=e.prototype;return t.createEl=function(){var e=r.prototype.createEl.call(this,"div",{className:"vjs-load-progress"}),t=$("span",{className:"vjs-control-text"}),i=$("span",{textContent:this.localize("Loaded")}),n=document.createTextNode(": ");return this.percentageEl_=$("span",{className:"vjs-control-text-loaded-percentage",textContent:"0%"}),e.appendChild(t),t.appendChild(i),t.appendChild(n),t.appendChild(this.percentageEl_),e},t.dispose=function(){this.partEls_=null,this.percentageEl_=null,r.prototype.dispose.call(this)},t.update=function(e){var l=this;this.requestNamedAnimationFrame("LoadProgressBar#update",function(){var e=l.player_.liveTracker,t=l.player_.buffered(),e=e&&e.isLive()?e.seekableEnd():l.player_.duration(),i=l.player_.bufferedEnd(),n=l.partEls_,e=dn(i,e);l.percent_!==e&&(l.el_.style.width=e,J(l.percentageEl_,e),l.percent_=e);for(var r=0;r<t.length;r++){var a=t.start(r),s=t.end(r),o=n[r];o||(o=l.el_.appendChild($()),n[r]=o),o.dataset.start===a&&o.dataset.end===s||(o.dataset.start=a,o.dataset.end=s,o.style.left=dn(a,i),o.style.width=dn(s-a,i))}for(var u=n.length;u>t.length;u--)l.el_.removeChild(n[u-1]);n.length=t.length})},e}(pt)),pt.registerComponent("TimeTooltip",function(i){function e(e,t){t=i.call(this,e,t)||this;return t.update=We(Ve(ft(t),t.update),30),t}mt(e,i);var t=e.prototype;return t.createEl=function(){return i.prototype.createEl.call(this,"div",{className:"vjs-time-tooltip"},{"aria-hidden":"true"})},t.update=function(e,t,i){var n=he(this.el_),r=de(this.player_.el()),a=e.width*t;r&&n&&(t=e.left-r.left+a,r=e.width-a+(r.right-e.right),t<(e=n.width/2)?e+=e-t:r<e&&(e=r),e<0?e=0:e>n.width&&(e=n.width),e=Math.round(e),this.el_.style.right="-"+e+"px",this.write(i))},t.write=function(e){J(this.el_,e)},t.updateTime=function(n,r,a,s){var o=this;this.requestNamedAnimationFrame("TimeTooltip#updateTime",function(){var e,t,i=o.player_.duration();i=o.player_.liveTracker&&o.player_.liveTracker.isLive()?((t=(e=o.player_.liveTracker.liveWindow())-r*e)<1?"":"-")+ln(t,e):ln(a,i),o.update(n,r,i),s&&s()})},e}(pt));Xt=function(i){function e(e,t){t=i.call(this,e,t)||this;return t.update=We(Ve(ft(t),t.update),30),t}mt(e,i);var t=e.prototype;return t.createEl=function(){return i.prototype.createEl.call(this,"div",{className:"vjs-play-progress vjs-slider-bar"},{"aria-hidden":"true"})},t.update=function(e,t){var i,n=this.getChild("timeTooltip");n&&(i=this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime(),n.updateTime(e,t,i))},e}(pt);Xt.prototype.options_={children:[]},q||A||Xt.prototype.options_.children.push("timeTooltip"),pt.registerComponent("PlayProgressBar",Xt);I=function(i){function e(e,t){t=i.call(this,e,t)||this;return t.update=We(Ve(ft(t),t.update),30),t}mt(e,i);var t=e.prototype;return t.createEl=function(){return i.prototype.createEl.call(this,"div",{className:"vjs-mouse-display"})},t.update=function(e,t){var i=this,n=t*this.player_.duration();this.getChild("timeTooltip").updateTime(e,t,n,function(){i.el_.style.left=e.width*t+"px"})},e}(pt);I.prototype.options_={children:["timeTooltip"]},pt.registerComponent("MouseTimeDisplay",I);Bt=function(a){function e(e,t){t=a.call(this,e,t)||this;return t.setEventHandlers_(),t}mt(e,a);var t=e.prototype;return t.setEventHandlers_=function(){var t=this;this.update_=Ve(this,this.update),this.update=We(this.update_,30),this.on(this.player_,["ended","durationchange","timeupdate"],this.update),this.player_.liveTracker&&this.on(this.player_.liveTracker,"liveedgechange",this.update),this.updateInterval=null,this.enableIntervalHandler_=function(e){return t.enableInterval_(e)},this.disableIntervalHandler_=function(e){return t.disableInterval_(e)},this.on(this.player_,["playing"],this.enableIntervalHandler_),this.on(this.player_,["ended","pause","waiting"],this.disableIntervalHandler_),"hidden"in document&&"visibilityState"in document&&this.on(document,"visibilitychange",this.toggleVisibility_)},t.toggleVisibility_=function(e){"hidden"===document.visibilityState?(this.cancelNamedAnimationFrame("SeekBar#update"),this.cancelNamedAnimationFrame("Slider#update"),this.disableInterval_(e)):(this.player_.ended()||this.player_.paused()||this.enableInterval_(),this.update())},t.enableInterval_=function(){this.updateInterval||(this.updateInterval=this.setInterval(this.update,30))},t.disableInterval_=function(e){this.player_.liveTracker&&this.player_.liveTracker.isLive()&&e&&"ended"!==e.type||this.updateInterval&&(this.clearInterval(this.updateInterval),this.updateInterval=null)},t.createEl=function(){return a.prototype.createEl.call(this,"div",{className:"vjs-progress-holder"},{"aria-label":this.localize("Progress Bar")})},t.update=function(e){var n=this;if("hidden"!==document.visibilityState){var r=a.prototype.update.call(this);return this.requestNamedAnimationFrame("SeekBar#update",function(){var e=n.player_.ended()?n.player_.duration():n.getCurrentTime_(),t=n.player_.liveTracker,i=n.player_.duration();
4715t&&t.isLive()&&(i=n.player_.liveTracker.liveCurrentTime()),n.percent_!==r&&(n.el_.setAttribute("aria-valuenow",(100*r).toFixed(2)),n.percent_=r),n.currentTime_===e&&n.duration_===i||(n.el_.setAttribute("aria-valuetext",n.localize("progress bar timing: currentTime={1} duration={2}",[ln(e,i),ln(i,i)],"{1} of {2}")),n.currentTime_=e,n.duration_=i),n.bar&&n.bar.update(de(n.el()),n.getProgress())}),r}},t.userSeek_=function(e){this.player_.liveTracker&&this.player_.liveTracker.isLive()&&this.player_.liveTracker.nextSeekedFromUser(),this.player_.currentTime(e)},t.getCurrentTime_=function(){return this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime()},t.getPercent=function(){var e,t=this.getCurrentTime_(),i=this.player_.liveTracker;return i&&i.isLive()?(e=(t-i.seekableStart())/i.liveWindow(),i.atLiveEdge()&&(e=1)):e=t/this.player_.duration(),e},t.handleMouseDown=function(e){_e(e)&&(e.stopPropagation(),this.videoWasPlaying=!this.player_.paused(),this.player_.pause(),a.prototype.handleMouseDown.call(this,e))},t.handleMouseMove=function(e,t){if(void 0===t&&(t=!1),_e(e)){t||this.player_.scrubbing()||this.player_.scrubbing(!0);var i=this.calculateDistance(e),n=this.player_.liveTracker;if(n&&n.isLive()){if(.99<=i)return void n.seekToLiveEdge();var r,t=n.seekableStart(),e=n.liveCurrentTime();if((r=(r=e<=(r=t+i*n.liveWindow())?e:r)<=t?t+.1:r)===1/0)return}else(r=i*this.player_.duration())===this.player_.duration()&&(r-=.1);this.userSeek_(r)}},t.enable=function(){a.prototype.enable.call(this);var e=this.getChild("mouseTimeDisplay");e&&e.show()},t.disable=function(){a.prototype.disable.call(this);var e=this.getChild("mouseTimeDisplay");e&&e.hide()},t.handleMouseUp=function(e){a.prototype.handleMouseUp.call(this,e),e&&e.stopPropagation(),this.player_.scrubbing(!1),this.player_.trigger({type:"timeupdate",target:this,manuallyTriggered:!0}),this.videoWasPlaying?Et(this.player_.play()):this.update_()},t.stepForward=function(){this.userSeek_(this.player_.currentTime()+5)},t.stepBack=function(){this.userSeek_(this.player_.currentTime()-5)},t.handleAction=function(e){this.player_.paused()?this.player_.play():this.player_.pause()},t.handleKeyDown=function(e){var t,i=this.player_.liveTracker;ht.isEventKey(e,"Space")||ht.isEventKey(e,"Enter")?(e.preventDefault(),e.stopPropagation(),this.handleAction(e)):ht.isEventKey(e,"Home")?(e.preventDefault(),e.stopPropagation(),this.userSeek_(0)):ht.isEventKey(e,"End")?(e.preventDefault(),e.stopPropagation(),i&&i.isLive()?this.userSeek_(i.liveCurrentTime()):this.userSeek_(this.player_.duration())):/^[0-9]$/.test(ht(e))?(e.preventDefault(),e.stopPropagation(),t=10*(ht.codes[ht(e)]-ht.codes[0])/100,i&&i.isLive()?this.userSeek_(i.seekableStart()+i.liveWindow()*t):this.userSeek_(this.player_.duration()*t)):ht.isEventKey(e,"PgDn")?(e.preventDefault(),e.stopPropagation(),this.userSeek_(this.player_.currentTime()-60)):ht.isEventKey(e,"PgUp")?(e.preventDefault(),e.stopPropagation(),this.userSeek_(this.player_.currentTime()+60)):a.prototype.handleKeyDown.call(this,e)}
4715,t.dispose=function(){this.disableInterval_(),this.off(this.player_,["ended","durationchange","timeupdate"],this.update),this.player_.liveTracker&&this.off(this.player_.liveTracker,"liveedgechange",this.update),this.off(this.player_,["playing"],this.enableIntervalHandler_),this.off(this.player_,["ended","pause","waiting"],this.disableIntervalHandler_),"hidden"in document&&"visibilityState"in document&&this.off(document,"visibilitychange",this.toggleVisibility_),a.prototype.dispose.call(this)},e}(li);Bt.prototype.options_={children:["loadProgressBar","playProgressBar"],barName:"playProgressBar"},q||A||Bt.prototype.options_.children.splice(1,0,"mouseTimeDisplay"),pt.registerComponent("SeekBar",Bt);Ft=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.handleMouseMove=We(Ve(ft(i),i.handleMouseMove),30),i.throttledHandleMouseSeek=We(Ve(ft(i),i.handleMouseSeek),30),i.handleMouseUpHandler_=function(e){return i.handleMouseUp(e)},i.handleMouseDownHandler_=function(e){return i.handleMouseDown(e)},i.enable(),i}mt(e,n);var t=e.prototype;return t.createEl=function(){return n.prototype.createEl.call(this,"div",{className:"vjs-progress-control vjs-control"})},t.handleMouseMove=function(e){var t,i,n,r,a=this.getChild("seekBar");a&&(t=a.getChild("playProgressBar"),i=a.getChild("mouseTimeDisplay"),(t||i)&&(r=he(n=a.el()),e=pe(n,e).x,e=cn(e,0,1),i&&i.update(r,e),t&&t.update(r,a.getProgress())))},t.handleMouseSeek=function(e){var t=this.getChild("seekBar");t&&t.handleMouseMove(e)},t.enabled=function(){return this.enabled_},t.disable=function(){var e;
4715this.children().forEach(function(e){return e.disable&&e.disable()}),this.enabled()&&(this.off(["mousedown","touchstart"],this.handleMouseDownHandler_),this.off(this.el_,"mousemove",this.handleMouseMove),this.removeListenersAddedOnMousedownAndTouchstart(),this.addClass("disabled"),this.enabled_=!1,this.player_.scrubbing()&&(e=this.getChild("seekBar"),this.player_.scrubbing(!1),e.videoWasPlaying&&Et(this.player_.play())))},t.enable=function(){this.children().forEach(function(e){return e.enable&&e.enable()}),this.enabled()||(this.on(["mousedown","touchstart"],this.handleMouseDownHandler_),this.on(this.el_,"mousemove",this.handleMouseMove),this.removeClass("disabled"),this.enabled_=!0)},t.removeListenersAddedOnMousedownAndTouchstart=function(){var e=this.el_.ownerDocument;this.off(e,"mousemove",this.throttledHandleMouseSeek),this.off(e,"touchmove",this.throttledHandleMouseSeek),this.off(e,"mouseup",this.handleMouseUpHandler_),this.off(e,"touchend",this.handleMouseUpHandler_)},t.handleMouseDown=function(e){var t=this.el_.ownerDocument,i=this.getChild("seekBar");i&&i.handleMouseDown(e),this.on(t,"mousemove",this.throttledHandleMouseSeek),this.on(t,"touchmove",this.throttledHandleMouseSeek),this.on(t,"mouseup",this.handleMouseUpHandler_),this.on(t,"touchend",this.handleMouseUpHandler_)},t.handleMouseUp=function(e){var t=this.getChild("seekBar");t&&t.handleMouseUp(e),this.removeListenersAddedOnMousedownAndTouchstart()},e}(pt);Ft.prototype.options_={children:["seekBar"]},pt.registerComponent("ProgressControl",Ft);jt=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on(e,["enterpictureinpicture","leavepictureinpicture"],function(e){return i.handlePictureInPictureChange(e)}),i.on(e,["disablepictureinpicturechanged","loadedmetadata"],function(e){return i.handlePictureInPictureEnabledChange(e)}),i.disable(),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-picture-in-picture-control "+n.prototype.buildCSSClass.call(this)},t.handlePictureInPictureEnabledChange=function(){document.pictureInPictureEnabled&&!1===this.player_.disablePictureInPicture()?this.enable():this.disable()},t.handlePictureInPictureChange=function(e){this.player_.isInPictureInPicture()?this.controlText("Exit Picture-in-Picture"):this.controlText("Picture-in-Picture"),this.handlePictureInPictureEnabledChange()},t.handleClick=function(e){this.player_.isInPictureInPicture()?this.player_.exitPictureInPicture():this.player_.requestPictureInPicture()},e}(sn);jt.prototype.controlText_="Picture-in-Picture",pt.registerComponent("PictureInPictureToggle",jt);j=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on(e,"fullscreenchange",function(e){return i.handleFullscreenChange(e)}),!1===document[e.fsApi_.fullscreenEnabled]&&i.disable(),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-fullscreen-control "+n.prototype.buildCSSClass.call(this)},t.handleFullscreenChange=function(e){this.player_.isFullscreen()?this.controlText("Non-Fullscreen"):this.controlText("Fullscreen")},t.handleClick=function(e){this.player_.isFullscreen()?this.player_.exitFullscreen():this.player_.requestFullscreen()},e}(sn);j.prototype.controlText_="Fullscreen",pt.registerComponent("FullscreenToggle",j);pt.registerComponent("VolumeLevel",function(t){function e(){return t.apply(this,arguments)||this}return mt(e,t),e.prototype.createEl=function(){var e=t.prototype.createEl.call(this,"div",{className:"vjs-volume-level"});return e.appendChild(t.prototype.createEl.call(this,"span",{className:"vjs-control-text"})),e},e}(pt)),pt.registerComponent("VolumeLevelTooltip",function(i){function e(e,t){t=i.call(this,e,t)||this;return t.update=We(Ve(ft(t),t.update),30),t}mt(e,i);var t=e.prototype;return t.createEl=function(){return i.prototype.createEl.call(this,"div",{className:"vjs-volume-tooltip"},{"aria-hidden":"true"})},t.update=function(e,t,i,n){if(!i){var r=de(this.el_),a=de(this.player_.el()),i=e.width*t;if(!a||!r)return;t=e.left-a.left+i,a=e.width-i+(a.right-e.right),e=r.width/2;t<e?e+=e-t:a<e&&(e=a),e<0?e=0:e>r.width&&(e=r.width),this.el_.style.right="-"+e+"px"}this.write(n+"%")},t.write=function(e){J(this.el_,e)},t.updateVolume=function(e,t,i,n,r){var a=this;this.requestNamedAnimationFrame("VolumeLevelTooltip#updateVolume",function(){a.update(e,t,i,n.toFixed(0)),r&&r()})},e}(pt));k=function(i){function e(e,t){t=i.call(this,e,t)||this;return t.update=We(Ve(ft(t),t.update),30),t}
4715mt(e,i);var t=e.prototype;return t.createEl=function(){return i.prototype.createEl.call(this,"div",{className:"vjs-mouse-display"})},t.update=function(e,t,i){var n=this,r=100*t;this.getChild("volumeLevelTooltip").updateVolume(e,t,i,r,function(){i?n.el_.style.bottom=e.height*t+"px":n.el_.style.left=e.width*t+"px"})},e}(pt);k.prototype.options_={children:["volumeLevelTooltip"]},pt.registerComponent("MouseVolumeLevelDisplay",k);f=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on("slideractive",function(e){return i.updateLastVolume_(e)}),i.on(e,"volumechange",function(e){return i.updateARIAAttributes(e)}),e.ready(function(){return i.updateARIAAttributes()}),i}mt(e,n);var t=e.prototype;return t.createEl=function(){return n.prototype.createEl.call(this,"div",{className:"vjs-volume-bar vjs-slider-bar"},{"aria-label":this.localize("Volume Level"),"aria-live":"polite"})},t.handleMouseDown=function(e){_e(e)&&n.prototype.handleMouseDown.call(this,e)},t.handleMouseMove=function(e){var t,i,n,r=this.getChild("mouseVolumeLevelDisplay");r&&(t=de(n=this.el()),i=this.vertical(),n=pe(n,e),n=i?n.y:n.x,n=cn(n,0,1),r.update(t,n,i)),_e(e)&&(this.checkMuted(),this.player_.volume(this.calculateDistance(e)))},t.checkMuted=function(){this.player_.muted()&&this.player_.muted(!1)},t.getPercent=function(){return this.player_.muted()?0:this.player_.volume()},t.stepForward=function(){this.checkMuted(),this.player_.volume(this.player_.volume()+.1)},t.stepBack=function(){this.checkMuted(),this.player_.volume(this.player_.volume()-.1)},t.updateARIAAttributes=function(e){var t=this.player_.muted()?0:this.volumeAsPercentage_();this.el_.setAttribute("aria-valuenow",t),this.el_.setAttribute("aria-valuetext",t+"%")},t.volumeAsPercentage_=function(){return Math.round(100*this.player_.volume())},t.updateLastVolume_=function(){var e=this,t=this.player_.volume();this.one("sliderinactive",function(){0===e.player_.volume()&&e.player_.lastVolume_(t)})},e}(li);f.prototype.options_={children:["volumeLevel"],barName:"volumeLevel"},q||A||f.prototype.options_.children.splice(0,0,"mouseVolumeLevelDisplay"),f.prototype.playerEvent="volumechange",pt.registerComponent("VolumeBar",f);ui=function(a){function e(e,t){var i,n,r;return(t=void 0===t?{}:t).vertical=t.vertical||!1,"undefined"!=typeof t.volumeBar&&!S(t.volumeBar)||(t.volumeBar=t.volumeBar||{},t.volumeBar.vertical=t.vertical),i=a.call(this,e,t)||this,n=ft(i),(r=e).tech_&&!r.tech_.featuresVolumeControl&&n.addClass("vjs-hidden"),n.on(r,"loadstart",function(){r.tech_.featuresVolumeControl?n.removeClass("vjs-hidden"):n.addClass("vjs-hidden")}),i.throttledHandleMouseMove=We(Ve(ft(i),i.handleMouseMove),30),i.handleMouseUpHandler_=function(e){return i.handleMouseUp(e)},i.on("mousedown",function(e){return i.handleMouseDown(e)}),i.on("touchstart",function(e){return i.handleMouseDown(e)}),i.on("mousemove",function(e){return i.handleMouseMove(e)}),i.on(i.volumeBar,["focus","slideractive"],function(){i.volumeBar.addClass("vjs-slider-active"),i.addClass("vjs-slider-active"),i.trigger("slideractive")}),i.on(i.volumeBar,["blur","sliderinactive"],function(){i.volumeBar.removeClass("vjs-slider-active"),i.removeClass("vjs-slider-active"),i.trigger("sliderinactive")}),i}mt(e,a);var t=e.prototype;return t.createEl=function(){var e="vjs-volume-horizontal";return this.options_.vertical&&(e="vjs-volume-vertical"),a.prototype.createEl.call(this,"div",{className:"vjs-volume-control vjs-control "+e})},t.handleMouseDown=function(e){var t=this.el_.ownerDocument;this.on(t,"mousemove",this.throttledHandleMouseMove),this.on(t,"touchmove",this.throttledHandleMouseMove),this.on(t,"mouseup",this.handleMouseUpHandler_),this.on(t,"touchend",this.handleMouseUpHandler_)},t.handleMouseUp=function(e){var t=this.el_.ownerDocument;this.off(t,"mousemove",this.throttledHandleMouseMove),this.off(t,"touchmove",this.throttledHandleMouseMove),this.off(t,"mouseup",this.handleMouseUpHandler_),this.off(t,"touchend",this.handleMouseUpHandler_)},t.handleMouseMove=function(e){this.volumeBar.handleMouseMove(e)},e}(pt);ui.prototype.options_={children:["volumeBar"]}
4715,pt.registerComponent("VolumeControl",ui);Xt=function(a){function e(e,t){var i,n,r=a.call(this,e,t)||this;return i=ft(r),(n=e).tech_&&!n.tech_.featuresMuteControl&&i.addClass("vjs-hidden"),i.on(n,"loadstart",function(){n.tech_.featuresMuteControl?i.removeClass("vjs-hidden"):i.addClass("vjs-hidden")}),r.on(e,["loadstart","volumechange"],function(e){return r.update(e)}),r}mt(e,a);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-mute-control "+a.prototype.buildCSSClass.call(this)},t.handleClick=function(e){var t=this.player_.volume(),i=this.player_.lastVolume_();0===t?(this.player_.volume(i<.1?.1:i),this.player_.muted(!1)):this.player_.muted(!this.player_.muted())},t.update=function(e){this.updateIcon_(),this.updateControlText_()},t.updateIcon_=function(){var e=this.player_.volume(),t=3;q&&this.player_.tech_&&this.player_.tech_.el_&&this.player_.muted(this.player_.tech_.el_.muted),0===e||this.player_.muted()?t=0:e<.33?t=1:e<.67&&(t=2);for(var i=0;i<4;i++)ie(this.el_,"vjs-vol-"+i);te(this.el_,"vjs-vol-"+t)},t.updateControlText_=function(){var e=this.player_.muted()||0===this.player_.volume()?"Unmute":"Mute";this.controlText()!==e&&this.controlText(e)},e}(sn);Xt.prototype.controlText_="Mute",pt.registerComponent("MuteToggle",Xt);I=function(n){function e(e,t){var i;return"undefined"!=typeof(t=void 0===t?{}:t).inline?t.inline=t.inline:t.inline=!0,"undefined"!=typeof t.volumeControl&&!S(t.volumeControl)||(t.volumeControl=t.volumeControl||{},t.volumeControl.vertical=!t.inline),(i=n.call(this,e,t)||this).handleKeyPressHandler_=function(e){return i.handleKeyPress(e)},i.on(e,["loadstart"],function(e){return i.volumePanelState_(e)}),i.on(i.muteToggle,"keyup",function(e){return i.handleKeyPress(e)}),i.on(i.volumeControl,"keyup",function(e){return i.handleVolumeControlKeyUp(e)}),i.on("keydown",function(e){return i.handleKeyPress(e)}),i.on("mouseover",function(e){return i.handleMouseOver(e)}),i.on("mouseout",function(e){return i.handleMouseOut(e)}),i.on(i.volumeControl,["slideractive"],i.sliderActive_),i.on(i.volumeControl,["sliderinactive"],i.sliderInactive_),i}mt(e,n);var t=e.prototype;return t.sliderActive_=function(){this.addClass("vjs-slider-active")},t.sliderInactive_=function(){this.removeClass("vjs-slider-active")},t.volumePanelState_=function(){this.volumeControl.hasClass("vjs-hidden")&&this.muteToggle.hasClass("vjs-hidden")&&this.addClass("vjs-hidden"),this.volumeControl.hasClass("vjs-hidden")&&!this.muteToggle.hasClass("vjs-hidden")&&this.addClass("vjs-mute-toggle-only")},t.createEl=function(){var e="vjs-volume-panel-horizontal";return this.options_.inline||(e="vjs-volume-panel-vertical"),n.prototype.createEl.call(this,"div",{className:"vjs-volume-panel vjs-control "+e})},t.dispose=function(){this.handleMouseOut(),n.prototype.dispose.call(this)},t.handleVolumeControlKeyUp=function(e){ht.isEventKey(e,"Esc")&&this.muteToggle.focus()},t.handleMouseOver=function(e){this.addClass("vjs-hover"),Be(document,"keyup",this.handleKeyPressHandler_)},t.handleMouseOut=function(e){this.removeClass("vjs-hover"),Fe(document,"keyup",this.handleKeyPressHandler_)},t.handleKeyPress=function(e){ht.isEventKey(e,"Esc")&&this.handleMouseOut()},e}(pt);I.prototype.options_={children:["muteToggle","volumeControl"]},pt.registerComponent("VolumePanel",I);var hn=function(n){function e(e,t){var i=n.call(this,e,t)||this;return t&&(i.menuButton_=t.menuButton),i.focusedChild_=-1,i.on("keydown",function(e){return i.handleKeyDown(e)}),i.boundHandleBlur_=function(e){return i.handleBlur(e)},i.boundHandleTapClick_=function(e){return i.handleTapClick(e)},i}mt(e,n);var t=e.prototype;return t.addEventListenerForItem=function(e){e instanceof pt&&(this.on(e,"blur",this.boundHandleBlur_),this.on(e,["tap","click"],this.boundHandleTapClick_))},t.removeEventListenerForItem=function(e){e instanceof pt&&(this.off(e,"blur",this.boundHandleBlur_),this.off(e,["tap","click"],this.boundHandleTapClick_))},t.removeChild=function(e){"string"==typeof e&&(e=this.getChild(e)),this.removeEventListenerForItem(e),n.prototype.removeChild.call(this,e)},t.addItem=function(e){e=this.addChild(e);e&&this.addEventListenerForItem(e)},t.createEl=function(){var e=this.options_.contentElType||"ul";this.contentEl_=$(e,{className:"vjs-menu-content"}),this.contentEl_.setAttribute("role","menu");e=n.prototype.createEl.call(this,"div",{append:this.contentEl_,className:"vjs-menu"});return e.appendChild(this.contentEl_),Be(e,"click",function(e){e.preventDefault(),e.stopImmediatePropagation()}),e},t.dispose=function(){this.contentEl_=null,this.boundHandleBlur_=null,this.boundHandleTapClick_=null,n.prototype.dispose.call(this)},t.handleBlur=function(e){var t=e.relatedTarget||document.activeElement;this.children().some(function(e){return e.el()===t})||(e=this.menuButton_)&&e.buttonPressed_&&t!==e.el().firstChild&&e.unpressButton()},t.handleTapClick=function(t){var e;this.menuButton_&&(this.menuButton_.unpressButton(),e=this.children(),!Array.isArray(e)||(e=e.filter(function(e){return e.el()===t.target})[0])&&"CaptionSettingsMenuItem"!==e.name()&&this.menuButton_.focus())},t.handleKeyDown=function(e){ht.isEventKey(e,"Left")||ht.isEventKey(e,"Down")?(e.preventDefault(),e.stopPropagation(),this.stepForward()):(ht.isEventKey(e,"Right")||ht.isEventKey(e,"Up"))&&(e.preventDefault(),e.stopPropagation(),this.stepBack())},t.stepForward=function(){var e=0;void 0!==this.focusedChild_&&(e=this.focusedChild_+1),this.focus(e)},t.stepBack=function(){var e=0;void 0!==this.focusedChild_&&(e=this.focusedChild_-1),this.focus(e)},t.focus=function(e){void 0===e&&(e=0);var t=this.children().slice();t.length&&t[0].hasClass("vjs-menu-title")&&t.shift(),0<t.length&&(e<0?e=0:e>=t.length&&(e=t.length-1),t[this.focusedChild_=e].el_.focus())},e}(pt);pt.registerComponent("Menu",hn);Bt=function(n){function e(e,t){var i;(i=n.call(this,e,t=void 0===t?{}:t)||this).menuButton_=new sn(e,t),i.menuButton_.controlText(i.controlText_),i.menuButton_.el_.setAttribute("aria-haspopup","true");t=sn.prototype.buildCSSClass();i.menuButton_.el_.className=i.buildCSSClass()+" "+t,i.menuButton_.removeClass("vjs-control"),i.addChild(i.menuButton_),i.update(),i.enabled_=!0;t=function(e){return i.handleClick(e)};return i.handleMenuKeyUp_=function(e){return i.handleMenuKeyUp(e)},i.on(i.menuButton_,"tap",t),i.on(i.menuButton_,"click",t),i.on(i.menuButton_,"keydown",function(e){return i.handleKeyDown(e)}),i.on(i.menuButton_,"mouseenter",function(){i.addClass("vjs-hover"),i.menu.show(),Be(document,"keyup",i.handleMenuKeyUp_)}
4715),i.on("mouseleave",function(e){return i.handleMouseLeave(e)}),i.on("keydown",function(e){return i.handleSubmenuKeyDown(e)}),i}mt(e,n);var t=e.prototype;return t.update=function(){var e=this.createMenu();this.menu&&(this.menu.dispose(),this.removeChild(this.menu)),this.menu=e,this.addChild(e),this.buttonPressed_=!1,this.menuButton_.el_.setAttribute("aria-expanded","false"),this.items&&this.items.length<=this.hideThreshold_?this.hide():this.show()},t.createMenu=function(){var e,t=new hn(this.player_,{menuButton:this});if(this.hideThreshold_=0,this.options_.title&&(e=$("li",{className:"vjs-menu-title",textContent:ut(this.options_.title),tabIndex:-1}),e=new pt(this.player_,{el:e}),t.addItem(e)),this.items=this.createItems(),this.items)for(var i=0;i<this.items.length;i++)t.addItem(this.items[i]);return t},t.createItems=function(){},t.createEl=function(){return n.prototype.createEl.call(this,"div",{className:this.buildWrapperCSSClass()},{})},t.buildWrapperCSSClass=function(){var e="vjs-menu-button";return!0===this.options_.inline?e+="-inline":e+="-popup","vjs-menu-button "+e+" "+sn.prototype.buildCSSClass()+" "+n.prototype.buildCSSClass.call(this)},t.buildCSSClass=function(){var e="vjs-menu-button";return!0===this.options_.inline?e+="-inline":e+="-popup","vjs-menu-button "+e+" "+n.prototype.buildCSSClass.call(this)},t.controlText=function(e,t){return void 0===t&&(t=this.menuButton_.el()),this.menuButton_.controlText(e,t)},t.dispose=function(){this.handleMouseLeave(),n.prototype.dispose.call(this)},t.handleClick=function(e){this.buttonPressed_?this.unpressButton():this.pressButton()},t.handleMouseLeave=function(e){this.removeClass("vjs-hover"),Fe(document,"keyup",this.handleMenuKeyUp_)},t.focus=function(){this.menuButton_.focus()},t.blur=function(){this.menuButton_.blur()},t.handleKeyDown=function(e){ht.isEventKey(e,"Esc")||ht.isEventKey(e,"Tab")?(this.buttonPressed_&&this.unpressButton(),ht.isEventKey(e,"Tab")||(e.preventDefault(),this.menuButton_.focus())):(ht.isEventKey(e,"Up")||ht.isEventKey(e,"Down"))&&(this.buttonPressed_||(e.preventDefault(),this.pressButton()))},t.handleMenuKeyUp=function(e){(ht.isEventKey(e,"Esc")||ht.isEventKey(e,"Tab"))&&this.removeClass("vjs-hover")},t.handleSubmenuKeyPress=function(e){this.handleSubmenuKeyDown(e)},t.handleSubmenuKeyDown=function(e){(ht.isEventKey(e,"Esc")||ht.isEventKey(e,"Tab"))&&(this.buttonPressed_&&this.unpressButton(),ht.isEventKey(e,"Tab")||(e.preventDefault(),this.menuButton_.focus()))},t.pressButton=function(){this.enabled_&&(this.buttonPressed_=!0,this.menu.show(),this.menu.lockShowing(),this.menuButton_.el_.setAttribute("aria-expanded","true"),q&&Y()||this.menu.focus())},t.unpressButton=function(){this.enabled_&&(this.buttonPressed_=!1,this.menu.unlockShowing(),this.menu.hide(),this.menuButton_.el_.setAttribute("aria-expanded","false"))},t.disable=function(){this.unpressButton(),this.enabled_=!1,this.addClass("vjs-disabled"),this.menuButton_.disable()},t.enable=function(){this.enabled_=!0,this.removeClass("vjs-disabled"),this.menuButton_.enable()},e}(pt);pt.registerComponent("MenuButton",Bt);Ft=function(r){function e(e,t){var i=t.tracks,t=r.call(this,e,t)||this;if(t.items.length<=1&&t.hide(),!i)return ft(t);var n=Ve(ft(t),t.update);return i.addEventListener("removetrack",n),i.addEventListener("addtrack",n),i.addEventListener("labelchange",n),t.player_.on("ready",n),t.player_.on("dispose",function(){i.removeEventListener("removetrack",n),i.removeEventListener("addtrack",n),i.removeEventListener("labelchange",n)}),t}return mt(e,r),e}(Bt);pt.registerComponent("TrackButton",Ft);var pn=["Tab","Esc","Up","Down","Right","Left"],jt=function(n){function e(e,t){e=n.call(this,e,t)||this;return e.selectable=t.selectable,e.isSelected_=t.selected||!1,e.multiSelectable=t.multiSelectable,e.selected(e.isSelected_),e.selectable?e.multiSelectable?e.el_.setAttribute("role","menuitemcheckbox"):e.el_.setAttribute("role","menuitemradio"):e.el_.setAttribute("role","menuitem"),e}mt(e,n);var t=e.prototype;return t.createEl=function(e,t,i){this.nonIconControl=!0;i=n.prototype.createEl.call(this,"li",b({className:"vjs-menu-item",tabIndex:-1},t),i);return i.replaceChild($("span",{className:"vjs-menu-item-text",textContent:this.localize(this.options_.label)}),i.querySelector(".vjs-icon-placeholder")),i},t.handleKeyDown=function(t){pn.some(function(e){return ht.isEventKey(t,e)})||n.prototype.handleKeyDown.call(this,t)},t.handleClick=function(e){this.selected(!0)},t.selected=function(e){this.selectable&&(e?(this.addClass("vjs-selected"),this.el_.setAttribute("aria-checked","true"),this.controlText(", selected"),this.isSelected_=!0):(this.removeClass("vjs-selected"),this.el_.setAttribute("aria-checked","fal
4715se"),this.controlText(""),this.isSelected_=!1))},e}(C);pt.registerComponent("MenuItem",jt);var fn=function(u){function e(e,t){var n,i=t.track,r=e.textTracks();t.label=i.label||i.language||"Unknown",t.selected="showing"===i.mode,(n=u.call(this,e,t)||this).track=i,n.kinds=(t.kinds||[t.kind||n.track.kind]).filter(Boolean);function a(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];n.handleTracksChange.apply(ft(n),t)}function s(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];n.handleSelectedLanguageChange.apply(ft(n),t)}var o;return e.on(["loadstart","texttrackchange"],a),r.addEventListener("change",a),r.addEventListener("selectedlanguagechange",s),n.on("dispose",function(){e.off(["loadstart","texttrackchange"],a),r.removeEventListener("change",a),r.removeEventListener("selectedlanguagechange",s)}),void 0===r.onchange&&n.on(["tap","click"],function(){if("object"!=typeof window.Event)try{o=new window.Event("change")}catch(e){}o||(o=document.createEvent("Event")).initEvent("change",!0,!0),r.dispatchEvent(o)}),n.handleTracksChange(),n}mt(e,u);var t=e.prototype;return t.handleClick=function(e){var t=this.track,i=this.player_.textTracks();if(u.prototype.handleClick.call(this,e),i)for(var n=0;n<i.length;n++){var r=i[n];-1!==this.kinds.indexOf(r.kind)&&(r===t?"showing"!==r.mode&&(r.mode="showing"):"disabled"!==r.mode&&(r.mode="disabled"))}},t.handleTracksChange=function(e){var t="showing"===this.track.mode;t!==this.isSelected_&&this.selected(t)},t.handleSelectedLanguageChange=function(e){var t;"showing"===this.track.mode&&((t=this.player_.cache_.selectedLanguage)&&t.enabled&&t.language===this.track.language&&t.kind!==this.track.kind||(this.player_.cache_.selectedLanguage={enabled:!0,language:this.track.language,kind:this.track.kind}))},t.dispose=function(){this.track=null,u.prototype.dispose.call(this)},e}(jt);pt.registerComponent("TextTrackMenuItem",fn);var mn=function(i){function e(e,t){return t.track={player:e,kind:t.kind,kinds:t.kinds,default:!1,mode:"disabled"},t.kinds||(t.kinds=[t.kind]),t.label?t.track.label=t.label:t.track.label=t.kinds.join(" and ")+" off",t.selectable=!0,t.multiSelectable=!1,i.call(this,e,t)||this}mt(e,i);var t=e.prototype;return t.handleTracksChange=function(e){for(var t=this.player().textTracks(),i=!0,n=0,r=t.length;n<r;n++){var a=t[n];if(-1<this.options_.kinds.indexOf(a.kind)&&"showing"===a.mode){i=!1;break}}i!==this.isSelected_&&this.selected(i)},t.handleSelectedLanguageChange=function(e){for(var t=this.player().textTracks(),i=!0,n=0,r=t.length;n<r;n++){var a=t[n];if(-1<["captions","descriptions","subtitles"].indexOf(a.kind)&&"showing"===a.mode){i=!1;break}}i&&(this.player_.cache_.selectedLanguage={enabled:!1})},e}(fn);pt.registerComponent("OffTextTrackMenuItem",mn);j=function(i){function e(e,t){return(t=void 0===t?{}:t).tracks=e.textTracks(),i.call(this,e,t)||this}return mt(e,i),e.prototype.createItems=function(e,t){var i;void 0===t&&(t=fn),this.label_&&(i=this.label_+" off"),(e=void 0===e?[]:e).push(new mn(this.player_,{kinds:this.kinds_,kind:this.kind_,label:i})),this.hideThreshold_+=1;var n=this.player_.textTracks();Array.isArray(this.kinds_)||(this.kinds_=[this.kind_]);for(var r=0;r<n.length;r++){var a,s=n[r];-1<this.kinds_.indexOf(s.kind)&&((a=new t(this.player_,{track:s,kinds:this.kinds_,kind:this.kind_,selectable:!0,multiSelectable:!1})).addClass("vjs-"+s.kind+"-menu-item"),e.push(a))}return e},e}(Ft);pt.registerComponent("TextTrackButton",j);var gn=function(a){function e(e,t){var i=t.track,n=t.cue,r=e.currentTime();return t.selectable=!0,t.multiSelectable=!1,t.label=n.text,t.selected=n.startTime<=r&&r<n.endTime,(t=a.call(this,e,t)||this).track=i,t.cue=n,i.addEventListener("cuechange",Ve(ft(t),t.update)),t}mt(e,a);var t=e.prototype;return t.handleClick=function(e){a.prototype.handleClick.call(this),this.player_.currentTime(this.cue.startTime),this.update(this.cue.startTime)},t.update=function(e){var t=this.cue,i=this.player_.currentTime();this.selected(t.startTime<=i&&i<t.endTime)},e}(jt);pt.registerComponent("ChaptersTrackMenuItem",gn);k=function(n){function e(e,t,i){return n.call(this,e,t,i)||this}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-chapters-button "+n.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-chapters-button "+n.prototype.buildWrapperCSSClass.call(this)},t.update=function(e){this.track_&&(!e||"addtrack"!==e.type&&"removetrack"!==e.type)||this.setTrack(this.findChapter
4715sTrack()),n.prototype.update.call(this)},t.setTrack=function(e){var t;this.track_!==e&&(this.updateHandler_||(this.updateHandler_=this.update.bind(this)),this.track_&&((t=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_))&&t.removeEventListener("load",this.updateHandler_),this.track_=null),this.track_=e,this.track_&&(this.track_.mode="hidden",(e=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_))&&e.addEventListener("load",this.updateHandler_)))},t.findChaptersTrack=function(){for(var e=this.player_.textTracks()||[],t=e.length-1;0<=t;t--){var i=e[t];if(i.kind===this.kind_)return i}},t.getMenuCaption=function(){return this.track_&&this.track_.label?this.track_.label:this.localize(ut(this.kind_))},t.createMenu=function(){return this.options_.title=this.getMenuCaption(),n.prototype.createMenu.call(this)},t.createItems=function(){var e=[];if(!this.track_)return e;var t=this.track_.cues;if(!t)return e;for(var i=0,n=t.length;i<n;i++){var r=t[i],r=new gn(this.player_,{track:this.track_,cue:r});e.push(r)}return e},e}(j);k.prototype.kind_="chapters",k.prototype.controlText_="Chapters",pt.registerComponent("ChaptersButton",k);li=function(a){function e(e,t,i){var i=a.call(this,e,t,i)||this,n=e.textTracks(),r=Ve(ft(i),i.handleTracksChange);return n.addEventListener("change",r),i.on("dispose",function(){n.removeEventListener("change",r)}),i}mt(e,a);var t=e.prototype;return t.handleTracksChange=function(e){for(var t=this.player().textTracks(),i=!1,n=0,r=t.length;n<r;n++){var a=t[n];if(a.kind!==this.kind_&&"showing"===a.mode){i=!0;break}}i?this.disable():this.enable()},t.buildCSSClass=function(){return"vjs-descriptions-button "+a.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-descriptions-button "+a.prototype.buildWrapperCSSClass.call(this)},e}(j);li.prototype.kind_="descriptions",li.prototype.controlText_="Descriptions",pt.registerComponent("DescriptionsButton",li);f=function(n){function e(e,t,i){return n.call(this,e,t,i)||this}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-subtitles-button "+n.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-subtitles-button "+n.prototype.buildWrapperCSSClass.call(this)},e}(j);f.prototype.kind_="subtitles",f.prototype.controlText_="Subtitles",pt.registerComponent("SubtitlesButton",f);var yn=function(i){function e(e,t){return t.track={player:e,kind:t.kind,label:t.kind+" settings",selectable:!1,default:!1,mode:"disabled"},t.selectable=!1,t.name="CaptionSettingsMenuItem",(e=i.call(this,e,t)||this).addClass("vjs-texttrack-settings"),e.controlText(", opens "+t.kind+" settings dialog"),e}return mt(e,i),e.prototype.handleClick=function(e){this.player().getChild("textTrackSettings").open()},e}(fn);pt.registerComponent("CaptionSettingsMenuItem",yn);ui=function(n){function e(e,t,i){return n.call(this,e,t,i)||this}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-captions-button "+n.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-captions-button "+n.prototype.buildWrapperCSSClass.call(this)},t.createItems=function(){var e=[];return this.player().tech_&&this.player().tech_.featuresNativeTextTracks||!this.player().getChild("textTrackSettings")||(e.push(new yn(this.player_,{kind:this.kind_})),this.hideThreshold_+=1),n.prototype.createItems.call(this,e)},e}(j);ui.prototype.kind_="captions",ui.prototype.controlText_="Captions",pt.registerComponent("CaptionsButton",ui);var vn=function(n){function e(){return n.apply(this,arguments)||this}return mt(e,n),e.prototype.createEl=function(e,t,i){t=n.prototype.createEl.call(this,e,t,i),i=t.querySelector(".vjs-menu-item-text");return"captions"===this.options_.track.kind&&(i.appendChild($("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),i.appendChild($("span",{className:"vjs-control-text",textContent:" "+this.localize("Captions")}))),t},e}(fn);pt.registerComponent("SubsCapsMenuItem",vn);Xt=function(i){function e(e,t){return(t=i.call(this,e,t=void 0===t?{}:t)||this).label_="subtitles",-1<["en","en-us","en-ca","fr-ca"].indexOf(t.player_.language_)&&(t.label_="captions"),t.menuButton_.controlText(ut(t.label_)),t}
4715mt(e,i);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-subs-caps-button "+i.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-subs-caps-button "+i.prototype.buildWrapperCSSClass.call(this)},t.createItems=function(){var e=[];return this.player().tech_&&this.player().tech_.featuresNativeTextTracks||!this.player().getChild("textTrackSettings")||(e.push(new yn(this.player_,{kind:this.label_})),this.hideThreshold_+=1),e=i.prototype.createItems.call(this,e,vn)},e}(j);Xt.prototype.kinds_=["captions","subtitles"],Xt.prototype.controlText_="Subtitles",pt.registerComponent("SubsCapsButton",Xt);var _n=function(s){function e(e,t){var n,i=t.track,r=e.audioTracks();t.label=i.label||i.language||"Unknown",t.selected=i.enabled,(n=s.call(this,e,t)||this).track=i,n.addClass("vjs-"+i.kind+"-menu-item");function a(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];n.handleTracksChange.apply(ft(n),t)}return r.addEventListener("change",a),n.on("dispose",function(){r.removeEventListener("change",a)}),n}mt(e,s);var t=e.prototype;return t.createEl=function(e,t,i){t=s.prototype.createEl.call(this,e,t,i),i=t.querySelector(".vjs-menu-item-text");return"main-desc"===this.options_.track.kind&&(i.appendChild($("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),i.appendChild($("span",{className:"vjs-control-text",textContent:" "+this.localize("Descriptions")}))),t},t.handleClick=function(e){if(s.prototype.handleClick.call(this,e),this.track.enabled=!0,this.player_.tech_.featuresNativeAudioTracks)for(var t=this.player_.audioTracks(),i=0;i<t.length;i++){var n=t[i];n!==this.track&&(n.enabled=n===this.track)}},t.handleTracksChange=function(e){this.selected(this.track.enabled)},e}(jt);pt.registerComponent("AudioTrackMenuItem",_n);I=function(i){function e(e,t){return(t=void 0===t?{}:t).tracks=e.audioTracks(),i.call(this,e,t)||this}mt(e,i);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-audio-button "+i.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-audio-button "+i.prototype.buildWrapperCSSClass.call(this)},t.createItems=function(e){void 0===e&&(e=[]),this.hideThreshold_=1;for(var t=this.player_.audioTracks(),i=0;i<t.length;i++){var n=t[i];e.push(new _n(this.player_,{track:n,selectable:!0,multiSelectable:!1}))}return e},e}(Ft);I.prototype.controlText_="Audio Track",pt.registerComponent("AudioTrackButton",I);var bn=function(a){function e(e,t){var i,n=t.rate,r=parseFloat(n,10);return t.label=n,t.selected=r===e.playbackRate(),t.selectable=!0,t.multiSelectable=!1,(i=a.call(this,e,t)||this).label=n,i.rate=r,i.on(e,"ratechange",function(e){return i.update(e)}),i}mt(e,a);var t=e.prototype;return t.handleClick=function(e){a.prototype.handleClick.call(this),this.player().playbackRate(this.rate)},t.update=function(e){this.selected(this.player().playbackRate()===this.rate)},e}(jt);bn.prototype.contentElType="button",pt.registerComponent("PlaybackRateMenuItem",bn);C=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.menuButton_.el_.setAttribute("aria-describedby",i.labelElId_),i.updateVisibility(),i.updateLabel(),i.on(e,"loadstart",function(e){return i.updateVisibility(e)}),i.on(e,"ratechange",function(e){return i.updateLabel(e)}),i.on(e,"playbackrateschange",function(e){return i.handlePlaybackRateschange(e)}),i}mt(e,n);var t=e.prototype;return t.createEl=function(){var e=n.prototype.createEl.call(this);return this.labelElId_="vjs-playback-rate-value-label-"+this.id_,this.labelEl_=$("div",{className:"vjs-playback-rate-value",id:this.labelElId_,textContent:"1x"}),e.appendChild(this.labelEl_),e},t.dispose=function(){this.labelEl_=null,n.prototype.dispose.call(this)},t.buildCSSClass=function(){return"vjs-playback-rate "+n.prototype.buildCSSClass.call(this)},t.buildWrapperCSSClass=function(){return"vjs-playback-rate "+n.prototype.buildWrapperCSSClass.call(this)},t.createItems=function(){for(var e=this.playbackRates(),t=[],i=e.length-1;0<=i;i--)t.push(new bn(this.player(),{rate:e[i]+"x"}));return t},t.updateARIAAttributes=function(){this.el().setAttribute("aria-valuenow",this.player().playbackRate())},t.handleClick=function(e){var t=this.player().playbackRate(),i=this.playbackRates(),t=(i.indexOf(t)+1)%i.length;this.player().playbackRate(i[t])},t.handlePlaybackRateschange=function(e){this.update()},t.playbackRates=function(){var e=this.player();return e.playbackRates&&e.playbackRates()||[]},t.playbackRateSupported=function(){return this.player().tech_&&this.player().tech_.featuresPlaybackRate&&this.playbackRates()&&0<this.playbackRates().length},t.updateVisibility=function(e){this.playbackRateSupported()?this.removeClass("vjs-hidden"):this.addClass("vjs-hidden")},t.updateLabel=function(e){this.playbackRateSupported()&&(this.labelEl_.textContent=this.player().playbackRate()+"x")},e}(Bt);C.prototype.controlText_="Playback Rate",pt.registerComponent("PlaybackRateMenuButton",C);k=function(n){function e(){return n.apply(this,arguments)||this}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-spacer "+n.prototype.buildCSSClass.call(this)},t.createEl=function(e,t,i){return void 0===e&&(e="div"),void 0===i&&(i={}),(t=void 0===t?{}:t).className||(t.className=this.buildCSSClass()),n.prototype.createEl.call(this,e,t,i)},e}(pt);pt.registerComponent("Spacer",k),pt.registerComponent("CustomControlSpacer",function(e){function t(){return e.apply(this,arguments)||this}mt(t,e);var i=t.prototype;return i.buildCSSClass=function(){return"vjs-custom-control-spacer "+e.prototype.buildCSSClass.call(this)},i.createEl=function(){return e.prototype.createEl.call(this,"div",{className:this.buildCSSClass(),textContent:" "})},t}(k));li=function(e){function t(){return e.apply(this,arguments)||this}return mt(t,e),t.prototype.createEl=function(){return e.prototype.createEl.call(this,"div",{className:"vjs-control-bar",dir:"ltr"})},t}(pt);li.prototype.options_={children:["playToggle","volumePanel","currentTimeDisplay","timeDivider","durationDisplay","progressControl","liveDisplay","seekToLive","remainingTimeDisplay","customControlSpacer","playbackRateMenuButton","chaptersButton","descriptionsButton","subsCapsButton","audioTrackButton","fullscreenToggle"]},"exitPictureInPicture"in document&&li.prototype.options_.children.splice(li.prototype.options_.children.length-1,0,"pictureInPictureToggle"),pt.registerComponent("ControlBar",li);f=function(n){function e(e,t){var i=n.call(this,e,t)||this;return i.on(e,"error",function(e){return i.open(e)}),i}mt(e,n);var t=e.prototype;return t.buildCSSClass=function(){return"vjs-error-display "+n.prototype.buildCSSClass.call(this)},t.content=function(){var e=this.player().error();return e?this.localize(e.message):""},e}(At);f.prototype.options_=g({}
vendor: 7,115 bytes, line 4715
4715,At.prototype.options_,{pauseOnOpen:!1,fillAlways:!0,temporary:!1,uncloseable:!0}),pt.registerComponent("ErrorDisplay",f);var Tn="vjs-text-track-settings",ui=["#000","Black"],j=["#00F","Blue"],Xt=["#0FF","Cyan"],Ft=["#0F0","Green"],I=["#F0F","Magenta"],jt=["#F00","Red"],Bt=["#FFF","White"],C=["#FF0","Yellow"],k=["1","Opaque"],li=["0.5","Semi-Transparent"],f=["0","Transparent"],Sn={backgroundColor:{selector:".vjs-bg-color > select",id:"captions-background-color-%s",label:"Color",options:[ui,Bt,jt,Ft,j,C,I,Xt]},backgroundOpacity:{selector:".vjs-bg-opacity > select",id:"captions-background-opacity-%s",label:"Transparency",options:[k,li,f]},color:{selector:".vjs-fg-color > select",id:"captions-foreground-color-%s",label:"Color",options:[Bt,ui,jt,Ft,j,C,I,Xt]},edgeStyle:{selector:".vjs-edge-style > select",id:"%s",label:"Text Edge Style",options:[["none","None"],["raised","Raised"],["depressed","Depressed"],["uniform","Uniform"],["dropshadow","Dropshadow"]]},fontFamily:{selector:".vjs-font-family > select",id:"captions-font-family-%s",label:"Font Family",options:[["proportionalSansSerif","Proportional Sans-Serif"],["monospaceSansSerif","Monospace Sans-Serif"],["proportionalSerif","Proportional Serif"],["monospaceSerif","Monospace Serif"],["casual","Casual"],["script","Script"],["small-caps","Small Caps"]]},fontPercent:{selector:".vjs-font-percent > select",id:"captions-font-size-%s",label:"Font Size",options:[["0.50","50%"],["0.75","75%"],["1.00","100%"],["1.25","125%"],["1.50","150%"],["1.75","175%"],["2.00","200%"],["3.00","300%"],["4.00","400%"]],default:2,parser:function(e){return"1.00"===e?null:Number(e)}},textOpacity:{selector:".vjs-text-opacity > select",id:"captions-foreground-opacity-%s",label:"Transparency",options:[k,li]},windowColor:{selector:".vjs-window-color > select",id:"captions-window-color-%s",label:"Color"},windowOpacity:{selector:".vjs-window-opacity > select",id:"captions-window-opacity-%s",label:"Transparency",options:[f,li,k]}};function wn(e,t){if((e=t?t(e):e)&&"none"!==e)return e}Sn.windowColor.options=Sn.backgroundColor.options,pt.registerComponent("TextTrackSettings",function(n){function e(e,t){var i;return t.temporary=!1,(i=n.call(this,e,t)||this).updateDisplay=i.updateDisplay.bind(ft(i)),i.fill(),i.hasBeenOpened_=i.hasBeenFilled_=!0,i.endDialog=$("p",{className:"vjs-control-text",textContent:i.localize("End of dialog window.")}),i.el().appendChild(i.endDialog),i.setDefaults(),void 0===t.persistTextTrackSettings&&(i.options_.persistTextTrackSettings=i.options_.playerOptions.persistTextTrackSettings),i.on(i.$(".vjs-done-button"),"click",function(){i.saveSettings(),i.close()}),i.on(i.$(".vjs-default-button"),"click",function(){i.setDefaults(),i.updateDisplay()}),_(Sn,function(e){i.on(i.$(e.selector),"change",i.updateDisplay)}),i.options_.persistTextTrackSettings&&i.restoreSettings(),i}mt(e,n);var t=e.prototype;return t.dispose=function(){this.endDialog=null,n.prototype.dispose.call(this)},t.createElSelect_=function(e,t,i){var n=this;void 0===t&&(t=""),void 0===i&&(i="label");var e=Sn[e],r=e.id.replace("%s",this.id_),a=[t,r].join(" ").trim();return["<"+i+' id="'+r+'" class="'+("label"===i?"vjs-label":"")+'">',this.localize(e.label),"</"+i+">",'<select aria-labelledby="'+a+'">'].concat(e.options.map(function(e){var t=r+"-"+e[1].replace(/\W+/g,"");return['<option id="'+t+'" value="'+e[0]+'" ','aria-labelledby="'+a+" "+t+'">',n.localize(e[1]),"</option>"].join("")})).concat("</select>").join("")},t.createElFgColor_=function(){var e="captions-text-legend-"+this.id_;return['<fieldset class="vjs-fg-color vjs-track-setting">','<legend id="'+e+'">',this.localize("Text"),"</legend>",this.createElSelect_("color",e),'<span class="vjs-text-opacity vjs-opacity">',this.createElSelect_("textOpacity",e),"</span>","</fieldset>"].join("")},t.createElBgColor_=function(){var e="captions-background-"+this.id_;return['<fieldset class="vjs-bg-color vjs-track-setting">','<legend id="'+e+'">',this.localize("Background"),"</legend>",this.createElSelect_("backgroundColor",e),'<span class="vjs-bg-opacity vjs-opacity">',this.createElSelect_("backgroundOpacity",e),"</span>","</fieldset>"].join("")},t.createElWinColor_=function(){var e="captions-window-"+this.id_;return['<fieldset class="vjs-window-color vjs-track-setting">','<legend id="'+e+'">',this.localize("Window"),"</legend>",this.createElSelect_("windowColor",e),'<span class="vjs-window-opacity vjs-opacity">',this.createElSelect_("windowOpacity",e),"</span>","</fieldset>"].join("")},t.createElColors_=function(){return $("div",{className:"vjs-track-settings-colors",innerHTML:[this.createElFgColor_(),this.createElBgColor_(),this.createElWinColor_()].join("")})},t.createElFont_=function(){return $("div",{className:"vjs-track-settings-font",innerHTML:['<fieldset class="vjs-font-percent vjs-track-setting">',this.createElSelect_("fontPercent","","legend"),"</fieldset>",'<fieldset class="vjs-edge-style vjs-track-setting">',this.createElSelect_("edgeStyle","","legend"),"</fieldset>",'<fieldset class="vjs-font-family vjs-track-setting">',this.createElSelect_("fontFamily","","legend"),"</fieldset>"].join("")})},t.createElControls_=function(){var e=this.localize("restore all settings to the default values");return $("div",{className:"vjs-track-settings-controls",innerHTML:['<button type="button" class="vjs-default-button" title="'+e+'">',this.localize("Reset"),'<span class="vjs-control-text"> '+e+"</span>","</button>",'<button type="button" class="vjs-done-button">'+this.localize("Done")+"</button>"].join("")})},t.content=function(){return[this.createElColors_(),this.createElFont_(),this.createElControls_()]},t.label=function(){return this.localize("Caption Settings Dialog")},t.description=function(){return this.localize("Beginning of dialog window. Escape will cancel and close the window.")},t.buildCSSClass=function(){return n.prototype.buildCSSClass.call(this)+" vjs-text-track-settings"},t.getValues=function(){var i,n,e,r=this;return n=function(e,t,i){var n,t=(n=r.$(t.selector),t=t.parser,wn(n.options[n.options.selectedIndex].value,t));return void 0!==t&&(e[i]=t),e},void 0===(e={})&&(e=0),v(i=Sn).reduce(function(e,t){return n(e,i[t],t)},e)},t.setValues=function(i){var n=this;_(Sn,function(e,t){!function(e,t,i){if(t)for(var n=0;n<e.options.length;n++)if(wn(e.options[n].value,i)===t){e.selectedIndex=n;break}}(n.$(e.selector),i[t],e.parser)})},t.setDefaults=function(){var i=this;_(Sn,function(e){var t=e.hasOwnProperty("default")?e.default:0;i.$(e.selector).selectedIndex=t})},t.restoreSettings=function(){var e;try{e=JSON.parse(window.localStorage.getItem(Tn))}catch(e){h.warn(e)}e&&this.setValues(e)},t.saveSettings=function(){if(this.options_.persistTextTrackSettings){var e=this.getValues();try{Object.keys(e).length?window.localStorage.setItem(Tn,JSON.stringify(e)):window.localStorage.removeItem(Tn)}catch(e){h.warn(e)}}},t.updateDisplay=function(){var e=this.player_.getChild("textTrackDisplay");e&&e.updateDisplay()},t.conditionalBlur_=function(){this.previouslyActiveEl_=null;var e=this.player_.controlBar,t=e&&e.subsCapsButton,e=e&&e.captionsButton;
4715t?t.focus():e&&e.focus()},e}(At)),pt.registerComponent("ResizeManager",function(a){function e(e,t){var i,n=t.ResizeObserver||window.ResizeObserver,r=lt({createEl:!(n=null===t.ResizeObserver?!1:n),reportTouchActivity:!1},t);return(i=a.call(this,e,r)||this).ResizeObserver=t.ResizeObserver||window.ResizeObserver,i.loadListener_=null,i.resizeObserver_=null,i.debouncedHandler_=Ge(function(){i.resizeHandler()},100,!1,ft(i)),n?(i.resizeObserver_=new i.ResizeObserver(i.debouncedHandler_),i.resizeObserver_.observe(e.el())):(i.loadListener_=function(){var e,t;i.el_&&i.el_.contentWindow&&(e=i.debouncedHandler_,t=i.unloadListener_=function(){Fe(this,"resize",e),Fe(this,"unload",t),t=null},Be(i.el_.contentWindow,"unload",t),Be(i.el_.contentWindow,"resize",e))},i.one("load",i.loadListener_)),i}mt(e,a);var t=e.prototype;return t.createEl=function(){return a.prototype.createEl.call(this,"iframe",{className:"vjs-resize-manager",tabIndex:-1},{"aria-hidden":"true"})},t.resizeHandler=function(){this.player_&&this.player_.trigger&&this.player_.trigger("playerresize")},t.dispose=function(){this.debouncedHandler_&&this.debouncedHandler_.cancel(),this.resizeObserver_&&(this.player_.el()&&this.resizeObserver_.unobserve(this.player_.el()),this.resizeObserver_.disconnect()),this.loadListener_&&this.off("load",this.loadListener_),this.el_&&this.el_.contentWindow&&this.unloadListener_&&this.unloadListener_.call(this.el_.contentWindow),this.ResizeObserver=null,this.resizeObserver=null,this.debouncedHandler_=null,this.loadListener_=null,a.prototype.dispose.call(this)},e}(pt));var En={trackingThreshold:20,liveTolerance:15};pt.registerComponent("LiveTracker",function(n){function e(e,t){var t=lt(En,t,{createEl:!1}),i=n.call(this,e,t)||this;return i.handleVisibilityChange_=function(e){return i.handleVisibilityChange(e)},i.trackLiveHandler_=function(){return i.trackLive_()},i.handlePlay_=function(e){return i.handlePlay(e)},i.handleFirstTimeupdate_=function(e){return i.handleFirstTimeupdate(e)},i.handleSeeked_=function(e){return i.handleSeeked(e)},i.seekToLiveEdge_=function(e){return i.seekToLiveEdge(e)},i.reset_(),i.on(i.player_,"durationchange",function(e){return i.handleDurationchange(e)}),i.on(i.player_,"canplay",function(){return i.toggleTracking()}),N&&"hidden"in document&&"visibilityState"in document&&i.on(document,"visibilitychange",i.handleVisibilityChange_),i}mt(e,n);var t=e.prototype;return t.handleVisibilityChange=function(){this.player_.duration()===1/0&&(document.hidden?this.stopTracking():this.startTracking())},t.trackLive_=function(){var e,t=this.player_.seekable();t&&t.length&&(e=Number(window.performance.now().toFixed(4)),t=-1===this.lastTime_?0:(e-this.lastTime_)/1e3,this.lastTime_=e,this.pastSeekEnd_=this.pastSeekEnd()+t,e=this.liveCurrentTime(),t=this.player_.currentTime(),t=this.player_.paused()||this.seekedBehindLive_||Math.abs(e-t)>this.options_.liveTolerance,(t=!this.timeupdateSeen_||e===1/0?!1:t)!==this.behindLiveEdge_&&(this.behindLiveEdge_=t,this.trigger("liveedgechange")))},t.handleDurationchange=function(){this.toggleTracking()},t.toggleTracking=function(){this.player_.duration()===1/0&&this.liveWindow()>=this.options_.trackingThreshold?(this.player_.options_.liveui&&this.player_.addClass("vjs-liveui"),this.startTracking()):(this.player_.removeClass("vjs-liveui"),this.stopTracking())},t.startTracking=function(){this.isTracking()||(this.timeupdateSeen_||(this.timeupdateSeen_=this.player_.hasStarted()),this.trackingInterval_=this.setInterval(this.trackLiveHandler_,30),this.trackLive_(),this.on(this.player_,["play","pause"],this.trackLiveHandler_),this.timeupdateSeen_?this.on(this.player_,"seeked",this.handleSeeked_):(this.one(this.player_,"play",this.handlePlay_),this.one(this.player_,"timeupdate",this.handleFirstTimeupdate_)))},t.handleFirstTimeupdate=function(){this.timeupdateSeen_=!0,this.on(this.player_,"seeked",this.handleSeeked_)},t.handleSeeked=function(){var e=Math.abs(this.liveCurrentTime()-this.player_.currentTime());this.seekedBehindLive_=this.nextSeekedFromUser_&&2<e,this.nextSeekedFromUser_=!1,this.trackLive_()},t.handlePlay=function(){this.one(this.player_,"timeupdate",this.seekToLiveEdge_)},t.reset_=function(){this.lastTime_=-1,this.pastSeekEnd_=0,this.lastSeekEnd_=-1,this.behindLiveEdge_=!0,this.timeupdateSeen_=!1,this.seekedBehindLive_=!1,this.nextSeekedFromUser_=!1,this.clearInterval(this.trackingInterval_),this.trackingInterval_=null,this.off(this.player_,["play","pause"],this.trackLiveHandler_),this.off(this.player_,"seeked",this.handleSeeked_),this.off(this.player_,"play",this.handlePlay_),this.off(this.player_,"timeupdate",this.handleFirstTimeupdate_),this.off(this.player_,"timeupdate",this.seekToLiveEdge_)},t.nextSeekedFromUser=function(){this.nextSeekedFromUser_=!0},t.stopTracking=function(){this.isTracking()&&(this.reset_(),this.trigger("liveedgechange"))},t.seekableEnd=function(){for(var e=this.player_.seekable(),t=[],i=e?e.length:0;i--;)t.push(e.end(i));return t.length?t.sort()[t.length-1]:1/0},t.seekableStart=function(){for(var e=this.player_.seekable(),t=[],i=e?e.length:0;i--;)t.push(e.start(i));return t.length?t.sort()[0]:0}
4715,t.liveWindow=function(){var e=this.liveCurrentTime();return e===1/0?0:e-this.seekableStart()},t.isLive=function(){return this.isTracking()},t.atLiveEdge=function(){return!this.behindLiveEdge()},t.liveCurrentTime=function(){return this.pastSeekEnd()+this.seekableEnd()},t.pastSeekEnd=function(){var e=this.seekableEnd();return-1!==this.lastSeekEnd_&&e!==this.lastSeekEnd_&&(this.pastSeekEnd_=0),this.lastSeekEnd_=e,this.pastSeekEnd_},t.behindLiveEdge=function(){return this.behindLiveEdge_},t.isTracking=function(){return"number"==typeof this.trackingInterval_},t.seekToLiveEdge=function(){this.seekedBehindLive_=!1,this.atLiveEdge()||(this.nextSeekedFromUser_=!1,this.player_.currentTime(this.liveCurrentTime()))},t.dispose=function(){this.off(document,"visibilitychange",this.handleVisibilityChange_),this.stopTracking(),n.prototype.dispose.call(this)},e}(pt));function kn(e){if((n=e.el()).hasAttribute("src"))return e.triggerSourceset(n.src),1;var t=e.$$("source"),i=[],n="";if(t.length){for(var r=0;r<t.length;r++){var a=t[r].src;a&&-1===i.indexOf(a)&&i.push(a)}return!!i.length&&(1===i.length&&(n=i[0]),e.triggerSourceset(n),!0)}}function Cn(e,t){for(var i={},n=0;n<e.length&&!((i=Object.getOwnPropertyDescriptor(e[n],t))&&i.set&&i.get);n++);return i.enumerable=!0,i.configurable=!0,i}function In(a){var t,e,i,s=a.el();s.resetSourceWatch_||(t={},e=Cn([a.el(),window.HTMLMediaElement.prototype,window.Element.prototype,Ln],"innerHTML"),i=function(r){return function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];var n=r.apply(s,t);return kn(a),n}},["append","appendChild","insertAdjacentHTML"].forEach(function(e){s[e]&&(t[e]=s[e],s[e]=i(t[e]))}),Object.defineProperty(s,"innerHTML",lt(e,{set:i(e.set)})),s.resetSourceWatch_=function(){s.resetSourceWatch_=null,Object.keys(t).forEach(function(e){s[e]=t[e]}),Object.defineProperty(s,"innerHTML",e)},a.one("sourceset",s.resetSourceWatch_))}function xn(i){var n,t,r,a;i.featuresSourceset&&((n=i.el()).resetSourceset_||(t=Cn([i.el(),window.HTMLMediaElement.prototype,Dn],"src"),r=n.setAttribute,a=n.load,Object.defineProperty(n,"src",lt(t,{set:function(e){e=t.set.call(n,e);return i.triggerSourceset(n.src),e}})),n.setAttribute=function(e,t){t=r.call(n,e,t);return/src/i.test(e)&&i.triggerSourceset(n.src),t},n.load=function(){var e=a.call(n);return kn(i)||(i.triggerSourceset(""),In(i)),e},n.currentSrc?i.triggerSourceset(n.currentSrc):kn(i)||In(i),n.resetSourceset_=function(){n.resetSourceset_=null,n.load=a,n.setAttribute=r,Object.defineProperty(n,"src",t),n.resetSourceWatch_&&n.resetSourceWatch_()}))}function An(t,i,n,e){function r(e){return Object.defineProperty(t,i,{value:e,enumerable:!0,writable:!0})}var a={configurable:!0,enumerable:!0,get:function(){var e=n();return r(e),e}};return(e=void 0===e?!0:e)&&(a.set=r),Object.defineProperty(t,i,a)}var Pn,Ln=Object.defineProperty({},"innerHTML",{get:function(){return this.cloneNode(!0).innerHTML},set:function(e){var t=document.createElement(this.nodeName.toLowerCase());t.innerHTML=e;for(var i=document.createDocumentFragment();t.childNodes.length;)i.appendChild(t.childNodes[0]);return this.innerText="",window.Element.prototype.appendChild.call(this,i),this.innerHTML}}),Dn=Object.defineProperty({},"src",{get:function(){return this.hasAttribute("src")?Mt(window.Element.prototype.getAttribute.call(this,"src")):""},set:function(e){return window.Element.prototype.setAttribute.call(this,"src",e),e}}),On=function(l){function s(e,t){var i=l.call(this,e,t)||this,t=e.source,n=!1;if(t&&(i.el_.currentSrc!==t.src||e.tag&&3===e.tag.initNetworkState_)?i.setSource(t):i.handleLateInit_(i.el_),e.enableSourceset&&i.setupSourcesetHandling_(),i.isScrubbing_=!1,i.el_.hasChildNodes()){for(var r=i.el_.childNodes,a=r.length,s=[];a--;){var o=r[a];"track"===o.nodeName.toLowerCase()&&(i.featuresNativeTextTracks?(i.remoteTextTrackEls().addTrackElement_(o),i.remoteTextTracks().addTrack(o.track),i.textTracks().addTrack(o.track),n||i.el_.hasAttribute("crossorigin")||!Ut(o.src)||(n=!0)):s.push(o))}for(var u=0;u<s.length;u++)i.el_.removeChild(s[u])}return i.proxyNativeTracks_(),i.featuresNativeTextTracks&&n&&h.warn("Text Tracks are being loaded from another origin but the crossorigin attribute isn't used.\nThis may prevent text tracks from loading."),i.restoreMetadataTracksInIOSNativePlayer_(),(F||H||L)&&!0===e.nativeControlsForTouch&&i.setControls(!0),i.proxyWebkitFullscreen_(),i.triggerReady(),i}mt(s,l);var e=s.prototype;return e.dispose=function(){this.el_&&this.el_.resetSourceset_&&this.el_.resetSourceset_(),s.disposeMediaElement(this.el_),this.options_=null,l.prototype.dispose.call(this)},e.setupSourcesetHandling_=function(){xn(this)},e.restoreMetadataTracksInIOSNativePlayer_=function(){function e(){i=[];for(var e=0;e<n.length;e++){var t=n[e];"metadata"===t.kind&&i.push({track:t,storedMode:t.mode})}}var i,n=this.textTracks();e(),n.addEventListener("change",e),this.on("dispose",function(){return n.removeEventListener("change",e)});function r(){for(var e=0;e<i.length;e++){var t=i[e];"disabled"===t.track.mode&&t.track.mode!==t.storedMode&&(t.track.mode=t.storedMode)}n.removeEventListener("change",r)}this.on("webkitbeginfullscreen",function(){n.removeEventListener("change",e),n.removeEventListener("change",r),n.addEventListener("change",r)}),this.on("webkitendfullscreen",function(){n.removeEventListener("change",e),n.addEventListener("change",e),n.removeEventListener("change",r)})},e.overrideNative_=function(e,t){var i,n=this;t===this["featuresNative"+e+"Tracks"]&&(this[(i=e.toLowerCase())+"TracksListeners_"]&&Object.keys(this[i+"TracksListeners_"]).forEac
4715h(function(e){n.el()[i+"Tracks"].removeEventListener(e,n[i+"TracksListeners_"][e])}),this["featuresNative"+e+"Tracks"]=!t,this[i+"TracksListeners_"]=null,this.proxyNativeTracksForType_(i))},e.overrideNativeAudioTracks=function(e){this.overrideNative_("Audio",e)},e.overrideNativeVideoTracks=function(e){this.overrideNative_("Video",e)},e.proxyNativeTracksForType_=function(i){var e,t,n=this,r=ai[i],a=this.el()[r.getterName],s=this[r.getterName]();this["featuresNative"+r.capitalName+"Tracks"]&&a&&a.addEventListener&&(t=function(){for(var e=[],t=0;t<s.length;t++){for(var i=!1,n=0;n<a.length;n++)if(a[n]===s[t]){i=!0;break}i||e.push(s[t])}for(;e.length;)s.removeTrack(e.shift())},this[r.getterName+"Listeners_"]=e={change:function(e){var t={type:"change",target:s,currentTarget:s,srcElement:s};s.trigger(t),"text"===i&&n[si.remoteText.getterName]().trigger(t)},addtrack:function(e){s.addTrack(e.track)},removetrack:function(e){s.removeTrack(e.track)}},Object.keys(e).forEach(function(t){var i=e[t];a.addEventListener(t,i),n.on("dispose",function(e){return a.removeEventListener(t,i)})}),this.on("loadstart",t),this.on("dispose",function(e){return n.off("loadstart",t)}))},e.proxyNativeTracks_=function(){var t=this;ai.names.forEach(function(e){t.proxyNativeTracksForType_(e)})},e.createEl=function(){var e,t=this.options_.tag;t&&(this.options_.playerElIngest||this.movingMediaElementInDOM)||(t?(e=t.cloneNode(!0),t.parentNode&&t.parentNode.insertBefore(e,t),s.disposeMediaElement(t),t=e):(t=document.createElement("video"),e=lt({},this.options_.tag&&ae(this.options_.tag)),F&&!0===this.options_.nativeControlsForTouch||delete e.controls,re(t,b(e,{id:this.options_.techId,class:"vjs-tech"}))),t.playerId=this.options_.playerId),"undefined"!=typeof this.options_.preload&&oe(t,"preload",this.options_.preload),void 0!==this.options_.disablePictureInPicture&&(t.disablePictureInPicture=this.options_.disablePictureInPicture);for(var i=["loop","muted","playsinline","autoplay"],n=0;n<i.length;n++){var r=i[n],a=this.options_[r];"undefined"!=typeof a&&(a?oe(t,r,r):ue(t,r),t[r]=a)}return t},e.handleLateInit_=function(e){if(0!==e.networkState&&3!==e.networkState){if(0===e.readyState){var t=!1,i=function(){t=!0};this.on("loadstart",i);var n=function(){t||this.trigger("loadstart")};return this.on("loadedmetadata",n),void this.ready(function(){this.off("loadstart",i),this.off("loadedmetadata",n),t||this.trigger("loadstart")})}var r=["loadstart"];r.push("loadedmetadata"),2<=e.readyState&&r.push("loadeddata"),3<=e.readyState&&r.push("canplay"),4<=e.readyState&&r.push("canplaythrough"),this.ready(function(){r.forEach(function(e){this.trigger(e)},this)})}},e.setScrubbing=function(e){this.isScrubbing_=e},e.scrubbing=function(){return this.isScrubbing_},e.setCurrentTime=function(e){try{this.isScrubbing_&&this.el_.fastSeek&&V?this.el_.fastSeek(e):this.el_.currentTime=e}catch(e){h(e,"Video is not ready. (Video.js)")}},e.duration=function(){var t=this;return this.el_.duration===1/0&&A&&R&&0===this.el_.currentTime?(this.on("timeupdate",function e(){0<t.el_.currentTime&&(t.el_.duration===1/0&&t.trigger("durationchange"),t.off("timeupdate",e))}),NaN):this.el_.duration||NaN},e.width=function(){return this.el_.offsetWidth},e.height=function(){return this.el_.offsetHeight},e.proxyWebkitFullscreen_=function(){var e,t,i=this;"webkitDisplayingFullscreen"in this.el_&&(e=function(){this.trigger("fullscreenchange",{isFullscreen:!1}),this.el_.controls&&!this.options_.nativeControlsForTouch&&this.controls()&&(this.el_.controls=!1)},t=function(){"webkitPresentationMode"in this.el_&&"picture-in-picture"!==this.el_.webkitPresentationMode&&(this.one("webkitendfullscreen",e),this.trigger("fullscreenchange",{isFullscreen:!0,nativeIOSFullscreen:!0}))},this.on("webkitbeginfullscreen",t),this.on("dispose",function(){i.off("webkitbeginfullscreen",t),i.off("webkitendfullscreen",e)}))},e.supportsFullScreen=function(){if("function"==typeof this.el_.webkitEnterFullScreen){var e=window.navigator&&window.navigator.userAgent||"";if(/Android/.test(e)||!/Chrome|Mac OS X 10.5/.test(e))return!0}return!1},e.enterFullScreen=function(){var e=this.el_;if(e.paused&&e.networkState<=e.HAVE_METADATA)Et(this.el_.play()),this.setTimeout(function(){e.pause();try{e.webkitEnterFullScreen()}catch(e){this.trigger("fullscreenerror",e)}},0);else try{e.webkitEnterFullScreen()}catch(e){this.trigger("fullscreenerror",e)}},e.exitFullScreen=function(){this.el_.webkitDisplayingFullscreen?this.el_.webkitExitFullScreen():this.trigger("fullscreenerror",new Error("The video is not fullscreen"))},e.requestPictureInPicture=function(){return this.el_.requestPictureInPicture()},e.src=function(e){if(void 0===e)return this.el_.src;this.setSrc(e)},e.reset=function(){s.resetMediaElement(this.el_)},e.currentSrc=function(){return this.currentSource_?this.currentSource_.src:this.el_.currentSrc},e.setControls=function(e){this.el_.controls=!!e},e.addTextTrack=function(e,t,i){return this.featuresNativeTextTracks?this.el_.addTextTrack(e,t,i):l.prototype.addTextTrack.call(this,e,t,i)},e.createRemoteTextTrack=function(e){if(!this.featuresNativeTextTracks)return l.prototype.createRemoteTextTrack.call(this,e);var t=document.createElement("track");return e.kind&&(t.kind=e.kind),e.label&&(t.label=e.label),(e.language||e.srclang)&&(t.srclang=e.language||e.srclang),e.default&&(t.default=e.default),e.id&&(t.id=e.id),e.src&&(t.src=e.src),t},e.addRemoteTextTrack=function(e,t){t=l.prototype.addRemoteTextTrack.call(this,e,t);return this.featuresNativeTextTracks&&this.el().appendChild(t),t},e.removeRemoteTextTrack=function(e){if(l.prototype.removeRemoteTextTrack.call(this,e),this.featuresNativeTextTracks)for(var t=this.$$("track"),i=t.length;i--;)e!==t[i]&&e!==t[i].track||this.el().removeChild(t[i])},e.getVideoPlaybackQuality=function(){if("function"==typeof this.el().getVideoPlaybackQuality)return this.el().getVideoPlaybackQuality();var e={};return"undefined"!=typeof this.el().webkitDroppedFrameCount&&"undefined"!=typeof this.el().webkitDecodedFrameCount&&(e.droppedVideoFrames=this.el().webkitDroppedFrameCount,e.totalVideoFrames=this.el().webkitDecodedFrameCount),window.performance&&"function"==typeof window.performance.now?e.creationTime=window.performance.now():window.performance&&window.performance.timing&&"number"==typeof window.performance.timing.navigationStart&&(e.creationTime=window.Date.now()-window.performance.timing.navigationStart),e},s}(ji);An(On,"TEST_VID",function(){if(X()){var e=document.createElement("video"),t=document.createElement("track");return t.kind="captions",t.srclang="en",t.label="English",e.appendChild(t),e}}),On.isSupported=function(){try{On.TEST_VID.volume=.5}catch(e){return!1}return!(!On.TEST_VID||!On.TEST_VID.canPlayType)},On.canPlayType=function(e){return On.TEST_VID.canPlayType(e)},On.canPlaySource=function(e,t){return On.canPlayType(e.type)},On.canControlVolume=function(){try{var e=On.TEST_VID.volume;On.TEST_VID.volume=e/2+.1;var t=e!==On.TEST_VID.volume;return t&&q?(window.setTimeout(function(){On&&On.prototype&&(On.prototype.featuresVolumeControl=e!==On.TEST_VID.volume)}),!1):t}catch(e){return!1}},On.canMuteVolume=function(){try{var e=On.TEST_VID.muted;return On.TEST_VID.muted=!e,On.TEST_VID.muted?oe(On.TEST_VID,"muted","muted"):ue(On.TEST_VID,"muted"),e!==On.TEST_VID.muted}catch(e){return!1}},On.canControlPlaybackRate=function(){if(A&&R&&M<58)return!1;try{var e=On.TEST_VID.playbackRate;return On.TEST_VID.playbackRate=e/2+.1,e!==On.TEST_VID.playbackRate}catch(e){return!1}},On.canOverrideAttributes=function(){try{var e=function(){};Object.defineProperty(document.createElement("video"),"src",{get:e,set:e}),Object.defineProperty(document.createElement("audio"),"src",{get:e,set:e}),Object.defineProperty(document.createElement("video"),"innerHTML",{get:e,set:e}),Object.defineProperty(document.createElement("audio"),"innerHTML",{get:e,set:e})}catch(e){return!1}return!0},On.supportsNativeTextTracks=function(){return V||q&&R},On.supportsNativeVideoTracks=function(){return!(!On.TEST_VID||!On.TEST_VID.videoTracks)},On.supportsNativeAudioTracks=function(){return!(!On.TEST_VID||!On.TEST_VID.audioTracks)},On.Events=["loadstart","suspend","abort","error","emptied","stalled","loadedmetadata","loadeddata","canplay","canplaythrough","playing","waiting","seeking","seeked","ended","durationchange","timeupdate","progress","play","pause","ratechange","resize","volumechange"],[["featuresMuteControl","canMuteVolume"],["featuresPlaybackRate","canControlPlaybackRate"],["featuresSourceset","canOverrideAttributes"],["featuresNativeTextTracks","supportsNativeTextTracks"],["featuresNativeVideoTracks","supportsNativeVideoTracks"],["featuresNativeAudioTracks","supportsNativeAudioTracks"]].forEac
vendor: 4,819 bytes, line 4715
4715h(function(e){var t=e[0],i=e[1];An(On.prototype,t,function(){return On[i]()},!0)}),On.prototype.featuresVolumeControl=On.canControlVolume(),On.prototype.movingMediaElementInDOM=!q,On.prototype.featuresFullscreenResize=!0,On.prototype.featuresProgressEvents=!0,On.prototype.featuresTimeupdateEvents=!0,On.patchCanPlayType=function(){4<=P&&!D&&!R&&(Pn=On.TEST_VID&&On.TEST_VID.constructor.prototype.canPlayType,On.TEST_VID.constructor.prototype.canPlayType=function(e){return e&&/^application\/(?:x-|vnd\.apple\.)mpegurl/i.test(e)?"maybe":Pn.call(this,e)})},On.unpatchCanPlayType=function(){var e=On.TEST_VID.constructor.prototype.canPlayType;return Pn&&(On.TEST_VID.constructor.prototype.canPlayType=Pn),e},On.patchCanPlayType(),On.disposeMediaElement=function(e){if(e){for(e.parentNode&&e.parentNode.removeChild(e);e.hasChildNodes();)e.removeChild(e.firstChild);e.removeAttribute("src"),"function"==typeof e.load&&function(){try{e.load()}catch(e){}}()}},On.resetMediaElement=function(e){if(e){for(var t=e.querySelectorAll("source"),i=t.length;i--;)e.removeChild(t[i]);e.removeAttribute("src"),"function"==typeof e.load&&function(){try{e.load()}catch(e){}}()}},["muted","defaultMuted","autoplay","controls","loop","playsinline"].forEach(function(e){On.prototype[e]=function(){return this.el_[e]||this.el_.hasAttribute(e)}}),["muted","defaultMuted","autoplay","loop","playsinline"].forEach(function(t){On.prototype["set"+ut(t)]=function(e){(this.el_[t]=e)?this.el_.setAttribute(t,t):this.el_.removeAttribute(t)}}),["paused","currentTime","buffered","volume","poster","preload","error","seeking","seekable","ended","playbackRate","defaultPlaybackRate","disablePictureInPicture","played","networkState","readyState","videoWidth","videoHeight","crossOrigin"].forEach(function(e){On.prototype[e]=function(){return this.el_[e]}}),["volume","src","poster","preload","playbackRate","defaultPlaybackRate","disablePictureInPicture","crossOrigin"].forEach(function(t){On.prototype["set"+ut(t)]=function(e){this.el_[t]=e}}),["pause","load","play"].forEach(function(e){On.prototype[e]=function(){return this.el_[e]()}}),ji.withSourceHandlers(On),On.nativeSourceHandler={},On.nativeSourceHandler.canPlayType=function(e){try{return On.TEST_VID.canPlayType(e)}catch(e){return""}},On.nativeSourceHandler.canHandleSource=function(e,t){if(e.type)return On.nativeSourceHandler.canPlayType(e.type);if(e.src){e=Nt(e.src);return On.nativeSourceHandler.canPlayType("video/"+e)}return""},On.nativeSourceHandler.handleSource=function(e,t,i){t.setSrc(e.src)},On.nativeSourceHandler.dispose=function(){},On.registerSourceHandler(On.nativeSourceHandler),ji.registerTech("Html5",On);var Rn=["progress","abort","suspend","emptied","stalled","loadedmetadata","loadeddata","timeupdate","resize","volumechange","texttrackchange"],Mn={canplay:"CanPlay",canplaythrough:"CanPlayThrough",playing:"Playing",seeked:"Seeked"},Nn=["tiny","xsmall","small","medium","large","xlarge","huge"],Un={};Nn.forEach(function(e){var t="x"===e.charAt(0)?"x-"+e.substring(1):e;Un[e]="vjs-layout-"+t});var Bn={tiny:210,xsmall:320,small:425,medium:768,large:1440,xlarge:2560,huge:1/0},Fn=function(c){function o(e,t,i){var n,r;if(e.id=e.id||t.id||"vjs_video_"+Pe++,(t=b(o.getTagSettings(e),t)).initChildren=!1,t.createEl=!1,t.evented=!1,t.reportTouchActivity=!1,!t.language)if("function"==typeof e.closest){var a=e.closest("[lang]");a&&a.getAttribute&&(t.language=a.getAttribute("lang"))}else for(var s=e;s&&1===s.nodeType;){if(ae(s).hasOwnProperty("lang")){t.language=s.getAttribute("lang");break}s=s.parentNode}if((n=c.call(this,null,t,i)||this).boundDocumentFullscreenChange_=function(e){return n.documentFullscreenChange_(e)},n.boundFullWindowOnEscKey_=function(e){return n.fullWindowOnEscKey(e)},n.boundUpdateStyleEl_=function(e){return n.updateStyleEl_(e)},n.boundApplyInitTime_=function(e){return n.applyInitTime_(e)},n.boundUpdateCurrentBreakpoint_=function(e){return n.updateCurrentBreakpoint_(e)},n.boundHandleTechClick_=function(e){return n.handleTechClick_(e)},n.boundHandleTechDoubleClick_=function(e){return n.handleTechDoubleClick_(e)},n.boundHandleTechTouchStart_=function(e){return n.handleTechTouchStart_(e)},n.boundHandleTechTouchMove_=function(e){return n.handleTechTouchMove_(e)},n.boundHandleTechTouchEnd_=function(e){return n.handleTechTouchEnd_(e)},n.boundHandleTechTap_=function(e){return n.handleTechTap_(e)},n.isFullscreen_=!1,n.log=p(n.id_),n.fsApi_=l,n.isPosterFromTech_=!1,n.queuedCallbacks_=[],n.isReady_=!1,n.hasStarted_=!1,n.userActive_=!1,n.debugEnabled_=!1,!n.options_||!n.options_.techOrder||!n.options_.techOrder.length)throw new Error("No techOrder specified. Did you overwrite videojs.options instead of just changing the properties you want to override?");n.tag=e,n.tagAttributes=e&&ae(e),n.language(n.options_.language),t.languages?(r={}
4715,Object.getOwnPropertyNames(t.languages).forEach(function(e){r[e.toLowerCase()]=t.languages[e]}),n.languages_=r):n.languages_=o.prototype.options_.languages,n.resetCache_(),n.poster_=t.poster||"",n.controls_=!!t.controls,e.controls=!1,e.removeAttribute("controls"),n.changingSrc_=!1,n.playCallbacks_=[],n.playTerminatedQueue_=[],e.hasAttribute("autoplay")?n.autoplay(!0):n.autoplay(n.options_.autoplay),t.plugins&&Object.keys(t.plugins).forEach(function(e){if("function"!=typeof n[e])throw new Error('plugin "'+e+'" does not exist')}),n.scrubbing_=!1,n.el_=n.createEl(),rt(ft(n),{eventBusKey:"el_"}),n.fsApi_.requestFullscreen&&(Be(document,n.fsApi_.fullscreenchange,n.boundDocumentFullscreenChange_),n.on(n.fsApi_.fullscreenchange,n.boundDocumentFullscreenChange_)),n.fluid_&&n.on(["playerreset","resize"],n.boundUpdateStyleEl_);i=lt(n.options_);t.plugins&&Object.keys(t.plugins).forEach(function(e){n[e](t.plugins[e])}),t.debug&&n.debug(!0),n.options_.playerOptions=i,n.middleware_=[],n.playbackRates(t.playbackRates),n.initChildren(),n.isAudio("audio"===e.nodeName.toLowerCase()),n.controls()?n.addClass("vjs-controls-enabled"):n.addClass("vjs-controls-disabled"),n.el_.setAttribute("role","region"),n.isAudio()?n.el_.setAttribute("aria-label",n.localize("Audio Player")):n.el_.setAttribute("aria-label",n.localize("Video Player")),n.isAudio()&&n.addClass("vjs-audio"),n.flexNotSupported_()&&n.addClass("vjs-no-flex"),F&&n.addClass("vjs-touch-enabled"),q||n.addClass("vjs-workinghover"),o.players[n.id_]=ft(n);e=u.split(".")[0];return n.addClass("vjs-v"+e),n.userActive(!0),n.reportUserActivity(),n.one("play",function(e){return n.listenForUserActivity_(e)}),n.on("stageclick",function(e){return n.handleStageClick_(e)}),n.on("keydown",function(e){return n.handleKeyDown(e)}),n.on("languagechange",function(e){return n.handleLanguagechange(e)}),n.breakpoints(n.options_.breakpoints),n.responsive(n.options_.responsive),n}mt(o,c);var e=o.prototype;return e.dispose=function(){var t=this;this.trigger("dispose"),this.off("dispose"),Fe(document,this.fsApi_.fullscreenchange,this.boundDocumentFullscreenChange_),Fe(document,"keydown",this.boundFullWindowOnEscKey_),this.styleEl_&&this.styleEl_.parentNode&&(this.styleEl_.parentNode.removeChild(this.styleEl_),this.styleEl_=null),o.players[this.id_]=null,this.tag&&this.tag.player&&(this.tag.player=null),this.el_&&this.el_.player&&(this.el_.player=null),this.tech_&&(this.tech_.dispose(),this.isPosterFromTech_=!1,this.poster_=""),this.playerElIngest_&&(this.playerElIngest_=null),this.tag&&(this.tag=null),qi[this.id()]=null,oi.names.forEach(function(e){e=oi[e],e=t[e.getterName]();e&&e.off&&e.off()}),c.prototype.dispose.call(this)},e.createEl=function(){var t,i=this.tag,e=this.playerElIngest_=i.parentNode&&i.parentNode.hasAttribute&&i.parentNode.hasAttribute("data-vjs-player"),n="video-js"===this.tag.tagName.toLowerCase();e?t=this.el_=i.parentNode:n||(t=this.el_=c.prototype.createEl.call(this,"div"));var r,a,s=ae(i);if(n){for(t=this.el_=i,i=this.tag=document.createElement("video");t.children.length;)i.appendChild(t.firstChild);ee(t,"video-js")||te(t,"video-js"),t.appendChild(i),e=this.playerElIngest_=t,Object.keys(t).forEach(function(e){try{i[e]=t[e]}catch(e){}})}i.setAttribute("tabindex","-1"),s.tabindex="-1",(N||R&&B)&&(i.setAttribute("role","application"),s.role="application"),i.removeAttribute("width"),i.removeAttribute("height"),"width"in s&&delete s.width,"height"in s&&delete s.height,Object.getOwnPropertyNames(s).forEach(function(e){n&&"class"===e||t.setAttribute(e,s[e]),n&&i.setAttribute(e,s[e])}),i.playerId=i.id,i.id+="_html5_api",i.className="vjs-tech",(i.player=t.player=this).addClass("vjs-paused"),!0!==window.VIDEOJS_NO_DYNAMIC_STYLE&&(this.styleEl_=xe("vjs-styles-dimensions"),r=Te(".vjs-styles-defaults"),(a=Te("head")).insertBefore(this.styleEl_,r?r.nextSibling:a.firstChild)),this.fill_=!1,this.fluid_=!1,this.width(this.options_.width),this.height(this.options_.height),this.fill(this.options_.fill),this.fluid(this.options_.fluid),this.aspectRatio(this.options_.aspectRatio),this.crossOrigin(this.options_.crossOrigin||this.options_.crossorigin);for(var o=i.getElementsByTagName("a"),u=0;u<o.length;u++){var l=o.item(u);te(l,"vjs-hidden"),l.setAttribute("hidden","hidden")}return i.initNetworkState_=i.networkState,i.parentNode&&!e&&i.parentNode.insertBefore(t,i),Z(i,t),this.children_.unshift(i),this.el_.setAttribute("lang",this.language_),this.el_.setAttribute("translate","no"),this.el_=t},e.crossOrigin=function(e){if(!e)return this.techGet_("crossOrigin");"anonymous"===e||"use-credentials"===e?this.techCall_("setCrossOrigin",e):h.warn('crossOrigin must be "anonymous" or "use-credentials", given "'+e+'"')},e.width=function(e){return this.dimension("width",e)},e.height=function(e){return this.dimension("height",e)},e.dimension=function(e,t){var i=e+"_";if(void 0===t)return this[i]||0;if(""===t||"auto"===t)return this[i]=void 0,void this.updateStyleEl_();var n=parseFloat(t);isNaN(n)?h.error('Improper value "'+t+'" supplied for for '+e):(this[i]=n,this.updateStyleEl_())},e.fluid=function(e){var t,i=this;if(void 0===e)return!!this.fluid_;this.fluid_=!!e,it(this)&&this.off(["playerreset","resize"],this.boundUpdateStyleEl_),e?(this.addClass("vjs-fluid"),this.fill(!1),t=function(){i.on(["playerreset","resize"],i.boundUpdateStyleEl_)},it(e=this)?t():(e.eventedCallbacks||(e.eventedCallbacks=[]),e.eventedCallbacks.push(t))):this.removeClass("vjs-fluid"),this.updateStyleEl_()},e.fill=function(e){if(void 0===e)return!!this.fill_;this.fill_=!!e,e?(this.addClass("vjs-fill"),this.fluid(!1)):this.removeClass("vjs-fill")},e.aspectRatio=function(e){if(void 0===e)return this.aspectRatio_;if(!/^\d+\:\d+$/.test(e))throw new Error("Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.");this.aspectRatio_=e,this.fluid(!0),this.updateStyleEl_()},e.updateStyleEl_=function(){var e,t,i,n;!0!==window.VIDEOJS_NO_DYNAMIC_STYLE?(n=(i=(void 0!==this.aspectRatio_&&"auto"!==this.aspectRatio_?this.aspectRatio_:0<this.videoWidth()?this.videoWidth()+":"+this.videoHeight():"16:9").split(":"))[1]/i[0],e=void 0!==this.width_?this.width_:void 0!==this.height_?this.height_/n:this.videoWidth()||300,t=void 0!==this.height_?this.height_:e*n,i=/^[^a-zA-Z]/.test(this.id())?"dimensions-"+this.id():this.id()+"-dimensions",this.addClass(i),Ae(this.styleEl_,"\n      ."+i+" {\n        width: "+e+"px;\n        height: "+t+"px;\n      }\n\n      ."+i+".vjs-fluid {\n        padding-top: "+100*n+"%;\n      }\n    ")):(t="number"==typeof this.width_?this.width_:this.options_.width,i="number"==typeof this.height_?this.height_:this.options_.height,(n=this.tech_&&this.tech_.el())&&
4715(0<=t&&(n.width=t),0<=i&&(n.height=i)))},e.loadTech_=function(e,t){var i=this;this.tech_&&this.unloadTech_();var n=ut(e),r=e.charAt(0).toLowerCase()+e.slice(1);"Html5"!==n&&this.tag&&(ji.getTech("Html5").disposeMediaElement(this.tag),this.tag.player=null,this.tag=null),this.techName_=n,this.isReady_=!1;var a=this.autoplay(),s={source:t,autoplay:a="string"==typeof this.autoplay()||!0===this.autoplay()&&this.options_.normalizeAutoplay?!1:a,nativeControlsForTouch:this.options_.nativeControlsForTouch,playerId:this.id(),techId:this.id()+"_"+r+"_api",playsinline:this.options_.playsinline,preload:this.options_.preload,loop:this.options_.loop,disablePictureInPicture:this.options_.disablePictureInPicture,muted:this.options_.muted,poster:this.poster(),language:this.language(),playerElIngest:this.playerElIngest_||!1,"vtt.js":this.options_["vtt.js"],canOverridePoster:!!this.options_.techCanOverridePoster,enableSourceset:this.options_.enableSourceset,Promise:this.options_.Promise};oi.names.forEach(function(e){e=oi[e];s[e.getterName]=i[e.privateName]}),b(s,this.options_[n]),b(s,this.options_[r]),b(s,this.options_[e.toLowerCase()]),this.tag&&(s.tag=this.tag),t&&t.src===this.cache_.src&&0<this.cache_.currentTime&&(s.startTime=this.cache_.currentTime);e=ji.getTech(e);if(!e)throw new Error("No Tech named '"+n+"' exists! '"+n+"' should be registered using videojs.registerTech()'");this.tech_=new e(s),this.tech_.ready(Ve(this,this.handleTechReady_),!0),It(this.textTracksJson_||[],this.tech_),Rn.forEach(function(t){i.on(i.tech_,t,function(e){return i["handleTech"+ut(t)+"_"](e)})}),Object.keys(Mn).forEach(function(t){i.on(i.tech_,t,function(e){0===i.tech_.playbackRate()&&i.tech_.seeking()?i.queuedCallbacks_.push({callback:i["handleTech"+Mn[t]+"_"].bind(i),event:e}):i["handleTech"+Mn[t]+"_"](e)})}),this.on(this.tech_,"loadstart",function(e){return i.handleTechLoadStart_(e)}),this.on(this.tech_,"sourceset",function(e){return i.handleTechSourceset_(e)}),this.on(this.tech_,"waiting",function(e){return i.handleTechWaiting_(e)}),this.on(this.tech_,"ended",function(e){return i.handleTechEnded_(e)}),this.on(this.tech_,"seeking",function(e){return i.handleTechSeeking_(e)}),this.on(this.tech_,"play",function(e){return i.handleTechPlay_(e)}),this.on(this.tech_,"firstplay",function(e){return i.handleTechFirstPlay_(e)}),this.on(this.tech_,"pause",function(e){return i.handleTechPause_(e)}),this.on(this.tech_,"durationchange",function(e){return i.handleTechDurationChange_(e)}),this.on(this.tech_,"fullscreenchange",function(e,t){return i.handleTechFullscreenChange_(e,t)}),this.on(this.tech_,"fullscreenerror",function(e,t){return i.handleTechFullscreenError_(e,t)}),this.on(this.tech_,"enterpictureinpicture",function(e){return i.handleTechEnterPictureInPicture_(e)}),this.on(this.tech_,"leavepictureinpicture",function(e){return i.handleTechLeavePictureInPicture_(e)}),this.on(this.tech_,"error",function(e){return i.handleTechError_(e)}),this.on(this.tech_,"posterchange",function(e){return i.handleTechPosterChange_(e)}),this.on(this.tech_,"textdata",function(e){return i.handleTechTextData_(e)}),this.on(this.tech_,"ratechange",function(e){return i.handleTechRateChange_(e)}),this.on(this.tech_,"loadedmetadata",this.boundUpdateStyleEl_),this.usingNativeControls(this.techGet_("controls")),this.controls()&&!this.usingNativeControls()&&this.addTechControlsListeners_(),this.tech_.el().parentNode===this.el()||"Html5"===n&&this.tag||Z(this.tech_.el(),this.el()),this.tag&&(this.tag.player=null,this.tag=null)},e.unloadTech_=function(){var t=this;oi.names.forEach(function(e){e=oi[e];t[e.privateName]=t[e.getterName]()}),this.textTracksJson_=Ct(this.tech_),this.isReady_=!1,this.tech_.dispose(),this.tech_=!1,this.isPosterFromTech_&&(this.poster_="",this.trigger("posterchange")),this.isPosterFromTech_=!1},e.tech=function(e){return void 0===e&&h.warn("Using the tech directly can be dangerous. I hope you know 
4715what you're doing.\nSee https://github.com/videojs/video.js/issues/2617 for more info.\n"),this.tech_},e.addTechControlsListeners_=function(){this.removeTechControlsListeners_(),this.on(this.tech_,"click",this.boundHandleTechClick_),this.on(this.tech_,"dblclick",this.boundHandleTechDoubleClick_),this.on(this.tech_,"touchstart",this.boundHandleTechTouchStart_),this.on(this.tech_,"touchmove",this.boundHandleTechTouchMove_),this.on(this.tech_,"touchend",this.boundHandleTechTouchEnd_),this.on(this.tech_,"tap",this.boundHandleTechTap_)},e.removeTechControlsListeners_=function(){this.off(this.tech_,"tap",this.boundHandleTechTap_),this.off(this.tech_,"touchstart",this.boundHandleTechTouchStart_),this.off(this.tech_,"touchmove",this.boundHandleTechTouchMove_),this.off(this.tech_,"touchend",this.boundHandleTechTouchEnd_),this.off(this.tech_,"click",this.boundHandleTechClick_),this.off(this.tech_,"dblclick",this.boundHandleTechDoubleClick_)},e.handleTechReady_=function(){this.triggerReady(),this.cache_.volume&&this.techCall_("setVolume",this.cache_.volume),this.handleTechPosterChange_(),this.handleTechDurationChange_()},e.handleTechLoadStart_=function(){this.removeClass("vjs-ended"),this.removeClass("vjs-seeking"),this.error(null),this.handleTechDurationChange_(),this.paused()?(this.hasStarted(!1),this.trigger("loadstart")):(this.trigger("loadstart"),this.trigger("firstplay")),this.manualAutoplay_(!0===this.autoplay()&&this.options_.normalizeAutoplay?"play":this.autoplay())},e.manualAutoplay_=function(e){var n=this;if(this.tech_&&"string"==typeof e){var t,i=function(){var e=n.muted();n.muted(!0);function t(){n.muted(e)}n.playTerminatedQueue_.push(t);var i=n.play();if(wt(i))return i.catch(function(e){throw t(),new Error("Rejection at manualAutoplay. Restoring muted value. "+(e||""))})};if("any"!==e||this.muted()?t="muted"!==e||this.muted()?this.play():i():wt(t=this.play())&&(t=t.catch(i)),wt(t))return t.then(function(){n.trigger({type:"autoplay-success",autoplay:e})}).catch(function(){n.trigger({type:"autoplay-failure",autoplay:e})})}},e.updateSourceCaches_=function(e){var t=e=void 0===e?"":e,i="";"string"!=typeof t&&(t=e.src,i=e.type),this.cache_.source=this.cache_.source||{},this.cache_.sources=this.cache_.sources||[],t&&!i&&(i=function(e,t){if(!t)return"";if(e.cache_.source.src===t&&e.cache_.source.type)return e.cache_.source.type;var i=e.cache_.sources.filter(function(e){return e.src===t});if(i.length)return i[0].type;for(var n=e.$$("source"),r=0;r<n.length;r++){var a=n[r];if(a.type&&a.src&&a.src===t)return a.type}return $i(t)}(this,t)),this.cache_.source=lt({},e,{src:t,type:i});for(var i=this.cache_.sources.filter(function(e){return e.src&&e.src===t}),n=[],r=this.$$("source"),a=[],s=0;s<r.length;s++){var o=ae(r[s]);n.push(o),o.src&&o.src===t&&a.push(o.src)}a.length&&!i.length?this.cache_.sources=n:i.length||(this.cache_.sources=[this.cache_.source]),this.cache_.src=t},e.handleTechSourceset_=function(e){var t,i,n,r=this;this.changingSrc_||(t=function(e){return r.updateSourceCaches_(e)},i=this.currentSource().src,n=e.src,i&&!/^blob:/.test(i)&&/^blob:/.test(n)&&(this.lastSource_&&(this.lastSource_.tech===n||this.lastSource_.player===i)||(t=function(){})),t(n),e.src||this.tech_.any(["sourceset","loadstart"],function(e){"sourceset"!==e.type&&(e=r.techGet("currentSrc"),r.lastSource_.tech=e,r.updateSourceCaches_(e))})),this.lastSource_={player:this.currentSource().src,tech:e.src},this.trigger({src:e.src,type:"sourceset"})},e.hasStarted=function(e){if(void 0===e)return this.hasStarted_;e!==this.hasStarted_&&(this.hasStarted_=e,this.hasStarted_?(this.addClass("vjs-has-started"),this.trigger("firstplay")):this.removeClass("vjs-has-started"))},e.handleTechPlay_=function(){this.removeClass("vjs-ended"),this.removeClass("vjs-paused"),this.addClass("vjs-playing"),this.hasStarted(!0),this.trigger("play")},e.handleTechRateChange_=function(){0<this.tech_.playbackRate()&&0===this.cache_.lastPlaybackRate&&(this.queuedCallbacks_.forEach(function(e){return e.callback(e.event)}),this.queuedCallbacks_=[]),this.cache_.lastPlaybackRate=this.tech_.playbackRate(),this.trigger("ratechange")},e.handleTechWaiting_=function(){var t=this;this.addClass("vjs-waiting"),this.trigger("waiting");var i=this.currentTime();this.on("timeupdate",function e(){i!==t.currentTime()&&(t.removeClass("vjs-waiting"),t.off("timeupdate",e))})},e.handleTechCanPlay_=function(){this.removeClass("vjs-waiting"),this.trigger("canplay")},e.handleTechCanPlayThrough_=function(){this.removeClass("vjs-waiting"),this.trigger("canplaythrough")},e.handleTechPlaying_=function(){this.removeClass("vjs-waiting"),this.trigger("playing")},e.handleTechSeeking_=function(){this.addClass("vjs-seeking"),this.trigger("seeking")},e.handleTechSeeked_=function(){this.removeClass("vjs-seeking"),this.removeClass("vjs-ended"),this.trigger("seeked")},e.handleTechFirstPlay_=function(){this.options_.starttime&&(h.warn("Passing the `starttime` option to the player will be deprecated 
4715in 6.0"),this.currentTime(this.options_.starttime)),this.addClass("vjs-has-started"),this.trigger("firstplay")},e.handleTechPause_=function(){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.trigger("pause")},e.handleTechEnded_=function(){this.addClass("vjs-ended"),this.removeClass("vjs-waiting"),this.options_.loop?(this.currentTime(0),this.play()):this.paused()||this.pause(),this.trigger("ended")},e.handleTechDurationChange_=function(){this.duration(this.techGet_("duration"))},e.handleTechClick_=function(e){this.controls_&&(void 0!==this.options_&&void 0!==this.options_.userActions&&void 0!==this.options_.userActions.click&&!1===this.options_.userActions.click||(void 0!==this.options_&&void 0!==this.options_.userActions&&"function"==typeof this.options_.userActions.click?this.options_.userActions.click.call(this,e):this.paused()?Et(this.play()):this.pause()))},e.handleTechDoubleClick_=function(t){this.controls_&&(Array.prototype.some.call(this.$$(".vjs-control-bar, .vjs-modal-dialog"),function(e){return e.contains(t.target)})||void 0!==this.options_&&void 0!==this.options_.userActions&&void 0!==this.options_.userActions.doubleClick&&!1===this.options_.userActions.doubleClick||(void 0!==this.options_&&void 0!==this.options_.userActions&&"function"==typeof this.options_.userActions.doubleClick?this.options_.userActions.doubleClick.call(this,t):this.isFullscreen()?this.exitFullscreen():this.requestFullscreen()))},e.handleTechTap_=function(){this.userActive(!this.userActive())},e.handleTechTouchStart_=function(){this.userWasActive=this.userActive()},e.handleTechTouchMove_=function(){this.userWasActive&&this.reportUserActivity()},e.handleTechTouchEnd_=function(e){e.cancelable&&e.preventDefault()},e.handleStageClick_=function(){this.reportUserActivity()},e.toggleFullscreenClass_=function(){this.isFullscreen()?this.addClass("vjs-fullscreen"):this.removeClass("vjs-fullscreen")},e.documentFullscreenChange_=function(e){var t=e.target.player;t&&t!==this||(e=this.el(),!(t=document[this.fsApi_.fullscreenElement]===e)&&e.matches?t=e.matches(":"+this.fsApi_.fullscreen):!t&&e.msMatchesSelector&&(t=e.msMatchesSelector(":"+this.fsApi_.fullscreen)),this.isFullscreen(t))},e.handleTechFullscreenChange_=function(e,t){var i=this;t&&(t.nativeIOSFullscreen&&(this.addClass("vjs-ios-native-fs"),this.tech_.one("webkitendfullscreen",function(){i.removeClass("vjs-ios-native-fs")})),this.isFullscreen(t.isFullscreen))},e.handleTechFullscreenError_=function(e,t){this.trigger("fullscreenerror",t)},e.togglePictureInPictureClass_=function(){this.isInPictureInPicture()?this.addClass("vjs-picture-in-picture"):this.removeClass("vjs-picture-in-picture")},e.handleTechEnterPictureInPicture_=function(e){this.isInPictureInPicture(!0)},e.handleTechLeavePictureInPicture_=function(e){this.isInPictureInPicture(!1)},e.handleTechError_=function(){var e=this.tech_.error();this.error(e)},e.handleTechTextData_=function(){this.trigger("textdata",1<arguments.length?arguments[1]:null)},e.getCache=function(){return this.cache_},e.resetCache_=function(){this.cache_={currentTime:0,initTime:0,inactivityTimeout:this.options_.inactivityTimeout,duration:NaN,lastVolume:1,lastPlaybackRate:this.defaultPlaybackRate(),media:null,src:"",source:{},sources:[],playbackRates:[],volume:1}},e.techCall_=function(n,r){this.ready(function(){if(n in Xi)return e=this.middleware_,t=this.tech_,i=r,t[t=n](e.reduce(Yi(t),i));if(n in Ki)return Gi(this.middleware_,this.tech_,n,r);var e,t,i;try{this.tech_&&this.tech_[n](r)}catch(e){throw h(e),e}},!0)},e.techGet_=function(t){if(this.tech_&&this.tech_.isReady_){if(t in zi)return e=this.middleware_,i=this.tech_,n=t,e.reduceRight(Yi(n),i[n]());if(t in Ki)return Gi(this.middleware_,this.tech_,t);var e,i,n;try{return this.tech_[t]()}catch(e){if(void 0===this.tech_[t])throw h("Video.js: "+t+" method not defined for "+this.techName_+" playback technology.",e),e;if("TypeError"===e.name)throw h("Video.js: "+t+" unavailable on "+this.techName_+" playback technology element.",e),this.tech_.isReady_=!1,e;throw h(e),e}}},e.play=function(){var t=this,e=this.options_.Promise||window.Promise;return e?new e(function(e){t.play_(e)}):this.play_()},e.play_=function(e){var t=this;this.playCallbacks_.push(e=void 0===e?Et:e);e=Boolean(!this.changingSrc_&&(this.src()||this.currentSrc()));if(this.waitToPlay_&&(this.off(["ready","loadstart"],this.waitToPlay_),this.waitToPlay_=null),!this.isReady_||!e)return this.waitToPlay_=function(e){t.play_()},this.one(["ready","loadstart"],this.waitToPlay_),void(e||!V&&!q||this.load());e=this.techGet_("play");null===e?this.runPlayTerminatedQueue_():this.runPlayCallbacks_(e)},e.runPlayTerminatedQueue_=function(){var e=this.playTerminatedQueue_.slice(0);this.playTerminatedQueue_=[],e.forEach(function(e){e()})},e.runPlayCallbacks_=function(t){var e=this.playCallbacks_.slice(0);this.playCallbacks_=[],this.playTerminatedQueue_=[],e.forEach(function(e){e(t)})},e.pause=function(){this.techCall_("pause")},e.paused=function(){return!1!==this.techGet_("paused")},e.played=function(){return this.techGet_("played")||vt(0,0)},e.scrubbing=function(e){if("undefined"==typeof e)return this.scrubbing_;this.scrubbing_=!!e,this.techCall_("setScrubbing",this.scrubbing_),e?this.addClass("vjs-scrubbing"):this.removeClass("vjs-scrubbing")},e.currentTime=function(e){return"undefined"!=typeof e?(e<0&&(e=0),this.isReady_&&!this.changingSrc_&&this.tech_&&this.tech_.isReady_?(this.techCall_("setCurrentTime",e),void(this.cache_.initTime=0)):(this.cache_.initTime=e,this.off("canplay",this.boundApplyInitTime_),void this.one("canplay",this.boundApplyInitTime_))):(this.cache_.currentTime=this.techGet_("currentTime")||0,this.cache_.currentTime)},e.applyInitTime_=function(){this.currentTime(this.cache_.initTime)},e.duration=function(e){if(void 0===e)return void 0!==this.cache_.duration?this.cache_.duration:NaN;(e=(e=parseFloat(e))<0?1/0:e)!==this.cache_.duration&&((this.cache_.duration=e)===1/0?this.addClass("vjs-live"):this.removeClass("vjs-live"),isNaN(e)||this.trigger("durationchange"))},e.remainingTime=function(){return this.duration()-this.currentTime()},e.remainingTimeDisplay=function(){return Math.floor(this.duration())-Math.floor(this.currentTime())},e.buffered=function(){var e;return e=!(e=this.techGet_("buffered"))||!e.length?vt(0,0):e},e.bufferedPercent=function(){return _t(this.buffered(),this.duration())},e.bufferedEnd=function(){var e=this.buffered(),t=this.duration(),e=e.end(e.length-1);return e=t<e?t:e},e.volume=function(e){var t;return void 0!==e?(t=Math.max(0,Math.min(1,parseFloat(e))),this.cache_.volume=t,this.techCall_("setVolume",t),void(0<t&&this.lastVolume_(t))):(t=parseFloat(this.techGet_("volume")),isNaN(t)?1:t)},e.muted=function(e){if(void 0===e)return this.techGet_("muted")||!1;this.techCall_("setMuted",e)},e.defaultMuted=function(e){return void 0!==e?this.techCall_("setDefaultMuted",e):this.techGet_("defaultMuted")||!1},e.lastVolume_=function(e){if(void 0===e||0===e)return this.cache_.lastVolume;this.cache_.lastVolume=e},e.supportsFullScreen=function(){return this.techGet_("supportsFullScreen")||!1},e.isFullscreen=function(e){if(void 0===e)return this.isFullscreen_;var t=this.isFullscreen_;this.isFullscreen_=Boolean(e),this.isFullscreen_!==t&&this.fsApi_.prefixed&&this.trigger("fullscreenchange"),this.toggleFullscreenClass_()},e.requestFullscreen=function(s){var e=this.options_.Promise||window.Promise;if(e){var o=this;return new e(function(e,i){function n(){o.off("fullscreenerror",r),o.off("fullscreenchange",t)}function t(){n(),e()}function r(e,t){n(),i(t)}o.one("fullscreenchange",t),o.one("fullscreenerror",r);var a=o.requestFullscreenHelper_(s);a&&(a.then(n,n),a.then(e,i))})}return this.requestFullscreenHelper_()},e.requestFullscreenHelper_=function(e){var t=this;if(this.fsApi_.prefixed||(i=this.options_.fullscreen&&this.options_.fullscreen.options||{},void 0!==e&&(i=e)),this.fsApi_.requestFullscreen){var i=this.el_[this.fsApi_.requestFullscreen](i);return i&&i.then(function(){return t.isFullscreen(!0)},function(){return t.isFullscreen(!1)}),i}this.tech_.supportsFullScreen()&&!0==!this.options_.preferFullWindow?this.techCall_("enterFullScreen"):this.enterFullWindow()},e.exitFullscreen=function(){var e=this.options_.Promise||window.Promise;if(e){var s=this;return new e(function(e,i){function n(){s.off("fullscreenerror",r),s.off("fullscreenchange",t)}function t(){n(),e()}function r(e,t){n(),i(t)}s.one("fullscreenchange",t),s.one("fullscreenerror",r);var a=s.exitFullscreenHelper_();a&&(a.then(n,n),a.then(e,i))})}return this.exitFullscreenHelper_()},e.exitFullscreenHelper_=function(){var e=this;if(this.fsApi_.requestFullscreen){var t=document[this.fsApi_.exitFullscreen]();return t&&Et(t.then(function(){return e.isFullscreen(!1)})),t}this.tech_.supportsFullScreen()&&!0==!this.options_.preferFullWindow?this.techCall_("exitFullScreen"):this.exitFullWindow()},e.enterFullWindow=function(){this.isFullscreen(!0),this.isFullWindow=!0,this.docOrigOverflow=document.documentElement.style.overflow,Be(document,"keydown",this.boundFullWindowOnEscKey_),document.documentElement.style.overflow="hidden",te(document.body,"vjs-full-window"),this.trigger("enterFullWindow")},e.fullWindowOnEscKey=function(e){ht.isEventKey(e,"Esc")&&!0===this.isFullscreen()&&(this.isFullWindow?this.exitFullWindow():this.exitFullscreen())},e.exitFullWindow=function(){this.isFullscreen(!1),this.isFullWindow=!1,Fe(document,"keydown",this.boundFullWindowOnEscKey_),document.documentElement.style.overflow=this.docOrigOverflow,ie(document.body,"vjs-full-window"),this.trigger("exitFullWindow")},e.disablePictureInPicture=function(e){if(void 0===e)return this.techGet_("disablePictureInPicture");this.techCall_("setDisablePictureInPicture",e),this.options_.disablePictureInPicture=e,this.trigger("disablepictureinpicturechanged")},e.isInPictureInPicture=function(e){return void 0!==e?(this.isInPictureInPicture_=!!e,void this.togglePictureInPictureClass_()):!!this.isInPictureInPicture_},e.requestPictureInPicture=function(){if("pictureInPictureEnabled"in document&&!1===this.disablePictureInPicture())return this.techGet_("requestPictureInPicture")},e.exitPictureInPicture=function(){if("pictureInPictureEnabled"in document)return document.exitPictureInPicture()},e.handleKeyDown=function(e){var t=this.options_.userActions;t&&t.hotkeys&&(function(e){var t=e.tagName.toLowerCase();if(e.isContentEditable)return!0;
4715if("input"===t)return-1===["button","checkbox","hidden","radio","reset","submit"].indexOf(e.type);return-1!==["textarea"].indexOf(t)}(this.el_.ownerDocument.activeElement)||("function"==typeof t.hotkeys?t.hotkeys.call(this,e):this.handleHotkeys(e)))},e.handleHotkeys=function(e){var t=this.options_.userActions?this.options_.userActions.hotkeys:{},i=t.fullscreenKey,n=t.muteKey,n=void 0===n?function(e){return ht.isEventKey(e,"m")}:n,t=t.playPauseKey,t=void 0===t?function(e){return ht.isEventKey(e,"k")||ht.isEventKey(e,"Space")}:t;(void 0===i?function(e){return ht.isEventKey(e,"f")}:i).call(this,e)?(e.preventDefault(),e.stopPropagation(),i=pt.getComponent("FullscreenToggle"),!1!==document[this.fsApi_.fullscreenEnabled]&&i.prototype.handleClick.call(this,e)):n.call(this,e)?(e.preventDefault(),e.stopPropagation(),pt.getComponent("MuteToggle").prototype.handleClick.call(this,e)):t.call(this,e)&&(e.preventDefault(),e.stopPropagation(),pt.getComponent("PlayToggle").prototype.handleClick.call(this,e))},e.canPlayType=function(e){for(var t,i=0,n=this.options_.techOrder;i<n.length;i++){var r=n[i],a=ji.getTech(r);if(a=a||pt.getComponent(r)){if(a.isSupported()&&(t=a.canPlayType(e)))return t}else h.error('The "'+r+'" tech is undefined. Skipped browser support check for that tech.')}return""},e.selectSource=function(e){function t(e,i,n){var r;return e.some(function(t){return i.some(function(e){if(r=n(t,e))return!0})}),r}var i,n=this,r=this.options_.techOrder.map(function(e){return[e,ji.getTech(e)]}).filter(function(e){var t=e[0],e=e[1];return e?e.isSupported():(h.error('The "'+t+'" tech is undefined. Skipped browser support check for that tech.'),!1)}),a=function(e,t){var i=e[0];if(e[1].canPlaySource(t,n.options_[i.toLowerCase()]))return{source:t,tech:i}},a=this.options_.sourceOrder?t(e,r,(i=a,function(e,t){return i(t,e)})):t(r,e,a);return a||!1},e.handleSrc_=function(e,n){var r=this;if("undefined"==typeof e)return this.cache_.src||"";this.resetRetryOnError_&&this.resetRetryOnError_();var t,i,a=Ji(e);a.length?(this.changingSrc_=!0,n||(this.cache_.sources=a),this.updateSourceCaches_(a[0]),Wi(this,a[0],function(e,t){var i;return r.middleware_=t,n||(r.cache_.sources=a),r.updateSourceCaches_(e),r.src_(e)?1<a.length?r.handleSrc_(a.slice(1)):(r.changingSrc_=!1,r.setTimeout(function(){this.error({code:4,message:this.localize(this.options_.notSupportedMessage)})},0),void r.triggerReady()):(t=t,i=r.tech_,void t.forEach(function(e){return e.setTech&&e.setTech(i)}))}),this.options_.retryOnError&&1<a.length&&(i=function(){r.off("error",t)},this.one("error",t=function(){r.error(null),r.handleSrc_(a.slice(1),!0)}),this.one("playing",i),this.resetRetryOnError_=function(){r.off("error",t),r.off("playing",i)})):this.setTimeout(function(){this.error({code:4,message:this.localize(this.options_.notSupportedMessage)})},0)},e.src=function(e){return this.handleSrc_(e,!1)},e.src_=function(e){var t,i,n=this,r=this.selectSource([e]);return!r||(t=r.tech,i=this.techName_,ut(t)!==ut(i)?(this.changingSrc_=!0,this.loadTech_(r.tech,r.source),this.tech_.ready(function(){n.changingSrc_=!1})):this.ready(function(){this.tech_.constructor.prototype.hasOwnProperty("setSource")?this.techCall_("setSource",e):this.techCall_("src",e.src),this.changingSrc_=!1},!0),!1)},e.load=function(){this.techCall_("load")},e.reset=function(){var e=this,t=this.options_.Promise||window.Promise;this.paused()||!t?this.doReset_():Et(this.play().then(function(){return e.doReset_()}))},e.doReset_=function(){this.tech_&&this.tech_.clearTracks("text"),this.resetCache_(),this.poster(""),this.loadTech_(this.options_.techOrder[0],null),this.techCall_("reset"),this.resetControlBarUI_(),it(this)&&this.trigger("playerreset")},e.resetControlBarUI_=function(){this.resetProgressBar_(),this.resetPlaybackRate_(),this.resetVolumeBar_()},e.resetProgressBar_=function(){this.currentTime(0);var e=this.controlBar,t=e.durationDisplay,e=e.remainingTimeDisplay;t&&t.updateContent(),e&&e.updateContent()},e.resetPlaybackRate_=function(){this.playbackRate(this.defaultPlaybackRate()),this.handleTechRateChange_()},e.resetVolumeBar_=function(){this.volume(1),this.trigger("volumechange")},e.currentSources=function(){var e=this.currentSource(),t=[];return 0!==Object.keys(e).length&&t.push(e),this.cache_.sources||t},e.currentSource=function(){return this.cache_.source||{}},e.currentSrc=function(){return this.currentSource()&&this.currentSource().src||""},e.currentType=function(){return this.currentSource()&&this.currentSource().type||""},e.preload=function(e){return void 0!==e?(this.techCall_("setPreload",e),void(this.options_.preload=e)):this.techGet_("preload")},e.autoplay=function(e){if(void 0===e)return this.options_.autoplay||!1;var t;"string"==typeof e&&/(any|play|muted)/.test(e)||!0===e&&this.options_.normalizeAutoplay?(this.options_.autoplay=e,this.manualAutoplay_("string"==typeof e?e:"play"),t=!1):this.options_.autoplay=!!e,t="undefined"==typeof t?this.options_.autoplay:t,this.tech_&&this.techCall_("setAutoplay",t)},e.playsinline=function(e){return void 0!==e?(this.techCall_("setPlaysinline",e),this.options_.playsinline=e,this):this.techGet_("playsinline")},e.loop=function(e){return void 0!==e?(this.techCall_("setLoop",e),void(this.options_.loop=e)):this.techGet_("loop")},e.poster=function(e){if(void 0===e)return this.poster_;(e=e||"")!==this.poster_&&(this.poster_=e,this.techCall_("setPoster",e),this.isPosterFromTech_=!1,this.trigger("posterchange"))},e.handleTechPosterChange_=function(){var e;this.poster_&&!this.options_.techCanOverridePoster||!this.tech_||!this.tech_.poster||(e=this.tech_.poster()||"")!==this.poster_&&(this.poster_=e,this.isPosterFromTech_=!0,this.trigger("posterchange"))},e.controls=function(e){if(void 0===e)return!!this.controls_;this.controls_!==(e=!!e)&&(this.controls_=e,this.usingNativeControls()&&this.techCall_("setControls",e),this.controls_?(this.removeClass("vjs-controls-disabled"),this.addClass("vjs-controls-enabled"),this.trigger("controlsenabled"),this.usingNativeControls()||this.addTechControl
4715sListeners_()):(this.removeClass("vjs-controls-enabled"),this.addClass("vjs-controls-disabled"),this.trigger("controlsdisabled"),this.usingNativeControls()||this.removeTechControlsListeners_()))},e.usingNativeControls=function(e){if(void 0===e)return!!this.usingNativeControls_;this.usingNativeControls_!==(e=!!e)&&(this.usingNativeControls_=e,this.usingNativeControls_?(this.addClass("vjs-using-native-controls"),this.trigger("usingnativecontrols")):(this.removeClass("vjs-using-native-controls"),this.trigger("usingcustomcontrols")))},e.error=function(t){var i=this;if(void 0===t)return this.error_||null;if(a("beforeerror").forEach(function(e){e=e(i,t);T(e)&&!Array.isArray(e)||"string"==typeof e||"number"==typeof e||null===e?t=e:i.log.error("please return a value that MediaError expects in beforeerror hooks")}),this.options_.suppressNotSupportedError&&t&&4===t.code){var e=function(){this.error(t)};return this.options_.suppressNotSupportedError=!1,this.any(["click","touchstart"],e),void this.one("loadstart",function(){this.off(["click","touchstart"],e)})}if(null===t)return this.error_=t,this.removeClass("vjs-error"),void(this.errorDisplay&&this.errorDisplay.close());this.error_=new bt(t),this.addClass("vjs-error"),h.error("(CODE:"+this.error_.code+" "+bt.errorTypes[this.error_.code]+")",this.error_.message,this.error_),this.trigger("error"),a("error").forEach(function(e){return e(i,i.error_)})},e.reportUserActivity=function(e){this.userActivity_=!0},e.userActive=function(e){if(void 0===e)return this.userActive_;if((e=!!e)!==this.userActive_){if(this.userActive_=e,this.userActive_)return this.userActivity_=!0,this.removeClass("vjs-user-inactive"),this.addClass("vjs-user-active"),void this.trigger("useractive");this.tech_&&this.tech_.one("mousemove",function(e){e.stopPropagation(),e.preventDefault()}),this.userActivity_=!1,this.removeClass("vjs-user-active"),this.addClass("vjs-user-inactive"),this.trigger("userinactive")}},e.listenForUserActivity_=function(){var t,i,n,r=Ve(this,this.reportUserActivity),e=function(e){r(),this.clearInterval(t)};this.on("mousedown",function(){r(),this.clearInterval(t),t=this.setInterval(r,250)}),this.on("mousemove",function(e){e.screenX===i&&e.screenY===n||(i=e.screenX,n=e.screenY,r())}),this.on("mouseup",e),this.on("mouseleave",e);var a,e=this.getChild("controlBar");!e||q||A||(e.on("mouseenter",function(e){0!==this.player().options_.inactivityTimeout&&(this.player().cache_.inactivityTimeout=this.player().options_.inactivityTimeout),this.player().options_.inactivityTimeout=0}),e.on("mouseleave",function(e){this.player().options_.inactivityTimeout=this.player().cache_.inactivityTimeout})),this.on("keydown",r),this.on("keyup",r),this.setInterval(function(){var e;this.userActivity_&&(this.userActivity_=!1,this.userActive(!0),this.clearTimeout(a),(e=this.options_.inactivityTimeout)<=0||(a=this.setTimeout(function(){this.userActivity_||this.userActive(!1)},e)))},250)},e.playbackRate=function(e){if(void 0===e)return this.tech_&&this.tech_.featuresPlaybackRate?this.cache_.lastPlaybackRate||this.techGet_("playbackRate"):1;this.techCall_("setPlaybackRate",e)},e.defaultPlaybackRate=function(e){return void 0!==e?this.techCall_("setDefaultPlaybackRate",e):this.tech_&&this.tech_.featuresPlaybackRate?this.techGet_("defaultPlaybackRate"):1},e.isAudio=function(e){if(void 0===e)return!!this.isAudio_;this.isAudio_=!!e},e.addTextTrack=function(e,t,i){if(this.tech_)return this.tech_.addTextTrack(e,t,i)},e.addRemoteTextTrack=function(e,t){if(this.tech_)return this.tech_.addRemoteTextTrack(e,t)},e.removeRemoteTextTrack=function(e){var t=(t=(e=void 0===e?{}:e).track)||e;if(this.tech_)return this.tech_.removeRemoteTextTrack(t)},e.getVideoPlaybackQuality=function(){return this.techGet_("getVideoPlaybackQuality")},e.videoWidth=function(){return this.tech_&&this.tech_.videoWidth&&this.tech_.videoWidth()||0},e.videoHeight=function(){return this.tech_&&this.tech_.videoHeight&&this.tech_.videoHeight()||0},e.language=function(e){if(void 0===e)return this.language_;this.language_!==String(e).toLowerCase()&&(this.language_=String(e).toLowerCase(),it
vendor: 4,295 bytes, line 4715
4715(this)&&this.trigger("languagechange"))},e.languages=function(){return lt(o.prototype.options_.languages,this.languages_)},e.toJSON=function(){var e=lt(this.options_),t=e.tracks;e.tracks=[];for(var i=0;i<t.length;i++){var n=t[i];(n=lt(n)).player=void 0,e.tracks[i]=n}return e},e.createModal=function(e,t){var i=this;(t=t||{}).content=e||"";var n=new At(this,t);return this.addChild(n),n.on("dispose",function(){i.removeChild(n)}),n.open(),n},e.updateCurrentBreakpoint_=function(){if(this.responsive())for(var e=this.currentBreakpoint(),t=this.currentWidth(),i=0;i<Nn.length;i++){var n=Nn[i];if(t<=this.breakpoints_[n]){if(e===n)return;e&&this.removeClass(Un[e]),this.addClass(Un[n]),this.breakpoint_=n;break}}},e.removeCurrentBreakpoint_=function(){var e=this.currentBreakpointClass();this.breakpoint_="",e&&this.removeClass(e)},e.breakpoints=function(e){return void 0===e||(this.breakpoint_="",this.breakpoints_=b({},Bn,e),this.updateCurrentBreakpoint_()),b(this.breakpoints_)},e.responsive=function(e){return void 0===e?this.responsive_:(e=Boolean(e))!==this.responsive_?((this.responsive_=e)?(this.on("playerresize",this.boundUpdateCurrentBreakpoint_),this.updateCurrentBreakpoint_()):(this.off("playerresize",this.boundUpdateCurrentBreakpoint_),this.removeCurrentBreakpoint_()),e):void 0},e.currentBreakpoint=function(){return this.breakpoint_},e.currentBreakpointClass=function(){return Un[this.breakpoint_]||""},e.loadMedia=function(e,t){var i,n,r,a=this;e&&"object"==typeof e&&(this.reset(),this.cache_.media=lt(e),i=(r=this.cache_.media).artwork,n=r.poster,e=r.src,r=r.textTracks,!i&&n&&(this.cache_.media.artwork=[{src:n,type:$i(n)}]),e&&this.src(e),n&&this.poster(n),Array.isArray(r)&&r.forEach(function(e){return a.addRemoteTextTrack(e,!1)}),this.ready(t))},e.getMedia=function(){if(this.cache_.media)return lt(this.cache_.media);var e=this.poster(),t={src:this.currentSources(),textTracks:Array.prototype.map.call(this.remoteTextTracks(),function(e){return{kind:e.kind,label:e.label,language:e.language,src:e.src}})};return e&&(t.poster=e,t.artwork=[{src:t.poster,type:$i(t.poster)}]),t},o.getTagSettings=function(e){var t,i={sources:[],tracks:[]},n=ae(e),r=n["data-setup"];if(ee(e,"vjs-fill")&&(n.fill=!0),ee(e,"vjs-fluid")&&(n.fluid=!0),null!==r&&(r=(t=St(r||"{}"))[0],t=t[1],r&&h.error(r),b(n,t)),b(i,n),e.hasChildNodes())for(var a=e.childNodes,s=0,o=a.length;s<o;s++){var u=a[s],l=u.nodeName.toLowerCase();"source"===l?i.sources.push(ae(u)):"track"===l&&i.tracks.push(ae(u))}return i},e.flexNotSupported_=function(){var e=document.createElement("i");return!("flexBasis"in e.style||"webkitFlexBasis"in e.style||"mozFlexBasis"in e.style||"msFlexBasis"in e.style||"msFlexOrder"in e.style)},e.debug=function(e){if(void 0===e)return this.debugEnabled_;e?(this.trigger("debugon"),this.previousLogLevel_=this.log.level,this.log.level("debug"),this.debugEnabled_=!0):(this.trigger("debugoff"),this.log.level(this.previousLogLevel_),this.previousLogLevel_=void 0,this.debugEnabled_=!1)},e.playbackRates=function(e){if(void 0===e)return this.cache_.playbackRates;Array.isArray(e)&&e.every(function(e){return"number"==typeof e})&&(this.cache_.playbackRates=e,this.trigger("playbackrateschange"))},o}(pt);oi.names.forEach(function(e){var t=oi[e];Fn.prototype[t.getterName]=function(){return this.tech_?this.tech_[t.getterName]():(this[t.privateName]=this[t.privateName]||new t.ListClass,this[t.privateName])}}),Fn.prototype.crossorigin=Fn.prototype.crossOrigin,Fn.players={};k=window.navigator;Fn.prototype.options_={techOrder:ji.defaultTechOrder_,html5:{},inactivityTimeout:2e3,playbackRates:[],liveui:!1,children:["mediaLoader","posterImage","textTrackDisplay","loadingSpinner","bigPlayButton","liveTracker","controlBar","errorDisplay","textTrackSettings","resizeManager"],language:k&&(k.languages&&k.languages[0]||k.userLanguage||k.language)||"en",languages:{},notSupportedMessage:"No compatible source was found for this media.",normalizeAutoplay:!1,fullscreen:{options:{navigationUI:"hide"}},breakpoints:{},responsive:!1},["ended","seeking","seekable","networkState","readyState"].forEach(function(e){Fn.prototype[e]=function(){return this.techGet_(e)}}),Rn.forEach(function(e){Fn.prototype["handleTech"+ut(e)+"_"]=function(){return this.trigger(e)}}),pt.registerComponent("Player",Fn);
4715var jn=m(function(i){function n(e,t){return i.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(e,t)}i.exports=n});function Hn(e){return Qn.hasOwnProperty(e)}function qn(e){return Hn(e)?Qn[e]:void 0}function Vn(e,t,i){i=(i?"before":"")+"pluginsetup",e.trigger(i,t),e.trigger(i+":"+t.name,t)}function Wn(t,i){function n(){Vn(this,{name:t,plugin:i,instance:null},!0);var e=i.apply(this,arguments);return $n(this,t),Vn(this,{name:t,plugin:i,instance:e}),e}return Object.keys(i).forEach(function(e){n[e]=i[e]}),n}function Gn(r,a){return a.prototype.name=r,function(){Vn(this,{name:r,plugin:a,instance:null},!0);for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];var n=Xn(a,[this].concat(t));return this[r]=function(){return n},Vn(this,n.getEventHash()),n}}var zn=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}},Xn=m(function(n){function r(e,t,i){return zn()?n.exports=r=Reflect.construct:n.exports=r=function(e,t,i){var n=[null];n.push.apply(n,t);n=new(Function.bind.apply(e,n));return i&&jn(n,i.prototype),n},r.apply(null,arguments)}n.exports=r}),Kn="plugin",Yn="activePlugins_",Qn={},$n=function(e,t){e[Yn]=e[Yn]||{},e[Yn][t]=!0},Jn=function(){function i(e){if(this.constructor===i)throw new Error("Plugin must be sub-classed; not directly instantiated.");this.player=e,this.log||(this.log=this.player.log.createLogger(this.name)),rt(this),delete this.trigger,st(this,this.constructor.defaultState),$n(e,this.name),this.dispose=this.dispose.bind(this),e.on("dispose",this.dispose)}var e=i.prototype;return e.version=function(){return this.constructor.VERSION},e.getEventHash=function(e){return(e=void 0===e?{}:e).name=this.name,e.plugin=this.constructor,e.instance=this,e},e.trigger=function(e,t){return je(this.eventBusEl_,e,this.getEventHash(t=void 0===t?{}:t))},e.handleStateChanged=function(e){},e.dispose=function(){var e=this.name,t=this.player;this.trigger("dispose"),this.off(),t.off("dispose",this.dispose),t[Yn][e]=!1,this.player=this.state=null,t[e]=Gn(e,Qn[e])},i.isBasic=function(e){e="string"==typeof e?qn(e):e;return"function"==typeof e&&!i.prototype.isPrototypeOf(e.prototype)},i.registerPlugin=function(e,t){if("string"!=typeof e)throw new Error('Illegal plugin name, "'+e+'", must be a string, was '+typeof e+".");if(Hn(e))h.warn('A plugin named "'+e+'" already exists. You may want to avoid re-registering plugins!');else if(Fn.prototype.hasOwnProperty(e))throw new Error('Illegal plugin name, "'+e+'", cannot share a name with an existing player method!');if("function"!=typeof t)throw new Error('Illegal plugin for "'+e+'", must be a function, was '+typeof t+".");return Qn[e]=t,e!==Kn&&(i.isBasic(t)?Fn.prototype[e]=Wn(e,t):Fn.prototype[e]=Gn(e,t)),t},i.deregisterPlugin=function(e){if(e===Kn)throw new Error("Cannot de-register base plugin.");Hn(e)&&(delete Qn[e],delete Fn.prototype[e])},i.getPlugins=function(e){var i;return(e=void 0===e?Object.keys(Qn):e).forEach(function(e){var t=qn(e);t&&((i=i||{})[e]=t)}),i},i.getPluginVersion=function(e){e=qn(e);return e&&e.VERSION||""},i}();Jn.getPlugin=qn,Jn.BASE_PLUGIN_NAME=Kn,Jn.registerPlugin(Kn,Jn),Fn.prototype.usingPlugin=function(e){return!!this[Yn]&&!0===this[Yn][e]},Fn.prototype.hasPlugin=function(e){return!!Hn(e)};var Zn=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&jn(e,t)},er=function(e){return 0===e.indexOf("#")?e.slice(1):e};function tr(e,t,i){if(r=tr.getPlayer(e))return t&&h.warn('Player "'+e+'" is already initialised. Options will not be applied.'),i&&r.ready(i),r;var n="string"==typeof e?Te("#"+er(e)):e;if(!K(n))throw new TypeError("The element or ID supplied is not valid. (videojs)");n.ownerDocument.defaultView&&n.ownerDocument.body.contains(n)||h.warn("The element supplied is not included in the DOM"),t=t||{},a("beforesetup").forEach(function(e){e=e(n,lt(t));
4715T(e)&&!Array.isArray(e)?t=lt(t,e):h.error("please return an object in beforesetup hooks")});var r=new(pt.getComponent("Player"))(n,t,i);return a("setup").forEach(function(e){return e(r)}),r}tr.hooks_=i,tr.hooks=a,tr.hook=function(e,t){a(e,t)},tr.hookOnce=function(i,e){a(i,[].concat(e).map(function(t){return function e(){return n(i,e),t.apply(void 0,arguments)}}))},tr.removeHook=n,!0!==window.VIDEOJS_NO_DYNAMIC_STYLE&&X()&&((ar=Te(".vjs-styles-defaults"))||(ar=xe("vjs-styles-defaults"),(k=Te("head"))&&k.insertBefore(ar,k.firstChild),Ae(ar,"\n      .video-js {\n        width: 300px;\n        height: 150px;\n      }\n\n      .vjs-fluid {\n        padding-top: 56.25%\n      }\n    "))),Ce(1,tr),tr.VERSION=u,tr.options=Fn.prototype.options_,tr.getPlayers=function(){return Fn.players},tr.getPlayer=function(e){var t=Fn.players;if("string"==typeof e){var i=er(e),n=t[i];if(n)return n;i=Te("#"+i)}else i=e;if(K(i)){e=i.player,i=i.playerId;if(e||t[i])return e||t[i]}},tr.getAllPlayers=function(){return Object.keys(Fn.players).map(function(e){return Fn.players[e]}).filter(Boolean)},tr.players=Fn.players,tr.getComponent=pt.getComponent,tr.registerComponent=function(e,t){ji.isTech(t)&&h.warn("The "+e+" tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)"),pt.registerComponent.call(pt,e,t)},tr.getTech=ji.getTech,tr.registerTech=ji.registerTech,tr.use=function(e,t){Hi[e]=Hi[e]||[],Hi[e].push(t)},Object.defineProperty(tr,"middleware",{value:{},writeable:!1,enumerable:!0}),Object.defineProperty(tr.middleware,"TERMINATOR",{value:Vi,writeable:!1,enumerable:!0}),tr.browser=W,tr.TOUCH_ENABLED=F,tr.extend=function(e,t){var i,n=function(){e.apply(this,arguments)},r={};for(i in"object"==typeof(t=void 0===t?{}:t)?(t.constructor!==Object.prototype.constructor&&(n=t.constructor),r=t):"function"==typeof t&&(n=t),Zn(n,e),e&&(n.super_=e),r)r.hasOwnProperty(i)&&(n.prototype[i]=r[i]);return n},tr.mergeOptions=lt,tr.bind=Ve,tr.registerPlugin=Jn.registerPlugin,tr.deregisterPlugin=Jn.deregisterPlugin,tr.plugin=function(e,t){return h.warn("videojs.plugin() is deprecated; use videojs.registerPlugin() instead"),Jn.registerPlugin(e,t)},tr.getPlugins=Jn.getPlugins,tr.getPlugin=Jn.getPlugin,tr.getPluginVersion=Jn.getPluginVersion,tr.addLanguage=function(e,t){var i;return e=(""+e).toLowerCase(),tr.options.languages=lt(tr.options.languages,((i={})[e]=t,i)),tr.options.languages[e]},tr.log=h,tr.createLogger=p,tr.createTimeRange=tr.createTimeRanges=vt,tr.formatTime=ln,tr.setFormatTime=function(e){un=e},tr.resetFormatTime=function(){un=on},tr.parseUrl=Rt,tr.isCrossOrigin=Ut,tr.EventTarget=ze,tr.on=Be,tr.one=He,tr.off=Fe,tr.trigger=je,tr.xhr=Jt,tr.TextTrack=ri,tr.AudioTrack=x,tr.VideoTrack=U,["isEl","isTextNode","createEl","hasClass","addClass","removeClass","toggleClass","setAttributes","getAttributes","emptyEl","appendContent","insertContent"].forEach(function(e){tr[e]=function(){return h.warn("videojs."+e+"() is deprecated; use videojs.dom."+e+"() instead"),we[e].apply(null,arguments)}}),tr.computedStyle=w,tr.dom=we,tr.url=zt,tr.defineLazyProperty=An,tr.addLanguage("en",{"Non-Fullscreen":"Exit Fullscreen"});function ir(e,t){if(/^[a-z]+:/i.test(t))return t;/^data:/.test(e)&&(e=window.location&&window.location.href||"");var i="function"==typeof window.URL,n=/^\/\//.test(e),r=!window.location&&!/\/\//i.test(e);if(i?e=new window.URL(e,window.location||rr):/\/\//i.test(e)||(e=nr.buildAbsoluteURL(window.location&&window.location.href||"",e)),i){i=new URL(t,e);return r?i.href.slice(rr.length):n?i.href.slice(i.protocol.length):i.href}return nr.buildAbsoluteURL(e,t)}var nr=m(function(e,t){var i,a,n,r,s;i=/^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/?#]*\/)*[^;?#]*)?(;[^?#]*)?(\?[^#]*)?(#[^]*)?$/,a=/^([^\/?#]*)([^]*)$/,n=/(?:\/|^)\.(?=\/)/g,r=/(?:\/|^)\.\.\/(?!\.\.\/)[^\/]*(?=\/)/g,s={buildAbsoluteURL:function(e,t,i){if(i=i||{},e=e.trim(),!(t=t.trim())){if(!i.alwaysNormalize)return e;var n=s.parseURL(e);if(!n)throw new Error("Error trying to parse base URL.");return n.path=s.normalizePath(n.path),s.buildURLFromParts(n)}n=s.parseURL(t);if(!n)throw new Error("Error trying to parse relative URL.");
4715if(n.scheme)return i.alwaysNormalize?(n.path=s.normalizePath(n.path),s.buildURLFromParts(n)):t;t=s.parseURL(e);if(!t)throw new Error("Error trying to parse base URL.");!t.netLoc&&t.path&&"/"!==t.path[0]&&(r=a.exec(t.path),t.netLoc=r[1],t.path=r[2]),t.netLoc&&!t.path&&(t.path="/");var r,e={scheme:t.scheme,netLoc:n.netLoc,path:null,params:n.params,query:n.query,fragment:n.fragment};return n.netLoc||(e.netLoc=t.netLoc,"/"!==n.path[0]&&(n.path?(r=(r=t.path).substring(0,r.lastIndexOf("/")+1)+n.path,e.path=s.normalizePath(r)):(e.path=t.path,n.params||(e.params=t.params,n.query||(e.query=t.query))))),null===e.path&&(e.path=i.alwaysNormalize?s.normalizePath(n.path):n.path),s.buildURLFromParts(e)},parseURL:function(e){e=i.exec(e);return e?{scheme:e[1]||"",netLoc:e[2]||"",path:e[3]||"",params:e[4]||"",query:e[5]||"",fragment:e[6]||""}:null},normalizePath:function(e){for(e=e.split("").reverse().join("").replace(n,"");e.length!==(e=e.replace(r,"")).length;);return e.split("").reverse().join("")},buildURLFromParts:function(e){return e.scheme+e.netLoc+e.path+e.params+e.query+e.fragment}},e.exports=s}),rr="http://example.com",ar=function(){function e(){this.listeners={}}var t=e.prototype;return t.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)},t.off=function(e,t){if(!this.listeners[e])return!1;t=this.listeners[e].indexOf(t);return this.listeners[e]=this.listeners[e].slice(0),this.listeners[e].splice(t,1),-1<t},t.trigger=function(e){var t=this.listeners[e];if(t)if(2===arguments.length)for(var i=t.length,n=0;n<i;++n)t[n].call(this,arguments[1]);else for(var r=Array.prototype.slice.call(arguments,1),a=t.length,s=0;s<a;++s)t[s].apply(this,r)},t.dispose=function(){this.listeners={}},t.pipe=function(t){this.on("data",function(e){t.push(e)})},e}(),sr=function(e){return window.atob?window.atob(e):Buffer.from(e,"base64").toString("binary")};function or(e){for(var t=sr(e),i=new Uint8Array(t.length),n=0;n<t.length;n++)i[n]=t.charCodeAt(n);return i}
4716 /*! @name m3u8-parser @version 4.7.0 @license Apache-2.0 */function ur(e){var t=/([0-9.]*)?@?([0-9.]*)?/.exec(e||""),e={};return t[1]&&(e.length=parseInt(t[1],10)),t[2]&&(e.offset=parseInt(t[2],10)),e}function lr(e){for(var t,i=e.split(new RegExp('(?:^|,)((?:[^=]*)=(?:"[^"]*"|[^,]*))')),n={},r=i.length;r--;)""!==i[r]&&((t=/([^=]*)=(.*)/.exec(i[r]).slice(1))[0]=t[0].replace(/^\s+|\s+$/g,""),t[1]=t[1].replace(/^\s+|\s+$/g,""),t[1]=t[1].replace(/^['"](.*)['"]$/g,"$1"),n[t[0]]=t[1]);return n}function cr(t){var i={};return Object.keys(t).forEach(function(e){i[e.toLowerCase().replace(/-(\w)/g,function(e){return e[1].toUpperCase()})]=t[e]}),i}function dr(e){var t,i,n,r,a=e.serverControl,s=e.targetDuration,o=e.partTargetDuration;a&&(t="#EXT-X-SERVER-CONTROL",i="holdBack",n="partHoldBack",r=s&&3*s,e=o&&2*o,s&&!a.hasOwnProperty(i)&&(a[i]=r,this.trigger("info",{message:t+" defaulting HOLD-BACK to targetDuration * 3 ("+r+")."})),r&&a[i]<r&&(this.trigger("warn",{message:t+" clamping HOLD-BACK ("+a[i]+") to targetDuration * 3 ("+r+")"}),a[i]=r),o&&!a.hasOwnProperty(n)&&(a[n]=3*o,this.trigger("info",{message:t+" defaulting PART-HOLD-BACK to partTargetDuration * 3 ("+a[n]+")."})),o&&a[n]<e&&(this.trigger("warn",{message:t+" clamping PART-HOLD-BACK ("+a[n]+") to partTargetDuration * 2 ("+e+")."}),a[n]=e))}function hr(e){return e&&e.replace(/avc1\.(\d+)\.(\d+)/i,function(e,t,i){return"avc1."+("00"+Number(t).toString(16)).slice(-2)+"00"+("00"+Number(i).toString(16)).slice(-2)})}function pr(e){var e=(e=void 0===e?"":e).split(","),a=[];return e.forEach(function(n){var r;n=n.trim(),Er.forEach(function(e){var t,i=wr[e].exec(n.toLowerCase());!i||i.length<=1||(r=e,t=n.substring(0,i[1].length),i=n.replace(t,""),a.push({type:t,details:i,mediaType:e}))}),r||a.push({type:n,details:"",mediaType:"unknown"})}),a}function fr(e){return wr.audio.test((e=void 0===e?"":e).trim().toLowerCase())}function mr(e){if(e&&"string"==typeof e){var t=e.toLowerCase().split(",").map(function(e){return hr(e.trim())}),i="video";1===t.length&&fr(t[0])?i="audio":1===t.length&&(n=t[0],wr.text.test((n=void 0===n?"":n).trim().toLowerCase()))&&
4716(i="application");var n="mp4";return t.every(function(e){return wr.mp4.test(e)})?n="mp4":t.every(function(e){return wr.webm.test(e)})?n="webm":t.every(function(e){return wr.ogg.test(e)})&&(n="ogg"),i+"/"+n+';codecs="'+e+'"'}}function gr(e){return void 0===e&&(e=""),window.MediaSource&&window.MediaSource.isTypeSupported&&window.MediaSource.isTypeSupported(mr(e))||!1}function yr(e){return(e=void 0===e?"":e).toLowerCase().split(",").every(function(e){e=e.trim();for(var t=0;t<kr.length;t++)if(wr["muxer"+kr[t]].test(e))return!0;return!1})}function vr(e){return Ir.test(e)?"hls":xr.test(e)?"dash":"application/vnd.videojs.vhs+json"===e?"vhs-json":null}var _r=function(t){function e(){var e=t.call(this)||this;return e.buffer="",e}return mt(e,t),e.prototype.push=function(e){var t;for(this.buffer+=e,t=this.buffer.indexOf("\n");-1<t;t=this.buffer.indexOf("\n"))this.trigger("data",this.buffer.substring(0,t)),this.buffer=this.buffer.substring(t+1)},e}(ar),br=String.fromCharCode(9),Tr=function(t){function e(){var e=t.call(this)||this;return e.customParsers=[],e.tagMappers=[],e}mt(e,t);var i=e.prototype;return i.push=function(i){var r,a,s=this;0!==(i=i.trim()).length&&("#"===i[0]?this.tagMappers.reduce(function(e,t){t=t(i);return t===i?e:e.concat([t])},[i]).forEach(function(e){for(var t,i,n=0;n<s.customParsers.length;n++)if(s.customParsers[n].call(s,e))return;if(0===e.indexOf("#EXT"))if(e=e.replace("\r",""),r=/^#EXTM3U/.exec(e))s.trigger("data",{type:"tag",tagType:"m3u"});else{if(r=/^#EXTINF:?([0-9\.]*)?,?(.*)?$/.exec(e))return a={type:"tag",tagType:"inf"},r[1]&&(a.duration=parseFloat(r[1])),r[2]&&(a.title=r[2]),void s.trigger("data",a);if(r=/^#EXT-X-TARGETDURATION:?([0-9.]*)?/.exec(e))return a={type:"tag",tagType:"targetduration"},r[1]&&(a.duration=parseInt(r[1],10)),void s.trigger("data",a);if(r=/^#EXT-X-VERSION:?([0-9.]*)?/.exec(e))return a={type:"tag",tagType:"version"},r[1]&&(a.version=parseInt(r[1],10)),void s.trigger("data",a);if(r=/^#EXT-X-MEDIA-SEQUENCE:?(\-?[0-9.]*)?/.exec(e))return a={type:"tag",tagType:"media-sequence"},r[1]&&(a.number=parseInt(r[1],10)),void s.trigger("data",a);if(r=/^#EXT-X-DISCONTINUITY-SEQUENCE:?(\-?[0-9.]*)?/.exec(e))return a={type:"tag",tagType:"discontinuity-sequence"},r[1]&&(a.number=parseInt(r[1],10)),void s.trigger("data",a);if(r=/^#EXT-X-PLAYLIST-TYPE:?(.*)?$/.exec(e))return a={type:"tag",tagType:"playlist-type"},r[1]&&(a.playlistType=r[1]),void s.trigger("data",a);if(r=/^#EXT-X-BYTERANGE:?(.*)?$/.exec(e))return a=g(ur(r[1]),{type:"tag",tagType:"byterange"}),void s.trigger("data",a);if(r=/^#EXT-X-ALLOW-CACHE:?(YES|NO)?/.exec(e))return a={type:"tag",tagType:"allow-cache"},r[1]&&(a.allowed=!/NO/.test(r[1])),void s.trigger("data",a);if(r=/^#EXT-X-MAP:?(.*)$/.exec(e))return a={type:"tag",tagType:"map"},r[1]&&((t=lr(r[1])).URI&&(a.uri=t.URI),t.BYTERANGE&&(a.byterange=ur(t.BYTERANGE))),void s.trigger("data",a);if(r=/^#EXT-X-STREAM-INF:?(.*)$/.exec(e))return a={type:"tag",tagType:"stream-inf"},r[1]&&(a.attributes=lr(r[1]),a.attributes.RESOLUTION&&(i={},(t=a.attributes.RESOLUTION.split("x"))[0]&&(i.width=parseInt(t[0],10)),t[1]&&(i.height=parseInt(t[1],10)),a.attributes.RESOLUTION=i),a.attributes.BANDWIDTH&&(a.attributes.BANDWIDTH=parseInt(a.attributes.BANDWIDTH,10)),a.attributes["PROGRAM-ID"]&&(a.attributes["PROGRAM-ID"]=parseInt(a.attributes["PROGRAM-ID"],10))),void s.trigger("data",a);if(r=/^#EXT-X-MEDIA:?(.*)$/.exec(e))return a={type:"tag",tagType:"media"},r[1]&&(a.attributes=lr(r[1])),void s.trigger("data",a);if(r=/^#EXT-X-ENDLIST/.exec(e))s.trigger("data",{type:"tag",tagType:"endlist"});else{if(!(r=/^#EXT-X-DISCONTINUITY/.exec(e)))return(r=/^#EXT-X-PROGRAM-DATE-TIME:?(.*)$/.exec(e))?(a={type:"tag",tagType:"program-date-time"},r[1]&&(a.dateTimeString=r[1],a.dateTimeObject=new Date(r[1])),void s.trigger("data",a)):(r=/^#EXT-X-KEY:?(.*)$/.exec(e))?(a={type:"tag",tagType:"key"},r[1]&&(a.attributes=lr(r[1]),a.attributes.IV&&("0x"===a.attributes.IV.substring(0,2).toLowerCase()&&(a.attributes.IV=a.attributes.IV.substring(2)),a.attributes.IV=a.attributes.IV.match(/.{8}/g),a.attributes.IV[0]=parseInt(a.attributes.IV[0],16),a.attributes.IV[1]=parseInt(a.attributes.IV[1],16),a.attributes.IV[2]=parseInt(a.attributes.IV[2],16),a.attributes.IV[3]=parseInt(a.attributes.IV[3],16),a.attributes.IV=new Uint32Array(a.attributes.IV))),void s.trigger("data",a)):(r=/^#EXT-X-START:?(.*)$/.exec(e))?(a={type:"tag",tagType:"start"},r[1]&&(a.attributes=lr(r[1]),a.attributes["TIME-OFFSET"]=parseFloat(a.attributes["TIME-OFFSET"]),a.attributes.PRECISE=/YES/.test(a.attributes.PRECISE)),void s.trigger("data",a)):(r=/^#EXT-X-CUE-OUT-CONT:?(.*)?$/.exec(e))?(a={type:"tag",tagType:"cue-out-cont"},r[1]?a.data=r[1]:a.data="",void s.trigger("data",a)):(r=/^#EXT-X-CUE-OUT:?(.*)?$/.exec(e))?(a={type:"tag",tagType:"cue-out"},r[1]?a.data=r[1]:a.data="",void s.trigger("data",a)):(r=/^#EXT-X-CUE-IN:?(.*)?$/.exec(e))?(a={type:"tag",tagType:"cue-in"},r[1]?a.data=r[1]:a.data="",void s.trigger("data",a)):(r=/^#EXT-X-SKIP:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"skip"}).attributes=lr(r[1]),a.attributes.hasOwnProperty("SKIPPED-SEGMENTS")&&(a.attributes["SKIPPED-SEGMENTS"]=parseInt(a.attributes["SKIPPED-SEGMENTS"],10)),a.attributes.hasOwnProperty("RECENTLY-REMOVED-DATERANGES")&&(a.attributes["RECENTLY-REMOVED-DATERANGES"]=a.attributes["RECENTLY-REMOVED-DATERANGES"].split(br)),void s.trigger("data",a)):(r=/^#EXT-X-PART
4716:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"part"}).attributes=lr(r[1]),["DURATION"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=parseFloat(a.attributes[e]))}),["INDEPENDENT","GAP"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=/YES/.test(a.attributes[e]))}),a.attributes.hasOwnProperty("BYTERANGE")&&(a.attributes.byterange=ur(a.attributes.BYTERANGE)),void s.trigger("data",a)):(r=/^#EXT-X-SERVER-CONTROL:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"server-control"}).attributes=lr(r[1]),["CAN-SKIP-UNTIL","PART-HOLD-BACK","HOLD-BACK"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=parseFloat(a.attributes[e]))}),["CAN-SKIP-DATERANGES","CAN-BLOCK-RELOAD"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=/YES/.test(a.attributes[e]))}),void s.trigger("data",a)):(r=/^#EXT-X-PART-INF:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"part-inf"}).attributes=lr(r[1]),["PART-TARGET"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=parseFloat(a.attributes[e]))}),void s.trigger("data",a)):(r=/^#EXT-X-PRELOAD-HINT:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"preload-hint"}).attributes=lr(r[1]),["BYTERANGE-START","BYTERANGE-LENGTH"].forEach(function(e){var t;a.attributes.hasOwnProperty(e)&&(a.attributes[e]=parseInt(a.attributes[e],10),t="BYTERANGE-LENGTH"===e?"length":"offset",a.attributes.byterange=a.attributes.byterange||{},a.attributes.byterange[t]=a.attributes[e],delete a.attributes[e])}),void s.trigger("data",a)):(r=/^#EXT-X-RENDITION-REPORT:(.*)$/.exec(e))&&r[1]?((a={type:"tag",tagType:"rendition-report"}).attributes=lr(r[1]),["LAST-MSN","LAST-PART"].forEach(function(e){a.attributes.hasOwnProperty(e)&&(a.attributes[e]=parseInt(a.attributes[e],10))}),void s.trigger("data",a)):void s.trigger("data",{type:"tag",data:e.slice(4)});s.trigger("data",{type:"tag",tagType:"discontinuity"})}}else s.trigger("data",{type:"comment",text:e.slice(1)})}):this.trigger("data",{type:"uri",uri:i}))},i.addParser=function(e){var t=this,i=e.expression,n=e.customType,r=e.dataParser,a=e.segment;"function"!=typeof r&&(r=function(e){return e}),this.customParsers.push(function(e){if(i.exec(e))return t.trigger("data",{type:"custom",data:r(e),customType:n,segment:a}),!0})},i.addTagMapper=function(e){var t=e.expression,i=e.map;this.tagMappers.push(function(e){return t.test(e)?i(e):e})},e}(ar),Sr=function(t){function e(){var e=t.call(this)||this;e.lineStream=new _r,e.parseStream=new Tr,e.lineStream.pipe(e.parseStream);var n,r,a=ft(e),o=[],u={},l=!1,c={AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},d=0;e.manifest={allowCache:!0,discontinuityStarts:[],segments:[]};var h=0,p=0;return e.on("end",function(){u.uri||!u.parts&&!u.preloadHints||(!u.map&&n&&(u.map=n),!u.key&&r&&(u.key=r),u.timeline||"number"!=typeof d||(u.timeline=d),e.manifest.preloadSegment=u)}),e.parseStream.on("data",function(s){var t,i;({tag:function(){({version:function(){s.version&&(this.manifest.version=s.version)},"allow-cache":function(){this.manifest.allowCache=s.allowed,"allowed"in s||(this.trigger("info",{message:"defaulting allowCache to YES"}),this.manifest.allowCache=!0)},byterange:function(){var e={};"length"in s&&((u.byterange=e).length=s.length,"offset"in s||(s.offset=h)),"offset"in s&&((u.byterange=e).offset=s.offset),h=e.offset+e.length},endlist:function(){this.manifest.endList=!0},inf:function(){"mediaSequence"in this.manifest||(this.manifest.mediaSequence=0,this.trigger("info",{message:"defaulting media sequence to zero"})),"discontinuitySequence"in this.manifest||(this.manifest.discontinuitySequence=0,this.trigger("info",{message:"defaulting discontinuity sequence to zero"})),0<s.duration&&(u.duration=s.duration),0===s.duration&&(u.duration=.01,this.trigger("info",{message:"updating zero segment duration to a small value"})),this.manifest.segments=o},key:function(){if(s.attributes)if("NONE"!==s.attributes.METHOD)if(s.attributes.URI){if("com.apple.streamingkeydelivery"===s.attributes.KEYFORMAT)return this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.apple.fps.1_0"]={attributes:s.attributes});if("urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"===s.attributes.KEYFORMAT)return-1===["SAMPLE-AES","SAMPLE-AES-CTR","SAMPLE-AES-CENC"].indexOf(s.attributes.METHOD)?void this.trigger("warn",{message:"invalid key method provided for Widevine"}):("SAMPLE-AES-CENC"===s.attributes.METHOD&&this.trigger("warn",{message:"SAMPLE-AES-CENC is deprecated, please use SAMPLE-AES-CTR instead"}),"data:text/plain;base64,"!==s.attributes.URI.substring(0,23)?void this.trigger("warn",{message:"invalid key URI provided for Widevine"}):s.attributes.KEYID&&"0x"===s.attributes.KEYID.substring(0,2)?(this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.widevine.alpha"]={attributes:{schemeIdUri:s.attributes.KEYFORMAT,keyId:s.attributes.KEYID.substring(2)},pssh:or(s.attributes.URI.split(",")[1])})):void this.trigger("warn",{message:"invalid key ID provided for Widevine"}));s.attributes.METHOD||this.trigger("warn",{message:"defaulting key method to AES-128"}),r={method:s.attributes.METHOD||"AES-128",uri:s.attributes.URI},"undefined"!=typeof s.attributes.IV&&(r.iv=s.attributes.IV)}else this.trigger("warn",{message:"ignoring key declaration without URI"});else r=null;else this.trigger("warn",{message:"ignoring key declaration without attribute list"})},"media-sequence":function(){isFinite(s.number)?this.manifest.mediaSequence=s.number:this.trigger("warn",{message:"ignoring invalid media sequence: "+s.number})},"discontinuity-sequence":function(){isFinite(s.number)?(this.manifest.discontinuitySequence=s.number,d=s.number):this.trigger("warn",{message:"ignoring invalid discontinuity sequence: "+s.number})},"playlist-type":function(){/VOD|EVENT/.test(s.playlistType)?this.manifest.playlistType=s.playlistType:this.trigger("warn",{message:"ignoring unknown playlist type: "+s.playlist})},map:function(){n={},s.uri&&(n.uri=s.uri),s.byterange&&(n.byterange=s.byterange),r&&(n.key=r)},"stream-inf":function(){this.manifest.playlists=o,this.manifest.mediaGroups=this.manifest.mediaGroups||c,s.attributes?(u.attributes||(u.attributes={}),g(u.attributes,s.attributes)):this.trigger("warn",{message:"ignoring empty stream-inf attributes"})},media:function(){var e;this.manifest.mediaGroups=this.manifest.mediaGroups||c,s.attributes&&s.attributes.TYPE&&s.attributes["GROUP-ID"]&&s.attributes.NAME?((e=this.manifest.mediaGroups[s.attributes.TYPE])[s.attributes["GROUP-ID"]]=e[s.attributes["GROUP-ID"]]||{},t=e[s.attributes["GROUP-ID"]],(i={default:/yes/i.test(s.attributes.DEFAULT)}).default?i.autoselect=!0:i.autoselect=/yes/i.test(s.attributes.AUTOSELECT),s.attributes.LANGUAGE&&(i.language=s.attributes.LANGUAGE),s.attributes.URI&&(i.uri=s.attributes.URI),s.attributes["INSTREAM-ID"]&&(i.instreamId=s.attributes["INSTREAM-ID"]),s.attributes.CHARACTERISTICS&&(i.characteristics=s.attributes.CHARACTERISTICS),s.attributes.FORCED&&(i.forced=/yes/i.test(s.attributes.FORCED)),t[s.attributes.NAME]=i):this.trigger("warn",{message:"ignoring incomplete or missing media group"})},discontinuity:function(){d+=1,u.discontinuity=!0,this.manifest.discontinuityStarts.push(o.length)},"program-date-time":function(){"undefined"==typeof this.manifest.dateTimeString&&(this.manifest.dateTimeString=s.dateTimeString,this.manifest.dateTimeObject=s.dateTimeObject),u.dateTimeString=s.dateTimeString,u.dateTimeObject=s.dateTimeObject},targetduration:function(){!isFinite(s.duration)||s.duration<0?this.trigger("warn",{message:"ignoring invalid target duration: "+s.duration}):(this.manifest.targetDuration=s.duration,dr.call(this,this.manifest))},start:function(){s.attributes&&!isNaN(s.attributes["TIME-OFFSET"])?this.manifest.start={timeOffset:s.attributes["TIME-OFFSET"],precise:s.attributes.PRECISE}:this.trigger("warn",{message:"ignoring start declaration without appropriate attribute list"})},"cue-out":function(){u.cueOut=s.data},"cue-out-cont":function(){u.cueOutCont=s.data},"cue-in":function(){u.cueIn=s.data},skip:function(){this.manifest.skip=cr(s.attributes),this.warnOnMissingAttributes_("#EXT-X-SKIP",s.attributes,["SKIPPED-SEGMENTS"])},part:function(){var i=this;l=!0;var e=this.manifest.segments.length,t=cr(s.attributes);u.parts=u.parts||[],u.parts.push(t),t.byterange&&(t.byterange.hasOwnProperty("offset")||(t.byterange.offset=p),p=t.byterange.offset+t.byterange.length);var n=u.parts.length-1;this.warnOnMissingAttributes_("#EXT-X-PART #"+n+" for segment #"+e,s.attributes,["URI","DURATION"]),this.manifest.renditionReports&&this.manifest.renditionReports.forEac
4716h(function(e,t){e.hasOwnProperty("lastPart")||i.trigger("warn",{message:"#EXT-X-RENDITION-REPORT #"+t+" lacks required attribute(s): LAST-PART"})})},"server-control":function(){var e=this.manifest.serverControl=cr(s.attributes);e.hasOwnProperty("canBlockReload")||(e.canBlockReload=!1,this.trigger("info",{message:"#EXT-X-SERVER-CONTROL defaulting CAN-BLOCK-RELOAD to false"})),dr.call(this,this.manifest),e.canSkipDateranges&&!e.hasOwnProperty("canSkipUntil")&&this.trigger("warn",{message:"#EXT-X-SERVER-CONTROL lacks required attribute CAN-SKIP-UNTIL which is required when CAN-SKIP-DATERANGES is set"})},"preload-hint":function(){var e=this.manifest.segments.length,t=cr(s.attributes),i=t.type&&"PART"===t.type;u.preloadHints=u.preloadHints||[],u.preloadHints.push(t),t.byterange&&(t.byterange.hasOwnProperty("offset")||(t.byterange.offset=i?p:0,i&&(p=t.byterange.offset+t.byterange.length)));var n=u.preloadHints.length-1;if(this.warnOnMissingAttributes_("#EXT-X-PRELOAD-HINT #"+n+" for segment #"+e,s.attributes,["TYPE","URI"]),t.type)for(var r=0;r<u.preloadHints.length-1;r++){var a=u.preloadHints[r];a.type&&a.type===t.type&&this.trigger("warn",{message:"#EXT-X-PRELOAD-HINT #"+n+" for segment #"+e+" has the same TYPE "+t.type+" as preload hint #"+r})}},"rendition-report":function(){var e=cr(s.attributes);this.manifest.renditionReports=this.manifest.renditionReports||[],this.manifest.renditionReports.push(e);var t=this.manifest.renditionReports.length-1,e=["LAST-MSN","URI"];l&&e.push("LAST-PART"),this.warnOnMissingAttributes_("#EXT-X-RENDITION-REPORT #"+t,s.attributes,e)},"part-inf":function(){this.manifest.partInf=cr(s.attributes),this.warnOnMissingAttributes_("#EXT-X-PART-INF",s.attributes,["PART-TARGET"]),this.manifest.partInf.partTarget&&(this.manifest.partTargetDuration=this.manifest.partInf.partTarget),dr.call(this,this.manifest)}}[s.tagType]||function(){}).call(a)},uri:function(){u.uri=s.uri,o.push(u),!this.manifest.targetDuration||"duration"in u||(this.trigger("warn",{message:"defaulting segment duration to the target duration"}),u.duration=this.manifest.targetDuration),r&&(u.key=r),u.timeline=d,n&&(u.map=n),p=0,u={}},comment:function(){},custom:function(){s.segment?(u.custom=u.custom||{},u.custom[s.customType]=s.data):(this.manifest.custom=this.manifest.custom||{},this.manifest.custom[s.customType]=s.data)}})[s.type].call(a)}),e}mt(e,t);var i=e.prototype;return i.warnOnMissingAttributes_=function(e,t,i){var n=[];i.forEach(function(e){t.hasOwnProperty(e)||n.push(e)}),n.length&&this.trigger("warn",{message:e+" lacks required attribute(s): "+n.join(", ")})},i.push=function(e){this.lineStream.push(e)},i.end=function(){this.lineStream.push("\n"),this.trigger("end")},i.addParser=function(e){this.parseStream.addParser(e)},i.addTagMapper=function(e){this.parseStream.addTagMapper(e)},e}(ar),wr={mp4:/^(av0?1|avc0?[1234]|vp0?9|flac|opus|mp3|mp4a|mp4v|stpp.ttml.im1t)/,webm:/^(vp0?[89]|av0?1|opus|vorbis)/,ogg:/^(vp0?[89]|theora|flac|opus|vorbis)/,video:/^(av0?1|avc0?[1234]|vp0?[89]|hvc1|hev1|theora|mp4v)/,audio:/^(mp4a|flac|vorbis|opus|ac-[34]|ec-3|alac|mp3|speex|aac)/,text:/^(stpp.ttml.im1t)/,muxerVideo:/^(avc0?1)/,muxerAudio:/^(mp4a)/,muxerText:/a^/},Er=["video","audio","text"],kr=["Video","Audio","Text"],Cr="mp4a.40.2",Ir=/^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i,xr=/^application\/dash\+xml/i;function Ar(e,t){return(t=void 0===t?Object:t)&&"function"==typeof t.freeze?t.freeze(e):e}var Pr=Ar({HTML:"text/html",isHTML:function(e){return e===Pr.HTML},XML_APPLICATION:"application/xml",XML_TEXT:"text/xml",XML_XHTML_APPLICATION:"application/xhtml+xml",XML_SVG_IMAGE:"image/svg+xml"}),Lr=Ar({HTML:"http://www.w3.org/1999/xhtml",isHTML:function(e){return e===Lr.HTML},SVG:"http://www.w3.org/2000/svg",XML:"http://www.w3.org/XML/1998/namespace",XMLNS:"http://www.w3.org/2000/xmlns/"}),Dr={freeze:Ar,MIME_TYPE:Pr,NAMESPACE:Lr},Or=Dr.NAMESPACE;function Rr(e){return""!==e}function Mr(e,t){return e.hasOwnProperty(t)||(e[t]=!0),e}function Nr(e){if(!e)return[];e=(e=e)?e.split(/[\t\n\f\r ]+/).filter(Rr):[];return Object.keys(e.reduce(Mr,{}))}function Ur(e,t){for(var i in e)t[i]=e[i]}function Br(e,t){var i,n=e.prototype;n instanceof t||((i=function(){}).prototype=t.prototype,Ur(n,i=new i),e.prototype=n=i),n.constructor!=e&&(n.constructor=e)}var W={},Fr=W.ELEMENT_NODE=1,jr=W.ATTRIBUTE_NODE=2,Hr=W.TEXT_NODE=3,qr=W.CDATA_SECTION_NODE=4,Vr=W.ENTITY_REFERENCE_NODE=5,Wr=(W.ENTITY_NODE=6,W.PROCESSING_INSTRUCTION_NODE=7),Gr=W.COMMENT_NODE=8,zr=W.DOCUMENT_NODE=9,Xr=W.DOCUMENT_TYPE_NODE=10,Kr=W.DOCUMENT_FRAGMENT_NODE=11,x=(W.NOTATION_NODE=12,{}),Yr={};x.INDEX_SIZE_ERR=(Yr[1]="Index size error",1),x.DOMSTRING_SIZE_ERR=(Yr[2]="DOMString size error",2);x.HIERARCHY_REQUEST_ERR=(Yr[3]="Hierarchy request error",3);x.WRONG_DOCUMENT_ERR=(Yr[4]="Wrong document",4),x.INVALID_CHARACTER_ERR=(Yr[5]="Invalid character",5),x.NO_DATA_ALLOWED_ER
4716R=(Yr[6]="No data allowed",6),x.NO_MODIFICATION_ALLOWED_ERR=(Yr[7]="No modification allowed",7);x.NOT_FOUND_ERR=(Yr[8]="Not found",8);x.NOT_SUPPORTED_ERR=(Yr[9]="Not supported",9);var Qr;x.INUSE_ATTRIBUTE_ERR=(Yr[10]="Attribute in use",10);function $r(e,t){var i;return t instanceof Error?i=t:(i=this,Error.call(this,Yr[e]),this.message=Yr[e],Error.captureStackTrace&&Error.captureStackTrace(this,$r)),i.code=e,t&&(this.message=this.message+": "+t),i}function Jr(){}function Zr(e,t){this._node=e,this._refresh=t,ea(this)}function ea(e){var t,i=e._node._inc||e._node.ownerDocument._inc;e._inc!=i&&(t=e._refresh(e._node),La(e,"length",t.length),Ur(t,e),e._inc=i)}function ta(){}function ia(e,t){for(var i=e.length;i--;)if(e[i]===t)return i}function na(e,t,i,n){n?t[ia(t,n)]=i:t[t.length++]=i,!e||(t=(i.ownerElement=e).ownerDocument)&&(n&&ca(t,e,n),e=e,i=i,(t=t)&&t._inc++,i.namespaceURI===Or.XMLNS&&(e._nsMap[i.prefix?i.localName:""]=i.value))}function ra(e,t,i){var n=ia(t,i);if(!(0<=n))throw $r(8,new Error(e.tagName+"@"+i));for(var r,a=t.length-1;n<a;)t[n]=t[++n];t.length=a,!e||(r=e.ownerDocument)&&(ca(r,e,i),i.ownerElement=null)}function aa(){}function sa(){}function oa(e){return("<"==e?"&lt;":">"==e&&"&gt;")||"&"==e&&"&amp;"||'"'==e&&"&quot;"||"&#"+e.charCodeAt()+";"}function ua(e,t){if(t(e))return 1;if(e=e.firstChild)do{if(ua(e,t))return 1}while(e=e.nextSibling)}function la(){}function ca(e,t,i){e&&e._inc++,i.namespaceURI===Or.XMLNS&&delete t._nsMap[i.prefix?i.localName:""]}function da(e,t,i){if(e&&e._inc){e._inc++;var n=t.childNodes;if(i)n[n.length++]=i;else{for(var r=t.firstChild,a=0;r;)r=(n[a++]=r).nextSibling;n.length=a}}}function ha(e,t){var i=t.previousSibling,n=t.nextSibling;return i?i.nextSibling=n:e.firstChild=n,n?n.previousSibling=i:e.lastChild=i,da(e.ownerDocument,e),t}function pa(e,t,i){var n=t.parentNode;if(n&&n.removeChild(t),t.nodeType===Kr){var r=t.firstChild;if(null==r)return t;var a=t.lastChild}else r=a=t;n=i?i.previousSibling:e.lastChild;for(r.previousSibling=n,a.nextSibling=i,n?n.nextSibling=r:e.firstChild=r,null==i?e.lastChild=a:i.previousSibling=a;r.parentNode=e,r!==a&&(r=r.nextSibling););return da(e.ownerDocument||e,e),t.nodeType==Kr&&(t.firstChild=t.lastChild=null),t}function fa(){this._nsMap={}}function ma(){}function ga(){}function ya(){}function va(){}function _a(){}function ba(){}function Ta(){}function Sa(){}function wa(){}function Ea(){}function ka(){}function Ca(){}function Ia(e,t){var i,n=[],r=9==this.nodeType&&this.documentElement||this,a=r.prefix,s=r.namespaceURI;return Pa(this,n,e,t,i=s&&null==a&&null==(a=r.lookupPrefix(s))?[{namespace:s,prefix:null}]:i),n.join("")}function xa(e,t,i){var n=e.prefix||"",r=e.namespaceURI;if(r&&("xml"!==n||r!==Or.XML)&&r!==Or.XMLNS){for(var a=i.length;a--;){var s=i[a];if(s.prefix===n)return s.namespace!==r}return 1}}function Aa(e,t,i){e.push(" ",t,'="',i.replace(/[<&"]/g,oa),'"')}function Pa(e,t,i,n,r){if(r=r||[],n){if(!(e=n(e)))return;if("string"==typeof e)return void t.push(e)}switch(e.nodeType){case Fr:var a=e.attributes,s=a.length,o=e.firstChild,u=e.tagName,l=u;if(!(i=Or.isHTML(e.namespaceURI)||i)&&!e.prefix&&e.namespaceURI){for(var c,d=0;d<a.length;d++)if("xmlns"===a.item(d).name){c=a.item(d).value;break}if(!c)for(var h=r.length-1;0<=h;h--)if(""===(p=r[h]).prefix&&p.namespace===e.namespaceURI){c=p.namespace;break}if(c!==e.namespaceURI)for(var p,h=r.length-1;0<=h;h--)if((p=r[h]).namespace===e.namespaceURI){p.prefix&&(l=p.prefix+":"+u);break}}t.push("<",l);for(var f=0;f<s;f++)"xmlns"==(m=a.item(f)).prefix?r.push({prefix:m.localName,namespace:m.value}):"xmlns"==m.nodeName&&r.push({prefix:"",namespace:m.value});for(var m,g,y,f=0;f<s;f++)xa(m=a.item(f),0,r)&&(Aa(t,(g=m.prefix||"")?"xmlns:"+g:"xmlns",y=m.namespaceURI),r.push({prefix:g,namespace:y})),Pa(m,t,i,n,r);if(u===l&&xa(e,0,r)&&(Aa(t,(g=e.prefix||"")?"xmlns:"+g:"xmlns",y=e.namespaceURI),r.push({prefix:g,namespace:y})),o||i&&!/^(?:meta|link|img|br|hr|input)$/i.test(u)){if(t.push(">"),i&&/^script$/i.test(u))for(;o;)o.data?t.push(o.data):Pa(o,t,i,n,r.slice()),o=o.nextSibling;else for(;o;)Pa(o,t,i,n,r.slice()),o=o.nextSibling;t.push("</",l,">")}else t.push("/>");return;case zr:case Kr:for(o=e.firstChild;o;)Pa(o,t,i,n,r.slice()),o=o.nextSibling;return;
4716case jr:return Aa(t,e.name,e.value),0;case Hr:return t.push(e.data.replace(/[<&]/g,oa).replace(/]]>/g,"]]&gt;"));case qr:return t.push("<![CDATA[",e.data,"]]>");case Gr:return t.push("\x3c!--",e.data,"--\x3e");case Xr:var v=e.publicId,_=e.systemId;return t.push("<!DOCTYPE ",e.name),void(v?(t.push(" PUBLIC ",v),_&&"."!=_&&t.push(" ",_),t.push(">")):_&&"."!=_?t.push(" SYSTEM ",_,">"):((_=e.internalSubset)&&t.push(" [",_,"]"),t.push(">")));case Wr:return t.push("<?",e.target," ",e.data,"?>");case Vr:return t.push("&",e.nodeName,";");default:t.push("??",e.nodeName)}}function La(e,t,i){e[t]=i}x.INVALID_STATE_ERR=(Yr[11]="Invalid state",11),x.SYNTAX_ERR=(Yr[12]="Syntax error",12),x.INVALID_MODIFICATION_ERR=(Yr[13]="Invalid modification",13),x.NAMESPACE_ERR=(Yr[14]="Invalid namespace",14),x.INVALID_ACCESS_ERR=(Yr[15]="Invalid access",15),$r.prototype=Error.prototype,Ur(x,$r),Jr.prototype={length:0,item:function(e){return this[e]||null},toString:function(e,t){for(var i=[],n=0;n<this.length;n++)Pa(this[n],i,e,t);return i.join("")}},Zr.prototype.item=function(e){return ea(this),this[e]},Br(Zr,Jr),ta.prototype={length:0,item:Jr.prototype.item,getNamedItem:function(e){for(var t=this.length;t--;){var i=this[t];if(i.nodeName==e)return i}},setNamedItem:function(e){var t=e.ownerElement;if(t&&t!=this._ownerElement)throw new $r(10);t=this.getNamedItem(e.nodeName);return na(this._ownerElement,this,e,t),t},setNamedItemNS:function(e){var t=e.ownerElement;if(t&&t!=this._ownerElement)throw new $r(10);return t=this.getNamedItemNS(e.namespaceURI,e.localName),na(this._ownerElement,this,e,t),t},removeNamedItem:function(e){e=this.getNamedItem(e);return ra(this._ownerElement,this,e),e},removeNamedItemNS:function(e,t){t=this.getNamedItemNS(e,t);return ra(this._ownerElement,this,t),t},getNamedItemNS:function(e,t){for(var i=this.length;i--;){var n=this[i];if(n.localName==t&&n.namespaceURI==e)return n}return null}},aa.prototype={hasFeature:function(e,t){return!0},createDocument:function(e,t,i){var n=new la;return n.implementation=this,n.childNodes=new Jr,n.doctype=i||null,i&&n.appendChild(i),t&&(t=n.createElementNS(e,t),n.appendChild(t)),n},createDocumentType:function(e,t,i){var n=new ba;return n.name=e,n.nodeName=e,n.publicId=t||"",n.systemId=i||"",n}},sa.prototype={firstChild:null,lastChild:null,previousSibling:null,nextSibling:null,attributes:null,parentNode:null,childNodes:null,ownerDocument:null,nodeValue:null,namespaceURI:null,prefix:null,localName:null,insertBefore:function(e,t){return pa(this,e,t)},replaceChild:function(e,t){this.insertBefore(e,t),t&&this.removeChild(t)},removeChild:function(e){return ha(this,e)},appendChild:function(e){return this.insertBefore(e,null)},hasChildNodes:function(){return null!=this.firstChild},cloneNode:function(e){return function e(t,i,n){var r=new i.constructor;for(var a in i){var s=i[a];"object"!=typeof s&&s!=r[a]&&(r[a]=s)}i.childNodes&&(r.childNodes=new Jr);r.ownerDocument=t;switch(r.nodeType){case Fr:var o=i.attributes,u=r.attributes=new ta,l=o.length;u._ownerElement=r;for(var c=0;c<l;c++)r.setAttributeNode(e(t,o.item(c),!0));break;case jr:n=!0}if(n)for(var d=i.firstChild;d;)r.appendChild(e(t,d,n)),d=d.nextSibling;return r}(this.ownerDocument||this,this,e)},normalize:function(){for(var e=this.firstChild;e;){var t=e.nextSibling;t&&t.nodeType==Hr&&e.nodeType==Hr?(this.removeChild(t),e.appendData(t.data)):(e.normalize(),e=t)}},isSupported:function(e,t){return this.ownerDocument.implementation.hasFeature(e,t)},hasAttributes:function(){return 0<this.attributes.length},lookupPrefix:function(e){for(var t=this;t;){var i=t._nsMap;if(i)for(var n in i)if(i[n]==e)return n;t=t.nodeType==jr?t.ownerDocument:t.parentNode}return null},lookupNamespaceURI:function(e){for(var t=this;t;){var i=t._nsMap;if(i&&e in i)return i[e];t=t.nodeType==jr?t.ownerDocument:t.parentNode}return null},isDefaultNamespace:function(e){return null==this.lookupPrefix(e)}},Ur(W,sa),Ur(W,sa.prototype),la.prototype={nodeName:"#document",nodeType:zr,doctype:null,documentElement:null,_inc:1,insertBefore:function(e,t){if(e.nodeType!=Kr)return null==this.documentElement&&e.nodeType==Fr&&(this.documentElement=e),pa(this,e,t),e.ownerDocument=this,e;for(var i=e.firstChild;i;){var n=i.nextSibling;this.insertBefore(i,t),i=n}return e},removeChild:function(e){return this.documentElement==e&&(this.documentElement=null),ha(this,e)},importNode:function(e,t){return function e(t,i,n){var r;switch(i.nodeType){case Fr:(r=i.cloneNode(!1)).ownerDocument=t;case Kr:break;case jr:n=!0}r=r||i.cloneNode(!1);r.ownerDocument=t;r.parentNode=null;if(n)for(var a=i.firstChild;a;)r.appendChild(e(t,a,n)),a=a.nextSibling;return r}(this,e,t)},getElementById:function(t){var i=null;return ua(this.documentElement,function(e){if(e.nodeType==Fr&&e.getAttribute("id")==t)return i=e,!0}),i},getElementsByClassName:function(s){var o=Nr(s);return new Zr(this,function(r){var a=[];return 0<o.length&&ua(r.documentElement,function(e){var t,i,n;e===r||e.nodeType!==Fr||(t=e.getAttribute("class"))&&((i=s===t)||(t=Nr(t),i=o.every((n=t,function(e){return n&&-1!==n.indexOf(e)}))),i&&a.push(e))}),a})},createElement:function(e){var t=new fa;return t.ownerDocument=this,t.nodeName=e,t.tagName=e,t.localName=e,t.childNodes=new Jr,(t.attributes=new ta)._ownerElement=t},createDocumentFragment:function(){var e=new Ea;return e.ownerDocument=this,e.childNodes=new Jr,e},createTextNode:function(e){var t=new ya;return t.ownerDocument=this,t.appendData(e),t},createComment:function(e){var t=new va;return t.ownerDocument=this,t.appendData(e),t},createCDATASection:function(e){var t=new _a;return t.ownerDocument=this,t.appendData(e),t},createProcessingInstruction:function(e,t){var i=new ka;return i.ownerDocument=this,i.tagName=i.target=e,i.nodeValue=i.data=t,i},createAttribute:function(e){var t=new ma;return t.ownerDocument=this,t.name=e,t.nodeName=e,t.localName=e,t.specified=!0,t},createEntityReference:function(e){var t=new wa;return t.ownerDocument=this,t.nodeName=e,t},createElementNS:function(e,t){var i=new fa,n=t.split(":"),r=i.attributes=new ta;return i.childNodes=new Jr,i.ownerDocument=this,i.nodeName=t,i.tagName=t,i.namespaceURI=e,2==n.length?(i.prefix=n[0],i.localName=n[1]):i.localName=t,r._ownerElement=i},createAttributeNS:function(e,t){var i=new ma,n=t.split(":");return i.ownerDocument=this,i.nodeName=t,i.name=t,i.namespaceURI=e,i.specified=!0,2==n.length?(i.prefix=n[0],i.localName=n[1]):i.localName=t,i}},Br(la,sa),la.prototype.getElementsByTagName=(fa.prototype={nodeType:Fr,hasAttribute:function(e){return null!=this.getAttributeNode(e)},getAttribute:function(e){e=this.getAttributeNode(e);return e&&e.value||""},getAttributeNode:function(e){return this.attributes.getNamedItem(e)},setAttribute:function(e,t){e=this.ownerDocument.createAttribute(e);e.value=e.nodeValue=""+t,this.setAttributeNode(e)},removeAttribute:function(e){e=this.getAttributeNode(e);e&&this.removeAttributeNode(e)}
4716,appendChild:function(e){return e.nodeType===Kr?this.insertBefore(e,null):function(e,t){var i=t.parentNode;i&&(n=e.lastChild,i.removeChild(t),n=e.lastChild);var n=e.lastChild;return t.parentNode=e,t.previousSibling=n,t.nextSibling=null,n?n.nextSibling=t:e.firstChild=t,e.lastChild=t,da(e.ownerDocument,e,t),t}(this,e)},setAttributeNode:function(e){return this.attributes.setNamedItem(e)},setAttributeNodeNS:function(e){return this.attributes.setNamedItemNS(e)},removeAttributeNode:function(e){return this.attributes.removeNamedItem(e.nodeName)},removeAttributeNS:function(e,t){t=this.getAttributeNodeNS(e,t);t&&this.removeAttributeNode(t)},hasAttributeNS:function(e,t){return null!=this.getAttributeNodeNS(e,t)},getAttributeNS:function(e,t){t=this.getAttributeNodeNS(e,t);return t&&t.value||""},setAttributeNS:function(e,t,i){t=this.ownerDocument.createAttributeNS(e,t);t.value=t.nodeValue=""+i,this.setAttributeNode(t)},getAttributeNodeNS:function(e,t){return this.attributes.getNamedItemNS(e,t)},getElementsByTagName:function(n){return new Zr(this,function(t){var i=[];return ua(t,function(e){e===t||e.nodeType!=Fr||"*"!==n&&e.tagName!=n||i.push(e)}),i})},getElementsByTagNameNS:function(n,r){return new Zr(this,function(t){var i=[];return ua(t,function(e){e===t||e.nodeType!==Fr||"*"!==n&&e.namespaceURI!==n||"*"!==r&&e.localName!=r||i.push(e)}),i})}}).getElementsByTagName,la.prototype.getElementsByTagNameNS=fa.prototype.getElementsByTagNameNS,Br(fa,sa),ma.prototype.nodeType=jr,Br(ma,sa),ga.prototype={data:"",substringData:function(e,t){return this.data.substring(e,e+t)},appendData:function(e){e=this.data+e,this.nodeValue=this.data=e,this.length=e.length},insertData:function(e,t){this.replaceData(e,0,t)},appendChild:function(e){throw new Error(Yr[3])},deleteData:function(e,t){this.replaceData(e,t,"")},replaceData:function(e,t,i){var n=this.data.substring(0,e),t=this.data.substring(e+t);this.nodeValue=this.data=i=n+i+t,this.length=i.length}},Br(ga,sa),ya.prototype={nodeName:"#text",nodeType:Hr,splitText:function(e){var t=(i=this.data).substring(e),i=i.substring(0,e);this.data=this.nodeValue=i,this.length=i.length;t=this.ownerDocument.createTextNode(t);return this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling),t}},Br(ya,ga),va.prototype={nodeName:"#comment",nodeType:Gr},Br(va,ga),_a.prototype={nodeName:"#cdata-section",nodeType:qr},Br(_a,ga),ba.prototype.nodeType=Xr,Br(ba,sa),Ta.prototype.nodeType=12,Br(Ta,sa),Sa.prototype.nodeType=6,Br(Sa,sa),wa.prototype.nodeType=Vr,Br(wa,sa),Ea.prototype.nodeName="#document-fragment",Ea.prototype.nodeType=Kr,Br(Ea,sa),ka.prototype.nodeType=Wr,Br(ka,sa),Ca.prototype.serializeToString=function(e,t,i){return Ia.call(e,t,i)},sa.prototype.toString=Ia;try{Object.defineProperty&&(Qr=function e(t){switch(t.nodeType){case Fr:case Kr:var i=[];for(t=t.firstChild;t;)7!==t.nodeType&&8!==t.nodeType&&i.push(e(t)),t=t.nextSibling;return i.join("");default:return t.nodeValue}},Object.defineProperty(Zr.prototype,"length",{get:function(){return ea(this),this.$$length}}),Object.defineProperty(sa.prototype,"textContent",{get:function(){return Qr(this)},set:function(e){switch(this.nodeType){case Fr:case Kr:for(;this.firstChild;)this.removeChild(this.firstChild);(e||String(e))&&this.appendChild(this.ownerDocument.createTextNode(e));break;default:this.data=e,this.value=e,this.nodeValue=e}}}),La=function(e,t,i){e["$$"+t]=i})}catch(e){}var U={DocumentType:ba,DOMException:$r,DOMImplementation:aa,Element:fa,Node:sa,NodeList:Jr,XMLSerializer:Ca},Da=m(function(e,t){var i=Dr.freeze;t.XML_ENTITIES=i({amp:"&",apos:"'",gt:">",lt:"<",quot:'"'}),t.HTML_ENTITIES=i({lt:"<",gt:">",amp:"&",quot:'"',apos:"'",Agrave:"À",Aacute:"Á",Acirc:"Â",Atilde:"Ã",Auml:"Ä",Aring:"Å",AElig:"Æ",Ccedil:"Ç",Egrave:"È",Eacute:"É",Ecirc:"Ê",Euml:"Ë",Igrave:"Ì",Iacute:"Í",Icirc:"Î",Iuml:"Ï",ETH:"Ð",Ntilde:"Ñ",Ograve:"Ò",Oacute:"Ó",Ocirc:"Ô",Otilde:"Õ",Ouml:"Ö",Oslash:"Ø",Ugrave:"Ù",Uacute:"Ú",Ucirc:"Û",Uuml:"Ü",Yacute:"Ý",THORN:"Þ",szlig:"ß",agrave:"à",aacute:"á",acirc:"â",atilde:"ã",auml:"ä",aring:"å",aelig:"æ",ccedil
vendor: 9,789 bytes, line 4716
4716:"ç",egrave:"è",eacute:"é",ecirc:"ê",euml:"ë",igrave:"ì",iacute:"í",icirc:"î",iuml:"ï",eth:"ð",ntilde:"ñ",ograve:"ò",oacute:"ó",ocirc:"ô",otilde:"õ",ouml:"ö",oslash:"ø",ugrave:"ù",uacute:"ú",ucirc:"û",uuml:"ü",yacute:"ý",thorn:"þ",yuml:"ÿ",nbsp:" ",iexcl:"¡",cent:"¢",pound:"£",curren:"¤",yen:"¥",brvbar:"¦",sect:"§",uml:"¨",copy:"©",ordf:"ª",laquo:"«",not:"¬",shy:"­­",reg:"®",macr:"¯",deg:"°",plusmn:"±",sup2:"²",sup3:"³",acute:"´",micro:"µ",para:"¶",middot:"·",cedil:"¸",sup1:"¹",ordm:"º",raquo:"»",frac14:"¼",frac12:"½",frac34:"¾",iquest:"¿",times:"×",divide:"÷",forall:"∀",part:"∂",exist:"∃",empty:"∅",nabla:"∇",isin:"∈",notin:"∉",ni:"∋",prod:"∏",sum:"∑",minus:"−",lowast:"∗",radic:"√",prop:"∝",infin:"∞",ang:"∠",and:"∧",or:"∨",cap:"∩",cup:"∪",int:"∫",there4:"∴",sim:"∼",cong:"≅",asymp:"≈",ne:"≠",equiv:"≡",le:"≤",ge:"≥",sub:"⊂",sup:"⊃",nsub:"⊄",sube:"⊆",supe:"⊇",oplus:"⊕",otimes:"⊗",perp:"⊥",sdot:"⋅",Alpha:"Α",Beta:"Β",Gamma:"Γ",Delta:"Δ",Epsilon:"Ε",Zeta:"Ζ",Eta:"Η",Theta:"Θ",Iota:"Ι",Kappa:"Κ",Lambda:"Λ",Mu:"Μ",Nu:"Ν",Xi:"Ξ",Omicron:"Ο",Pi:"Π",Rho:"Ρ",Sigma:"Σ",Tau:"Τ",Upsilon:"Υ",Phi:"Φ",Chi:"Χ",Psi:"Ψ",Omega:"Ω",alpha:"α",beta:"β",gamma:"γ",delta:"δ",epsilon:"ε",zeta:"ζ",eta:"η",theta:"θ",iota:"ι",kappa:"κ",lambda:"λ",mu:"μ",nu:"ν",xi:"ξ",omicron:"ο",pi:"π",rho:"ρ",sigmaf:"ς",sigma:"σ",tau:"τ",upsilon:"υ",phi:"φ",chi:"χ",psi:"ψ",omega:"ω",thetasym:"ϑ",upsih:"ϒ",piv:"ϖ",OElig:"Œ",oelig:"œ",Scaron:"Š",scaron:"š",Yuml:"Ÿ",fnof:"ƒ",circ:"ˆ",tilde:"˜",ensp:" ",emsp:" ",thinsp:" ",zwnj:"‌",zwj:"‍",lrm:"‎",rlm:"‏",ndash:"–",mdash:"—",lsquo:"‘",rsquo:"’",sbquo:"‚",ldquo:"“",rdquo:"”",bdquo:"„",dagger:"†",Dagger:"‡",bull:"•",hellip:"…",permil:"‰",prime:"′",Prime:"″",lsaquo:"‹",rsaquo:"›",oline:"‾",euro:"€",trade:"™",larr:"←",uarr:"↑",rarr:"→",darr:"↓",harr:"↔",crarr:"↵",lceil:"⌈",rceil:"⌉",lfloor:"⌊",rfloor:"⌋",loz:"◊",spades:"♠",clubs:"♣",hearts:"♥",diams:"♦"}),t.entityMap=t.HTML_ENTITIES});Da.XML_ENTITIES,Da.HTML_ENTITIES,Da.entityMap;var Oa=Dr.NAMESPACE,zt=/[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/,ar=new RegExp("[\\-\\.0-9"+zt.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"),Ra=new RegExp("^"+zt.source+ar.source+"*(?::"+zt.source+ar.source+"*)?$"),Ma=0,Na=1,Ua=2,Ba=3,Fa=4,ja=5,Ha=6,qa=7;function Va(e,t){this.message=e,this.locator=t,Error.captureStackTrace&&Error.captureStackTrace(this,Va)}function Wa(){}function Ga(e,t){return t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber,t}function za(e,t,i){for(var n=e.tagName,r=null,a=e.length;a--;){var s=e[a],o=s.qName,u=s.value,o=0<(c=o.indexOf(":"))?(l=s.prefix=o.slice(0,c),d=o.slice(c+1),"xmlns"===l&&d):(l=null,"xmlns"===(d=o)&&"");s.localName=d,!1!==o&&(null==r&&(r={},Xa(i,i={})),i[o]=r[o]=u,s.uri=Oa.XMLNS,t.startPrefixMapping(o,u))}for(var l,a=e.length;a--;)(l=(s=e[a]).prefix)&&("xml"===l&&(s.uri=Oa.XML),"xmlns"!==l&&(s.uri=i[l||""]));var c,d=0<(c=n.indexOf(":"))?(l=e.prefix=n.slice(0,c),e.localName=n.slice(c+1)):(l=null,e.localName=n),h=e.uri=i[l||""];if(t.startElement(h,d,n,e),!e.closed)return e.currentNSMap=i,e.localNSMap=r,1;if(t.endElement(h,d,n),r)for(l in r)t.endPrefixMapping(l)}function Xa(e,t){for(var i in e)t[i]=e[i]}function Ka(){this.attributeNames={}}(Va.prototype=new Error).name=Va.name,Wa.prototype={parse:function(e,t,i){var n=this.domBuilder;n.startDocument(),Xa(t,t={}),function(i,e,n,r,a){function s(e){var t=e.slice(1,-1);return t in n?n[t]:"#"===t.charAt(0)?65535<(t=parseInt(t.substr(1).replace("x","0x")))?(t-=65536,String.fromCharCode(55296+(t>>10),56320+(1023&t))):String.fromCharCode(t):(a.error("entity not found:"+e),e)}function t(e){var t;f<e&&(t=i.substring(f,e).replace(/&#?\w+;/g,s),d&&o(f),r.characters(t,0,e-f),f=e)}function o(e,t){for(;l<=e&&(t=c.exec(i));)u=t.index,l=u+t[0].length,d.lineNumber++;d.columnNumber=e-u+1}var u=0,l=0,c=/.*(?:\r\n?|\n)|.*$/g,d=r.locator,h=[{currentNSMap:e}],p={},f=0;for(;;){try{var m,g,y=i.indexOf("<",f);if(y<0)return i.substr(f).match(/^\s*$/)||(m=r.doc,g=m.createTextNode(i.substr(f)),m.appendChild(g),r.currentElement=g);switch(f<y&&t(y),i.charAt(y+1)){case"/":var v=i.indexOf(">",y+3),_=i.substring(y+2,v).replace(/[ \t\n\r]+$/g,""),b=h.pop();v<0?(_=i.substring(y+2).replace(/[\s<].*/,""),a.error("end tag name: "+_+" is not complete:"+b.tagName),v=y+1+_.length):_.match(/\s</)&&(_=_.replace(/[\s<].*/,""),a.error("end tag name: "+_+" maybe not complete"),v=y+1+_.length);var T=b.localNSMap,S=b.tagName==_;if(S||b.tagName&&b.tagName.toLowerCase()==_.toLowerCase()){if(r.endElement(b.uri,b.localName,_),T)for(var w in T)r.endPrefixMapping(w);S||a.fatalError("end tag name: "+_+" is not match the current start tagName:"+b.tagName)}else h.push(b);v++;break;case"?":d&&o(y),v=function(e,t,i){var n=e.indexOf("?>",t);if(n){t=e.substring(t,n).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);return t?(t[0].length,i.processingInstruction(t[1],t[2]),n+2):-1}return-1}(i,y,r);break;case"!":d&&o(y),v=function(e,t,i,n){{if("-"===e.charAt(t+2)){if("-"!==e.charAt(t+3))return-1;var r=e.indexOf("--\x3e",t+4);return t<r?(i.comment(e,t+4,r-t-4),r+3):(n.error("Unclosed comment"),-1)}if("CDATA["==e.substr(t+3,6)){r=e.indexOf("]]>",t+9);return i.startCDATA(),i.characters(e,t+9,r-t-9),i.endCDATA(),r+3}var a=function(e,t){var i,n=[],r=/'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;r.lastIndex=t,r.exec(e);for(;i=r.exec(e);)if(n.push(i),i[1])return n}(e,t),n=a.length;if(1<n&&/!doctype/i.test(a[0][0])){r=a[1][0],e=!1,t=!1;3<n&&(/^public$/i.test(a[2][0])?(e=a[3][0],t=4<n&&a[4][0]):/^system$/i.test(a[2][0])&&(t=a[3][0]));n=a[n-1];return i.startDTD(r,e,t),i.endDTD(),n.index+n[0].length}}return-1}(i,y,r,a);break;default:d&&o(y);var E=new Ka,k=h[h.length-1].currentNSMap,v=function(e,t,n,i,r,a){function s(e,t,i){n.attributeNames.hasOwnProperty(e)&&a.fatalError("Attribute "+e+" redefined"),n.addValue(e,t,i)}var o,u=++t,l=Ma;for(;;){var c=e.charAt(u);switch(c){case"=":if(l===Na)o=e.slice(t,u),l=Ba;else{if(l!==Ua)throw new Error("attribute equal must after attrName");l=Ba}break;case"'":case'"':if(l===Ba||l===Na){if(l===Na&&(a.warning('attribute value must after "="'),o=e.slice(t,u)),t=u+1,!(0<(u=e.indexOf(c,t))))throw new Error("attribute value no end '"+c+"' match");d=e.slice(t,u).replace(/&#?\w+;/g,r),s(o,d,t-1),l=ja}else{if(l!=Fa)throw new Error('attribute value must after "="');d=e.slice(t,u).replace(/&#?\w+;/g,r),s(o,d,t),a.warning('attribute "'+o+'" missed start quot('+c+")!!"),t=u+1,l=ja}break;case"/":switch(l){case Ma:n.setTagName(e.slice(t,u));case ja:case Ha:case qa:l=qa,n.closed=!0;case Fa:case Na:case Ua:break;default:throw new Error("attribute invalid close char('/')")}break;case"":return a.error("unexpected end of input"),l==Ma&&n.setTagName(e.slice(t,u)),u;case">":switch(l){case Ma:n.setTagName(e.slice(t,u));case ja:case Ha:case qa:break;case Fa:case Na:"/"===(d=e.slice(t,u)).slice(-1)&&(n.closed=!0,d=d.slice(0,-1));case Ua:l===Ua&&(d=o),l==Fa?(a.warning('attribute "'+d+'" missed quot(")!'),s(o,d.replace(/&#?\w+;/g,r),t)):(Oa.isHTML(i[""])&&d.match(/^(?:disabled|checked|selected)$/i)||a.warning('attribute "'+d+'" missed value!! "'+d+'" instead!!'),s(d,d,t));break;case Ba:throw new Error("attribute value missed!!")}return u;case"€":c=" ";default:if(c<=" ")switch(l){case Ma:n.setTagName(e.slice(t,u)),l=Ha;break;case Na:o=e.slice(t,u),l=Ua;break;case Fa:var d=e.slice(t,u).replace(/&#?\w+;/g,r);a.warning('attribute "'+d+'" missed quot(")!!'),s(o,d,t);case ja:l=Ha}else switch(l){case Ua:n.tagName,Oa.isHTML(i[""])&&o.match(/^(?:disabled|checked|selected)$/i)||a.warning('attribute "'+o+'" missed value!! "'+o+'" instead2!!'),s(o,o,t),t=u,l=Na;break;case ja:a.warning('attribute space is required"'+o+'"!!');case Ha:l=Na,t=u;break;case Ba:l=Fa,t=u;break;case qa:throw new Error("elements closed character '/' and '>' must be connected to")}}u++}}(i,y,E,k,s,a),C=E.length;if(!E.closed&&function(e,t,i,n){var r=n[i];null==r&&((r=e.lastIndexOf("</"+i+">"))<t&&(r=e.lastIndexOf("</"+i)),n[i]=r);return r<t}(i,v,E.tagName,p)&&(E.closed=!0,n.nbsp||a.warning("unclosed xml attribute")),d&&C){for(var I=Ga(d,{}),x=0;x<C;x++){var A=E[x];o(A.offset),A.locator=Ga(d,{})}r.locator=I,za(E,r,k)&&h.push(E),r.locator=d}else za(E,r,k)&&h.push(E);Oa.isHTML(E.uri)&&!E.closed?v=function(e,t,i,n,r){if(/^(?:script|textarea)$/i.test(i)){var a=e.indexOf("</"+i+">",t),e=e.substring(t+1,a);if(/[&<]/.test(e))return/^script$/i.test(i)||(e=e.replace(/&#?\w+;/g,n)),r.characters(e,0,e.length),a}return t+1}(i,v,E.tagName,s,r):v++}}catch(e){if(e instanceof Va)throw e;a.error("element parse error: "+e),v=-1}f<v?f=v:t(Math.max(y,f)+1)}}(e,t,i,n,this.errorHandler),n.endDocument()}},Ka.prototype={setTagName:function(e){if(!Ra.test(e))throw new Error("invalid tagName:"+e);this.tagName=e},addValue:function(e,t,i){if(!Ra.test(e))throw new Error("invalid attribute:"+e);this.attributeNames[e]=this.length,this[this.length++]={qName:e,value:t,offset:i}},length:0,getLocalName:function(e){return this[e].localName},getLocator:function(e){return this[e].locator},getQName:function(e){return this[e].qName},getURI:function(e){return this[e].uri},getValue:function(e){return this[e].value}};var x={XMLReader:Wa,ParseError:Va},Ya=U.DOMImplementation,Qa=Dr.NAMESPACE,$a=x.ParseError,Ja=x.XMLReader;function Za(e){this.options=e||{locator:{}}}function es(){this.cdata=!1}function ts(e,t){t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber}function is(e){if(e)return"\n@"+(e.systemId||"")+"#[line:"+e.lineNumber+",col:"+e.columnNumber+"]"}
vendor: 2,968 bytes, line 4716
4716function ns(e,t,i){return"string"==typeof e?e.substr(t,i):e.length>=t+i||t?new java.lang.String(e,t,i)+"":e}function rs(e,t){(e.currentElement||e.doc).appendChild(t)}Za.prototype.parseFromString=function(e,t){var i=this.options,n=new Ja,r=i.domBuilder||new es,a=i.errorHandler,s=i.locator,o=i.xmlns||{},u=/\/x?html?$/.test(t),t=u?Da.HTML_ENTITIES:Da.XML_ENTITIES;return s&&r.setDocumentLocator(s),n.errorHandler=function(n,e,r){if(!n){if(e instanceof es)return e;n=e}var a={},s=n instanceof Function;function t(t){var i=n[t];!i&&s&&(i=2==n.length?function(e){n(t,e)}:n),a[t]=i?function(e){i("[xmldom "+t+"]\t"+e+is(r))}:function(){}}return r=r||{},t("warning"),t("error"),t("fatalError"),a}(a,r,s),n.domBuilder=i.domBuilder||r,u&&(o[""]=Qa.HTML),o.xml=o.xml||Qa.XML,e&&"string"==typeof e?n.parse(e,o,t):n.errorHandler.error("invalid doc source"),r.doc},es.prototype={startDocument:function(){this.doc=(new Ya).createDocument(null,null,null),this.locator&&(this.doc.documentURI=this.locator.systemId)},startElement:function(e,t,i,n){var r=this.doc,a=r.createElementNS(e,i||t),s=n.length;rs(this,a),this.currentElement=a,this.locator&&ts(this.locator,a);for(var o=0;o<s;o++){var e=n.getURI(o),u=n.getValue(o),i=n.getQName(o),l=r.createAttributeNS(e,i);this.locator&&ts(n.getLocator(o),l),l.value=l.nodeValue=u,a.setAttributeNode(l)}},endElement:function(e,t,i){var n=this.currentElement;n.tagName,this.currentElement=n.parentNode},startPrefixMapping:function(e,t){},endPrefixMapping:function(e){},processingInstruction:function(e,t){t=this.doc.createProcessingInstruction(e,t);this.locator&&ts(this.locator,t),rs(this,t)},ignorableWhitespace:function(e,t,i){},characters:function(e,t,i){var n;(e=ns.apply(this,arguments))&&(n=this.cdata?this.doc.createCDATASection(e):this.doc.createTextNode(e),this.currentElement?this.currentElement.appendChild(n):/^\s*$/.test(e)&&this.doc.appendChild(n),this.locator&&ts(this.locator,n))},skippedEntity:function(e){},endDocument:function(){this.doc.normalize()},setDocumentLocator:function(e){(this.locator=e)&&(e.lineNumber=0)},comment:function(e,t,i){e=ns.apply(this,arguments);e=this.doc.createComment(e);this.locator&&ts(this.locator,e),rs(this,e)},startCDATA:function(){this.cdata=!0},endCDATA:function(){this.cdata=!1},startDTD:function(e,t,i){var n=this.doc.implementation;n&&n.createDocumentType&&(i=n.createDocumentType(e,t,i),this.locator&&ts(this.locator,i),rs(this,i),this.doc.doctype=i)},warning:function(e){},error:function(e){},fatalError:function(e){throw new $a(e,this.locator)}},"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(e){es.prototype[e]=function(){return null}});function as(e){return!!e&&"object"==typeof e}function ss(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];return t.reduce(function(t,i){return"object"!=typeof i||Object.keys(i).forEac
4716h(function(e){Array.isArray(t[e])&&Array.isArray(i[e])?t[e]=t[e].concat(i[e]):as(t[e])&&as(i[e])?t[e]=ss(t[e],i[e]):t[e]=i[e]}),t},{})}function os(t){return Object.keys(t).map(function(e){return t[e]})}function us(e){return e.reduce(function(e,t){return e.concat(t)},[])}function ls(e){if(!e.length)return[];for(var t=[],i=0;i<e.length;i++)t.push(e[i]);return t}function cs(e,t){for(var i=0;i<e.length;i++)if(t(e[i]))return i;return-1}function ds(e){var t=e.baseUrl,i=void 0===(n=e.source)?"":n,n=void 0===(n=e.range)?"":n,e=void 0===(e=e.indexRange)?"":e,i={uri:i,resolvedUri:ir((void 0===t?"":t)||"",i)};return(n||e)&&(n=(n||e).split("-"),e=window.BigInt?window.BigInt(n[0]):parseInt(n[0],10),n=window.BigInt?window.BigInt(n[1]):parseInt(n[1],10),e<Number.MAX_SAFE_INTEGER&&"bigint"==typeof e&&(e=Number(e)),"bigint"==typeof(n="bigint"==typeof(n=n<Number.MAX_SAFE_INTEGER&&"bigint"==typeof n?Number(n):n)||"bigint"==typeof e?window.BigInt(n)-window.BigInt(e)+window.BigInt(1):n-e+1)&&n<Number.MAX_SAFE_INTEGER&&(n=Number(n)),i.byterange={length:n,offset:e}),i}function hs(e){return e&&"number"!=typeof e&&(e=parseInt(e,10)),isNaN(e)?null:e}function ps(e){var a,t=e.type,i=e.duration,n=e.timescale,r=void 0===n?1:n,s=e.periodDuration,o=e.sourceDuration,e=function(e,t){for(var i=[],n=e;n<t;n++)i.push(n);return i}((n=ho[t](e)).start,n.end).map((a=e,function(e){var t=a.duration,i=a.timescale,n=a.periodStart,r=a.startNumber;return{number:(void 0===r?1:r)+e,duration:t/(void 0===i?1:i),timeline:n,time:e*t}}));return"static"===t&&(e[t=e.length-1].duration=("number"==typeof s?s:o)-i/r*t),e}function fs(e){var t=e.baseUrl,i=void 0===(u=e.initialization)?{}:u,n=e.sourceDuration,r=void 0===(o=e.indexRange)?"":o,a=e.periodStart,s=e.presentationTime,o=void 0===(u=e.number)?0:u,u=e.duration;if(!t)throw new Error(uo);return i=ds({baseUrl:t,source:i.sourceURL,range:i.range}),(r=ds({baseUrl:t,source:t,indexRange:r})).map=i,u?(e=ps(e)).length&&(r.duration=e[0].duration,r.timeline=e[0].timeline):n&&(r.duration=n,r.timeline=a),r.presentationTime=s||a,r.number=o,[r]}function ms(e,t,i){for(var n=e.sidx.map||null,r=e.sidx.duration,a=e.timeline||0,s=(s=e.sidx.byterange).offset+s.length,o=t.timescale,u=t.references.filter(function(e){return 1!==e.referenceType}),l=[],c=e.endList?"static":"dynamic",d=e.sidx.timeline,h=d,p=e.mediaSequence||0,f="bigint"==typeof t.firstOffset?window.BigInt(s)+t.firstOffset:s+t.firstOffset,m=0;m<u.length;m++){var g=t.references[m],y=g.referencedSize,v=g.subsegmentDuration,g=void 0,g="bigint"==typeof f?f+window.BigInt(y)-window.BigInt(1):f+y-1,g=fs({baseUrl:i,timescale:o,timeline:a,periodStart:d,presentationTime:h,number:p,duration:v,sourceDuration:r,indexRange:f+"-"+g,type:c})[0];n&&(g.map=n),l.push(g),f+="bigint"==typeof f?window.BigInt(y):y,h+=v/o,p++}return e.segments=l,e}function gs(e){return i=function(e){return e.timeline},os(e.reduce(function(t,e){return e.forEach(function(e){t[i(e)]=e}),t},{})).sort(function(e,t){return e.timeline>t.timeline?1:-1});var i}function ys(e){var r,a,s=[];return r=e,a=function(e,t,i,n){s=s.concat(e.playlists||[])},po.forEach(function(e){for(var t in r.mediaGroups[e])for(var i in r.mediaGroups[e][t]){var n=r.mediaGroups[e][t][i];a(n,e,t,i)}}),s}function vs(e){var i=e.playlist,e=e.mediaSequence;i.mediaSequence=e,i.segments.forEach(function(e,t){e.number=i.mediaSequence+t})}function _s(e){var r,a,t=e.oldManifest,i=e.newManifest,n=t.playlists.concat(ys(t)),e=i.playlists.concat(ys(i));return i.timelineStarts=gs([t.timelineStarts,i.timelineStarts]),n={oldPlaylists:n,newPlaylists:e,timelineStarts:i.timelineStarts},r=n.oldPlaylists,e=n.newPlaylists,a=n.timelineStarts,e.forEach(function(t){t.discontinuitySequence=cs(a,function(e){return e.timeline===t.timeline});var e=function(e,t){for(var i=0;i<e.length;i++)if(e[i].attributes.NAME===t)return e[i];return null}(r,t.attributes.NAME);if(e&&!t.sidx){var i=t.segments[0],n=cs(e.segments,function(e){return Math.abs(e.presentationTime-i.presentationTime)<1/60});if(-1===n)return vs({playlist:t,mediaSequence:e.mediaSequence+e.segments.length}),t.segments[0].discontinuity=!0,t.discontinuityStarts.unshift(0),void((!e.segments.length&&t.timeline>e.timeline||e.segments.length&&t.timeline>e.segments[e.segments.length-1].timeline)&&t.discontinuitySequence--);e.segments[n].discontinuity&&!i.discontinuity&&(i.discontinuity=!0,t.discontinuityStarts.unshift(0),t.discontinuitySequence--),vs({playlist:t,mediaSequence:e.segments[n].number})}}),i}function bs(e){return e&&e.uri+"-"+(t=e.byterange,e="bigint"==typeof t.offset||"bigint"==typeof t.length?window.BigInt(t.offset)+window.BigInt(t.length)-window.BigInt(1):t.offset+t.length-1,t.offset+"-"+e);var t}function Ts(e){return os(e.reduce(function(e,t){var i,n=t.attributes.id+(t.attributes.lang||"");return e[n]?(t.segments&&(t.segments[0]&&(t.segments[0].discontinuity=!0),(i=e[n].segments).push.apply(i,t.segments)),t.attributes.contentProtection&&(e[n].attributes.contentProtection=t.attributes.contentProtection)):(e[n]=t,e[n].attributes.timelineStarts=[]),e[n].attributes.timelineStarts.push({start:t.attributes.periodStart,timeline:t.attributes.periodStart}),e},{})).map(function(e){var t,n;return e.discontinuityStarts=(t=e.segments||[],n="discontinuity",t.reduce(function(e,t,i){return t[n]&&e.push(i),e},[])),e})}function Ss(e,t){var i=bs(e.sidx);return(i=i&&t[i]&&t[i].sidx)&&ms(e,i,e.sidx.resolvedUri),e}function ws(e,h,p){var f;return void 0===h&&(h={}),void 0===p&&(p=!1),e=e.reduce(function(e,t){var i=t.attributes.role&&t.attributes.role.value||"",n=t.attributes.lang||"",r=t.attributes.label||"main";e[r=n&&!t.attributes.label?t.attributes.lang+(i?" ("+i+")":""):r]||(e[r]={language:n,autoselect:!0,default:"main"===i,playlists:[],uri:""});var a,s,o,u,l,c,d,u=Ss((s=p,o=(a=t).attributes,u=a.segments,l=a.sidx,c=a.mediaSequence,d=a.discontinuitySequence,n=a.discontinuityStarts,u={attributes:((a={NAME:o.id,BANDWIDTH:o.bandwidth,CODECS:o.codecs})["PROGRAM-ID"]=1,a),uri:"",endList:"static"===o.type,timeline:o.periodStart,resolvedUri:"",targetDuration:o.duration,discontinuitySequence:d,discontinuityStarts:n,timelineStarts:o.timelineStarts,mediaSequence:c,segments:u},o.contentProtection&&(u.contentProtection=o.contentProtection),l&&(u.sidx=l),s&&(u.attributes.AUDIO="audio",u.attributes.SUBTITLES="subs"),u),h);return e[r].playlists.push(u),"undefined"==typeof f&&"main"===i&&((f=t).default=!0),e},{}),f||(e[Object.keys(e)[0]].default=!0),e}function Es(e){var t=e.attributes,i=e.segments,n=e.sidx,r=e.discontinuityStarts,i={attributes:((e={NAME:t.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:t.width,height:t.height},CODECS:t.codecs,BANDWIDTH:t.bandwidth})["PROGRAM-ID"]=1,e),uri:"",endList:"static"===t.type,timeline:t.periodStart,resolvedUri:"",targetDuration:t.duration,discontinuityStarts:r,timelineStarts:t.timelineStarts,segments:i};return t.contentProtection&&(i.contentProtection=t.contentProtection),n&&(i.sidx=n),i}function ks(e){return"video/mp4"===(e=e.attributes).mimeType||"video/webm"===e.mimeType||"video"===e.contentType}function Cs(e){return"audio/mp4"===(e=e.attributes).mimeType||"audio/webm"===e.mimeType||"audio"===e.contentType}function Is(e){return"text/vtt"===(e=e.attributes).mimeType||"text"===e.contentType}function xs(i){return i?Object.keys(i).reduce(function(e,t){t=i[t];return e.concat(t.playlists)},[]):[]}function As(e){var t=e.dashPlaylists,i=e.locations,n=void 0===(c=e.sidxMapping)?{}:c,r=e.previousManifest;if(!t.length)return{};var a=(d=t[0].attributes).sourceDuration,s=d.type,o=d.suggestedPresentationDelay,u=d.minimumUpdatePeriod,l=Ts(t.filter(ks)).map(Es),c=Ts(t.filter(Cs)),e=Ts(t.filter(Is)),d=t.map(function(e){return e.attributes.captionServices}
4716).filter(Boolean),a={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:((t={AUDIO:{},VIDEO:{}})["CLOSED-CAPTIONS"]={},t.SUBTITLES={},t),uri:"",duration:a,playlists:function(e,t){if(void 0===t&&(t={}),!Object.keys(t).length)return e;for(var i in e)e[i]=Ss(e[i],t);return e}(l,n)};0<=u&&(a.minimumUpdatePeriod=1e3*u),i&&(a.locations=i),"dynamic"===s&&(a.suggestedPresentationDelay=o);var h,p,o=0===a.playlists.length,o=c.length?ws(c,n,o):null,n=e.length?(void 0===(h=n)&&(h={}),e.reduce(function(e,t){var i=t.attributes.lang||"text";return e[i]||(e[i]={language:i,default:!1,autoselect:!1,playlists:[],uri:""}),e[i].playlists.push(Ss(function(e){var t=e.attributes,i=e.segments,n=e.mediaSequence,r=e.discontinuityStarts,a=e.discontinuitySequence;"undefined"==typeof i&&(i=[{uri:t.baseUrl,timeline:t.periodStart,resolvedUri:t.baseUrl||"",duration:t.sourceDuration,number:0}],t.duration=t.sourceDuration);(e={NAME:t.id,BANDWIDTH:t.bandwidth})["PROGRAM-ID"]=1;return t.codecs&&(e.CODECS=t.codecs),{attributes:e,uri:"",endList:"static"===t.type,timeline:t.periodStart,resolvedUri:t.baseUrl||"",targetDuration:t.duration,timelineStarts:t.timelineStarts,discontinuityStarts:r,discontinuitySequence:a,mediaSequence:n,segments:i}}(t),h)),e},{})):null,l=(e=l.concat(xs(o),xs(n))).map(function(e){return e.timelineStarts});return a.timelineStarts=gs(l),e=e,p=a.timelineStarts,e.forEach(function(t){t.mediaSequence=0,t.discontinuitySequence=cs(p,function(e){return e.timeline===t.timeline}),t.segments&&t.segments.forEach(function(e,t){e.number=t})}),o&&(a.mediaGroups.AUDIO.audio=o),n&&(a.mediaGroups.SUBTITLES.subs=n),d.length&&(a.mediaGroups["CLOSED-CAPTIONS"].cc=d.reduce(function(n,e){return e&&e.forEach(function(e){var t=e.channel,i=e.language;n[i]={autoselect:!1,default:!1,instreamId:t,language:i},e.hasOwnProperty("aspectRatio")&&(n[i].aspectRatio=e.aspectRatio),e.hasOwnProperty("easyReader")&&(n[i].easyReader=e.easyReader),e.hasOwnProperty("3D")&&(n[i]["3D"]=e["3D"])}),n},{})),r?_s({oldManifest:r,newManifest:a}):a}function Ps(e,t){for(var i,n,r,a,s,o,u=e.type,l=e.minimumUpdatePeriod,c=void 0===l?0:l,d=void 0===(l=e.media)?"":l,h=e.sourceDuration,p=void 0===(l=e.timescale)?1:l,f=void 0===(l=e.startNumber)?1:l,m=e.periodStart,g=[],y=-1,v=0;v<t.length;v++){var _=t[v],b=_.d,T=_.r||0,S=_.t||0;y<0&&(y=S),S&&y<S&&(y=S);var w,E=void 0;E=T<0?(w=v+1)===t.length?"dynamic"===u&&0<c&&0<d.indexOf("$Number$")?(i=y,n=b,_=o=s=a=r=void 0,r=(S=e).NOW,a=S.clientOffset,s=S.availabilityStartTime,o=S.timescale,_=S.periodStart,S=S.minimumUpdatePeriod,Math.ceil((((r+a)/1e3+(void 0===S?0:S)-(s+(void 0===_?0:_)))*(void 0===o?1:o)-i)/n)):(h*p-y)/b:(t[w].t-y)/b:T+1;for(var k=f+g.length+E,C=f+g.length;C<k;)g.push({number:C,duration:b/p,time:y,timeline:m}),y+=b,C++}return g}function Ls(e,t){return e.replace(fo,(r=t,function(e,t,i,n){if("$$"===e)return"$";if("undefined"==typeof r[t])return e;e=""+r[t];return"RepresentationID"===t||(n=i?parseInt(n,10):1)<=e.length?e:new Array(n-e.length+1).join("0")+e}));var r}function Ds(r,e){var a={RepresentationID:r.id,Bandwidth:r.bandwidth||0},t=void 0===(t=r.initialization)?{sourceURL:"",range:""}:t,s=ds({baseUrl:r.baseUrl,source:Ls(t.sourceURL,a),range:t.range});return(t=e,(e=r).duration||t?e.duration?ps(e):Ps(e,t):[{number:e.startNumber||1,duration:e.sourceDuration,time:0,timeline:e.periodStart}]).map(function(e){a.Number=e.number,a.Time=e.time;var t=Ls(r.media||"",a),i=r.timescale||1,n=r.presentationTimeOffset||0,i=r.periodStart+(e.time-n)/i;return{uri:t,timeline:e.timeline,duration:e.duration,resolvedUri:ir(r.baseUrl||"",t),map:s,number:e.number,presentationTime:i}})}function Os(r,e){var t=r.duration,i=void 0===(i=r.segmentUrls)?[]:i,a=r.periodStart;if(!t&&!e||t&&e)throw new Error(lo);var n,s=i.map(function(e){return i=e,e=(t=r).baseUrl,t=t.initialization,t=ds({baseUrl:e,source:(t=void 0===t?{}:t).sourceURL,range:t.range}),(i=ds({baseUrl:e,source:i.media,range:i.mediaRange})).map=t,i;var t,i});return t&&(n=ps(r)),(n=e?Ps(r,e):n).map(function(e,t){if(s[t]){var i=s[t],n=r.timescale||1,t=r.presentationTimeOffset||0;return i.timeline=e.timeline,i.duration=e.duration,i.number=e.number,i.presentationTime=a+(e.time-t)/n,i}}).filter(function(e){return e})}function Rs(e){var t,i=e.attributes,n=e.segmentInfo;n.template?(a=Ds,t=ss(i,n.template)):n.base?(a=fs,t=ss(i,n.base)):n.list&&(a=Os,t=ss(i,n.list));var r={attributes:i};if(!a)return r;var a,e=a(t,n.segmentTimeline);return t.duration?(i=t.duration,a=t.timescale,t.duration=i/(void 0===a?1:a)):e.length?t.duration=e.reduce(function(e,t){return Math.max(e,Math.ceil(t.duration))},0):t.duration=0,r.attributes=t,r.segments=e,n.base&&t.indexRange&&(r.sidx=e[0],r.segments=[]),r}function Ms(e,t){return ls(e.childNodes).filter(function(e){return e.tagName===t})}function Ns(e){return e.textContent.trim()}function Us(e){if(!(r=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(e)))return 0;var t=(a=r.slice(1))[0],i=a[1],n=a[2],e=a[3],r=a[4],a=a[5];
4716return 31536e3*parseFloat(t||0)+2592e3*parseFloat(i||0)+86400*parseFloat(n||0)+3600*parseFloat(e||0)+60*parseFloat(r||0)+parseFloat(a||0)}function Bs(e){return e&&e.attributes?ls(e.attributes).reduce(function(e,t){var i=mo[t.name]||mo.DEFAULT;return e[t.name]=i(t.value),e},{}):{}}function Fs(e,i){return i.length?us(e.map(function(t){return i.map(function(e){return ir(t,Ns(e))})})):e}function js(e){var t=Ms(e,"SegmentTemplate")[0],i=Ms(e,"SegmentList")[0],n=i&&Ms(i,"SegmentURL").map(function(e){return ss({tag:"SegmentURL"},Bs(e))}),r=Ms(e,"SegmentBase")[0],e=(a=i||t)&&Ms(a,"SegmentTimeline")[0],a=(a=i||r||t)&&Ms(a,"Initialization")[0];(t=t&&Bs(t))&&a?t.initialization=a&&Bs(a):t&&t.initialization&&(t.initialization={sourceURL:t.initialization});var s={template:t,segmentTimeline:e&&Ms(e,"S").map(Bs),list:i&&ss(Bs(i),{segmentUrls:n,initialization:Bs(a)}),base:r&&ss(Bs(r),{initialization:Bs(a)})};return Object.keys(s).forEach(function(e){s[e]||delete s[e]}),s}function Hs(u,l,c){return function(e){var t=Bs(e),i=Fs(l,Ms(e,"BaseURL")),n=Ms(e,"Role")[0],n={role:Bs(n)},t=ss(u,t,n),n=Ms(e,"Accessibility")[0],n="urn:scte:dash:cc:cea-608:2015"===(n=Bs(n)).schemeIdUri?("string"!=typeof n.value?[]:n.value.split(";")).map(function(e){var t,i,n;return/^CC\d=/.test(n=e)?(i=(t=e.split("="))[0],n=t[1]):/^CC\d$/.test(e)&&(i=e),{channel:i,language:n}}):"urn:scte:dash:cc:cea-708:2015"===n.schemeIdUri?("string"!=typeof n.value?[]:n.value.split(";")).map(function(e){var t,i,n={channel:void 0,language:void 0,aspectRatio:1,easyReader:0,"3D":0};return/=/.test(e)?(t=(i=e.split("="))[0],i=void 0===(i=i[1])?"":i,n.channel=t,n.language=e,i.split(",").forEach(function(e){var t=e.split(":"),e=t[0],t=t[1];"lang"===e?n.language=t:"er"===e?n.easyReader=Number(t):"war"===e?n.aspectRatio=Number(t):"3D"===e&&(n["3D"]=Number(t))})):n.language=e,n.channel&&(n.channel="SERVICE"+n.channel),n}):void 0;n&&(t=ss(t,{captionServices:n}));n=Ms(e,"Label")[0];n&&n.childNodes.length&&(r=n.childNodes[0].nodeValue.trim(),t=ss(t,{label:r}));var r=Ms(e,"ContentProtection").reduce(function(e,t){var i=Bs(t),n=go[i.schemeIdUri];return n&&(e[n]={attributes:i},(t=Ms(t,"cenc:pssh")[0])&&(t=(t=Ns(t))&&or(t),e[n].pssh=t)),e},{});Object.keys(r).length&&(t=ss(t,{contentProtection:r}));var a,s,o,r=js(e),e=Ms(e,"Representation"),r=ss(c,r);return us(e.map((a=t,s=i,o=r,function(e){var t=Ms(e,"BaseURL"),t=Fs(s,t),i=ss(a,Bs(e)),n=js(e);return t.map(function(e){return{segmentInfo:ss(o,n),attributes:ss(i,{baseUrl:e})}})})))}}function qs(e,t){var i=t=void 0===t?{}:t,n=void 0===(a=i.manifestUri)?"":a,t=void 0===(r=i.NOW)?Date.now():r,r=void 0===(a=i.clientOffset)?0:a;if(!(i=Ms(e,"Period")).length)throw new Error(ao);var a=Ms(e,"Location"),s=Bs(e),e=Fs([n],Ms(e,"BaseURL"));s.type=s.type||"static",s.sourceDuration=s.mediaPresentationDuration||0,s.NOW=t,s.clientOffset=r,a.length&&(s.locations=a.map(Ns));var o,u,l=[];return i.forEach(function(e,t){var i,n=Bs(e),r=l[t-1];n.start=(i={attributes:n,priorPeriodAttributes:r?r.attributes:null,mpdType:s.type},t=i.attributes,r=i.priorPeriodAttributes,i=i.mpdType,"number"==typeof t.start?t.start:r&&"number"==typeof r.start&&"number"==typeof r.duration?r.start+r.duration:r||"static"!==i?null:0),l.push({node:e,attributes:n})}),{locations:s.locations,representationInfo:us(l.map((o=s,u=e,function(e,t){var i=Fs(u,Ms(e.node,"BaseURL")),n=ss(o,{periodStart:e.attributes.start});"number"==typeof e.attributes.duration&&(n.periodDuration=e.attributes.duration);var r=Ms(e.node,"AdaptationSet"),e=js(e.node);return us(r.map(Hs(n,i,e)))})))}}function Vs(e){if(""===e)throw new Error(so);var t,i,n=new ro;try{i=(t=n.parseFromString(e,"application/xml"))&&"MPD"===t.documentElement.tagName?t.documentElement:null}catch(e){}if(!i||i&&0<i.getElementsByTagName("parsererror").length)throw new Error(oo);return i}function Ws(e,t){void 0===t&&(t={});var i=qs(Vs(e),t),e=i.representationInfo.map(Rs);return As({dashPlaylists:e,locations:i.locations,sidxMapping:t.sidxMapping,previousManifest:t.previousManifest})}function Gs(e){return function(e){e=Ms(e,"UTCTiming")[0];if(!e)return null;var t=Bs(e);switch(t.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":t.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":t.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":t.method="DIRECT",t.value=Date.parse(t.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(co)}return t}(Vs(e))}function zs(e){return e instanceof Uint8Array?e:(Array.isArray(e)||(t=e,ArrayBuffer.isView(t))||e instanceof ArrayBuffer||(e="number"!=typeof e||"number"==typeof e&&e!=e?0:[e]),new Uint8Array(e&&e.buffer||e,e&&e.byteOffset||0,e&&e.byteLength||0));var t}function Xs(e,t){var i=void 0!==(t=(void 0===t?{}:t).le)&&t;e=bo(e="bigint"!=typeof e&&"number"!=typeof e||"number"==typeof e&&e!=e?0:e);
4716for(var n=(t=e,Math.ceil(t.toString(2).length/8)),r=new Uint8Array(new ArrayBuffer(n)),a=0;a<n;a++){var s=i?a:Math.abs(a+1-r.length);r[s]=Number(e/To[a]&bo(255)),e<0&&(r[s]=Math.abs(~r[s]),r[s]-=0===a?1:2)}return r}function Ks(e,t){if("string"!=typeof(e="string"!=typeof e&&e&&"function"==typeof e.toString?e.toString():e))return new Uint8Array;t||(e=unescape(encodeURIComponent(e)));for(var i=new Uint8Array(e.length),n=0;n<e.length;n++)i[n]=e.charCodeAt(n);return i}function Ys(i,e,t){var n=void 0===t?{}:t,r=void 0===(t=n.offset)?0:t,a=void 0===(n=n.mask)?[]:n;return i=zs(i),n=(e=zs(e)).every||Array.prototype.every,e.length&&i.length-r>=e.length&&n.call(e,function(e,t){return e===(a[t]?a[t]&i[r+t]:i[r+t])})}function Qs(e,t){return void 0===t&&(t=0),(e=zs(e)).length-t<10||!Ys(e,So,{offset:t})?t:Qs(e,t+=function(e,t){void 0===t&&(t=0);var i=(e=zs(e))[t+5],t=e[t+6]<<21|e[t+7]<<14|e[t+8]<<7|e[t+9];return(16&i)>>4?20+t:10+t}(e,t))}function $s(e){return"string"==typeof e?Ks(e):e}function Js(e,t,i){var n;void 0===i&&(i=!1),n=t,t=Array.isArray(n)?n.map($s):[$s(n)],e=zs(e);var r=[];if(!t.length)return r;for(var a=0;a<e.length;){var s=(e[a]<<24|e[a+1]<<16|e[a+2]<<8|e[a+3])>>>0,o=e.subarray(a+4,a+8);if(0==s)break;var u=a+s;if(u>e.length){if(i)break;u=e.length}s=e.subarray(a+8,u);Ys(o,t[0])&&(1===t.length?r.push(s):r.push.apply(r,Js(s,t.slice(1),i))),a=u}return r}function Zs(e,t,i,n){void 0===i&&(i=!0),void 0===n&&(n=!1);var r=function(e){for(var t=1,i=0;i<Eo.length&&!(e&Eo[i]);i++)t++;return t}(e[t]),a=e.subarray(t,t+r);return i&&((a=Array.prototype.slice.call(e,t,t+r))[0]^=Eo[r-1]),{length:r,value:function(n,e){var t=void 0===e?{}:e,e=t.signed,e=void 0!==e&&e,t=t.le,r=void 0!==t&&t;n=zs(n);t=r?"reduce":"reduceRight",t=(n[t]||Array.prototype[t]).call(n,function(e,t,i){i=r?i:Math.abs(i+1-n.length);return e+bo(t)*To[i]},bo(0));return!e||(e=To[n.length]/bo(2)-bo(1))<(t=bo(t))&&(t-=e,t-=e,t-=bo(2)),Number(t)}(a,{signed:n}),bytes:a}}function eo(e){return"string"==typeof e?e.match(/.{1,2}/g).map(eo):"number"==typeof e?Xs(e):e}function to(e,t,i){if(i>=t.length)return t.length;var n=Zs(t,i,!1);if(Ys(e.bytes,n.bytes))return i;var r=Zs(t,i+n.length);return to(e,t,i+r.length+r.value+n.length)}function io(e,t){var i;i=t,t=Array.isArray(i)?i.map(eo):[eo(i)],e=zs(e);var n=[];if(!t.length)return n;for(var r=0;r<e.length;){var a=Zs(e,r,!1),s=Zs(e,r+a.length),o=r+a.length+s.length;127===s.value&&(s.value=to(a,e,o),s.value!==e.length&&(s.value-=o));var u=o+s.value>e.length?e.length:o+s.value,u=e.subarray(o,u);Ys(t[0],a.bytes)&&(1===t.length?n.push(u):n=n.concat(io(u,t.slice(1)))),r+=a.length+s.length+u.length}return n}function no(e,t,i,n){void 0===n&&(n=1/0),e=zs(e),i=[].concat(i);for(var r,a=0,s=0;a<e.length&&(s<n||r);){var o=void 0;if(Ys(e.subarray(a),ko)?o=4:Ys(e.subarray(a),Co)&&(o=3),o){if(s++,r)return function(e){for(var t=[],i=1;i<e.length-2;)Ys(e.subarray(i,i+3),Io)&&(t.push(i+2),i++),i++;if(0===t.length)return e;for(var n=e.length-t.length,r=new Uint8Array(n),a=0,i=0;i<n;a++,i++)a===t[0]&&(a++,t.shift()),r[i]=e[a];return r}(e.subarray(r,a));var u=void 0;"h264"===t?u=31&e[a+o]:"h265"===t&&(u=e[a+o]>>1&63),-1!==i.indexOf(u)&&(r=a+o),a+=o+("h264"===t?1:2)}else a++}return e.subarray(0,0)}var ro={__DOMHandler:es,DOMParser:Za,DOMImplementation:U.DOMImplementation,XMLSerializer:U.XMLSerializer}.DOMParser,ao="INVALID_NUMBER_OF_PERIOD",so="DASH_EMPTY_MANIFEST",oo="DASH_INVALID_XML",uo="NO_BASE_URL",lo="SEGMENT_TIME_UNSPECIFIED",co="UNSUPPORTED_UTC_TIMING_SCHEME",ho={static:function(e){var t=e.duration,i=e.timescale,n=void 0===i?1:i,r=e.sourceDuration,i=e.periodDuration,e=hs(e.endNumber),n=t/n;return"number"==typeof e?{start:0,end:e}:"number"==typeof i?{start:0,end:i/n}:{start:0,end:r/n}},dynamic:function(e){var t=e.NOW,i=e.clientOffset,n=e.availabilityStartTime,r=e.timescale,a=void 0===r?1:r,s=e.duration,o=e.periodStart,u=void 0===o?0:o,r=e.minimumUpdatePeriod,o=void 0===r?0:r,r=e.timeShiftBufferDepth,r=void 0===r?1/0:r,e=hs(e.endNumber),i=(t+i)/1e3,u=n+u,o=Math.ceil((i+o-u)*a/s),r=Math.floor((i-u-r)*a/s),s=Math.floor((i-u)*a/s);return{start:Math.max(0,r),end:"number"==typeof e?e:Math.min(o,s)}}},po=["AUDIO","SUBTITLES"],fo=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,mo={mediaPresentationDuration:Us,availabilityStartTime:function(e){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(e=e)&&(e+="Z"),Date.parse(e)/1e3},minimumUpdatePeriod:Us,suggestedPresentationDelay:Us,type:function(e){return e},timeShiftBufferDepth:Us,start:Us,width:function(e){return parseInt(e,10)},height:function(e){return parseInt(e,10)},bandwidth:function(e){return parseInt(e,10)},startNumber:function(e){return parseInt(e,10)},timescale:function(e){return parseInt(e,10)},presentationTimeOffset:function(e){return parseInt(e,10)},duration:function(e){var t=parseInt(e,10);return isNaN(t)?Us(e):t},d:function(e){return parseInt(e,10)},t:function(e){return parseInt(e,10)},r:function(e){return parseInt(e,10)},DEFAULT:function(e){return e}},go={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},yo=Math.pow(2,32),vo=function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);return t.getBigUint64?(e=t.getBigUint64(0))<Number.MAX_SAFE_INTEGER?
4716Number(e):e:t.getUint32(0)*yo+t.getUint32(4)},_o=function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),references:[],referenceId:t.getUint32(4),timescale:t.getUint32(8)},n=12;0===i.version?(i.earliestPresentationTime=t.getUint32(n),i.firstOffset=t.getUint32(n+4),n+=8):(i.earliestPresentationTime=vo(e.subarray(n)),i.firstOffset=vo(e.subarray(n+8)),n+=16);var r=t.getUint16(n+=2);for(n+=2;0<r;n+=12,r--)i.references.push({referenceType:(128&e[n])>>>7,referencedSize:2147483647&t.getUint32(n),subsegmentDuration:t.getUint32(n+4),startsWithSap:!!(128&e[n+8]),sapType:(112&e[n+8])>>>4,sapDeltaTime:268435455&t.getUint32(n+8)});return i},bo=window.BigInt||Number,To=[bo("0x1"),bo("0x100"),bo("0x10000"),bo("0x1000000"),bo("0x100000000"),bo("0x10000000000"),bo("0x1000000000000"),bo("0x100000000000000"),bo("0x10000000000000000")],So=zs([73,68,51]),wo={EBML:zs([26,69,223,163]),DocType:zs([66,130]),Segment:zs([24,83,128,103]),SegmentInfo:zs([21,73,169,102]),Tracks:zs([22,84,174,107]),Track:zs([174]),TrackNumber:zs([215]),DefaultDuration:zs([35,227,131]),TrackEntry:zs([174]),TrackType:zs([131]),FlagDefault:zs([136]),CodecID:zs([134]),CodecPrivate:zs([99,162]),VideoTrack:zs([224]),AudioTrack:zs([225]),Cluster:zs([31,67,182,117]),Timestamp:zs([231]),TimestampScale:zs([42,215,177]),BlockGroup:zs([160]),BlockDuration:zs([155]),Block:zs([161]),SimpleBlock:zs([163])},Eo=[128,64,32,16,8,4,2,1],ko=zs([0,0,0,1]),Co=zs([0,0,1]),Io=zs([0,0,3]),xo={webm:zs([119,101,98,109]),matroska:zs([109,97,116,114,111,115,107,97]),flac:zs([102,76,97,67]),ogg:zs([79,103,103,83]),ac3:zs([11,119]),riff:zs([82,73,70,70]),avi:zs([65,86,73]),wav:zs([87,65,86,69]),"3gp":zs([102,116,121,112,51,103]),mp4:zs([102,116,121,112]),fmp4:zs([115,116,121,112]),mov:zs([102,116,121,112,113,116]),moov:zs([109,111,111,118]),moof:zs([109,111,111,102])},Ao={aac:function(e){var t=Qs(e);return Ys(e,[255,16],{offset:t,mask:[255,22]})},mp3:function(e){var t=Qs(e);return Ys(e,[255,2],{offset:t,mask:[255,6]})},webm:function(e){e=io(e,[wo.EBML,wo.DocType])[0];return Ys(e,xo.webm)},mkv:function(e){e=io(e,[wo.EBML,wo.DocType])[0];return Ys(e,xo.matroska)},mp4:function(e){return!Ao["3gp"](e)&&!Ao.mov(e)&&(!(!Ys(e,xo.mp4,{offset:4})&&!Ys(e,xo.fmp4,{offset:4}))||(!(!Ys(e,xo.moof,{offset:4})&&!Ys(e,xo.moov,{offset:4}))||void 0))},mov:function(e){return Ys(e,xo.mov,{offset:4})},"3gp":function(e){return Ys(e,xo["3gp"],{offset:4})},ac3:function(e){var t=Qs(e);return Ys(e,xo.ac3,{offset:t})},ts:function(e){if(e.length<189&&1<=e.length)return 71===e[0];for(var t=0;t+188<e.length&&t<188;){if(71===e[t]&&71===e[t+188])return!0;t+=1}return!1},flac:function(e){var t=Qs(e);return Ys(e,xo.flac,{offset:t})},ogg:function(e){return Ys(e,xo.ogg)},avi:function(e){return Ys(e,xo.riff)&&Ys(e,xo.avi,{offset:8})},wav:function(e){return Ys(e,xo.riff)&&Ys(e,xo.wav,{offset:8})},h264:function(e){return no(e,"h264",7,3).length},h265:function(e){return no(e,"h265",[32,33],3).length}},Po=Object.keys(Ao).filter(function(e){return"ts"!==e&&"h264"!==e&&"h265"!==e}).concat(["ts","h264","h265"]);Po.forEach(function(e){var t=Ao[e];Ao[e]=function(e){return t(zs(e))}});function Lo(e){e=zs(e);for(var t=0;t<Po.length;t++){var i=Po[t];if(ll[i](e))return i}return""}function Do(e,t,i){return e&&i&&i.responseURL&&t!==i.responseURL?i.responseURL:t}function Oo(e){return tr.log.debug?tr.log.debug.bind(tr,"VHS:",e+" >"):function(){}}function Ro(e,t){var i,n=[];if(e&&e.length)for(i=0;i<e.length;i++)t(e.start(i),e.end(i))&&n.push([e.start(i),e.end(i)]);return tr.createTimeRanges(n)}function Mo(e,i){return Ro(e,function(e,t){return e-.1<=i&&i<=t+.1})}function No(e,t){return Ro(e,function(e){return t<=e-hl})}function Uo(e){var t=[];if(!e||!e.length)return"";for(var i=0;i<e.length;i++)t.push(e.start(i)+" => "+e.end(i));return t.join(", ")}function Bo(e){for(var t=[],i=0;i<e.length;i++)t.push({start:e.start(i),end:e.end(i)});return t}function Fo(e){if(e&&e.length&&e.end)return e.end(e.length-1)}function jo(e,t){var i=0;if(!e||!e.length)return i;for(var n=0;n<e.length;n++){var r=e.start(n),a=e.end(n);a<t||(i+=r<t&&t<=a?a-t:a-r)}return i}function Ho(t,e){if(!e.preload)return e.duration;var i=0;
4716return(e.parts||[]).forEach(function(e){i+=e.duration}),(e.preloadHints||[]).forEach(function(e){"PART"===e.type&&(i+=t.partTargetDuration)}),i}function qo(e){return(e.segments||[]).reduce(function(i,n,r){return n.parts?n.parts.forEach(function(e,t){i.push({duration:e.duration,segmentIndex:r,partIndex:t,part:e,segment:n})}):i.push({duration:n.duration,segmentIndex:r,partIndex:null,segment:n,part:null}),i},[])}function Vo(e){return(e=e.segments&&e.segments.length&&e.segments[e.segments.length-1])&&e.parts||[]}function Wo(e){var t=e.preloadSegment;if(t){e=t.parts,t=(t.preloadHints||[]).reduce(function(e,t){return e+("PART"===t.type?1:0)},0);return t+=e&&e.length?e.length:0}}function Go(e,t){return t.endList?0:e&&e.suggestedPresentationDelay?e.suggestedPresentationDelay:(e=0<Vo(t).length)&&t.serverControl&&t.serverControl.partHoldBack?t.serverControl.partHoldBack:e&&t.partTargetDuration?3*t.partTargetDuration:t.serverControl&&t.serverControl.holdBack?t.serverControl.holdBack:t.targetDuration?3*t.targetDuration:0}function zo(e,t,i){if((t="undefined"==typeof t?e.mediaSequence+e.segments.length:t)<e.mediaSequence)return 0;var n=function(e,t){var i=0,n=t-e.mediaSequence,r=e.segments[n];if(r){if("undefined"!=typeof r.start)return{result:r.start,precise:!0};if("undefined"!=typeof r.end)return{result:r.end-r.duration,precise:!0}}for(;n--;){if("undefined"!=typeof(r=e.segments[n]).end)return{result:i+r.end,precise:!0};if(i+=Ho(e,r),"undefined"!=typeof r.start)return{result:i+r.start,precise:!0}}return{result:i,precise:!1}}(e,t);return n.precise?n.result:(t=function(e,t){for(var i,n=0,r=t-e.mediaSequence;r<e.segments.length;r++){if("undefined"!=typeof(i=e.segments[r]).start)return{result:i.start-n,precise:!0};if(n+=Ho(e,i),"undefined"!=typeof i.end)return{result:i.end-n,precise:!0}}return{result:-1,precise:!1}}(e,t)).precise?t.result:n.result+i}function Xo(e,t,i){if(!e)return 0;if("number"!=typeof i&&(i=0),"undefined"==typeof t){if(e.totalDuration)return e.totalDuration;if(!e.endList)return window.Infinity}return zo(e,t,i)}function Ko(e){var t=e.defaultDuration,i=e.durationList,n=e.startIndex,r=e.endIndex,a=0;if(r<n&&(n=(e=[r,n])[0],r=e[1]),n<0){for(var s=n;s<Math.min(0,r);s++)a+=t;n=0}for(var o=n;o<r;o++)a+=i[o].duration;return a}function Yo(e,t,i,n){return e&&e.segments?e.endList?Xo(e):null===t?null:(t=zo(e,e.mediaSequence+e.segments.length,t=t||0),i&&(t-=n="number"==typeof n?n:Go(null,e)),Math.max(0,t)):null}function Qo(e){return e.excludeUntil&&e.excludeUntil>Date.now()}function $o(e){return e.excludeUntil&&e.excludeUntil===1/0}function Jo(e){var t=Qo(e);return!e.disabled&&!t}function Zo(e,t){return t.attributes&&t.attributes[e]}function eu(e,t){if(1===e.playlists.length)return!0;var i=t.attributes.BANDWIDTH||Number.MAX_VALUE;return 0===e.playlists.filter(function(e){return!!Jo(e)&&(e.attributes.BANDWIDTH||0)<i}).length}function tu(e,t){return!(!e&&!t||!e&&t||e&&!t)&&(e===t||(!(!e.id||!t.id||e.id!==t.id)||(!(!e.resolvedUri||!t.resolvedUri||e.resolvedUri!==t.resolvedUri)||!(!e.uri||!t.uri||e.uri!==t.uri))))}function iu(e,t){var i,n=e&&e.mediaGroups&&e.mediaGroups.AUDIO||{},r=!1;for(i in n){for(var a in n[i])if(r=t(n[i][a]))break;if(r)break}return!!r}function nu(i){if(!i||!i.playlists||!i.playlists.length)return iu(i,function(e){return e.playlists&&e.playlists.length||e.uri});for(var e=0;e<i.playlists.length;e++){var t=function(e){var t=i.playlists[e],e=t.attributes&&t.attributes.CODECS;return e&&e.split(",").every(fr)||iu(i,function(e){return tu(t,e)})?"continue":{v:!1}}(e);if("continue"!==t&&"object"==typeof t)return t.v}return!0}function ru(e,t){return e+"-"+t}function au(r,a){r.mediaGroups&&["AUDIO","SUBTITLES"].forEach(function(e){if(r.mediaGroups[e])for(var t in r.mediaGroups[e])for(var i in r.mediaGroups[e][t]){var n=r.mediaGroups[e][t][i];a(n,e,t,i)}})}function su(e){var t=e.playlist,i=e.uri,e=e.id;t.id=e,t.playlistErrors_=0,i&&(t.uri=i),t.attributes=t.attributes||{}}function ou(o,e){o.uri=e;for(var t=0;t<o.playlists.length;t++)o.playlists[t].uri||(o.playlists[t].uri="placeholder-uri-"+t);var i,u=nu(o);au(o,function(e,t,i,n){var r="placeholder-uri-"+t+"-"+i+"-"+n;if(!e.playlists||!e.playlists.length){if(u&&"AUDIO"===t&&!e.uri)for(var a=0;a<o.playlists.length;a++){var s=o.playlists[a];if(s.attributes&&s.attributes.AUDIO&&s.attributes.AUDIO===i)return}e.playlists=[g({},e)]}
4716e.playlists.forEach(function(e,t){var i=ru(t,r);e.uri?e.resolvedUri=e.resolvedUri||dl(o.uri,e.uri):(e.uri=0===t?r:i,e.resolvedUri=e.uri),e.id=e.id||i,e.attributes=e.attributes||{},o.playlists[e.id]=e,o.playlists[e.uri]=e})}),function(e){for(var t=e.playlists.length;t--;){var i=e.playlists[t];su({playlist:i,id:ru(t,i.uri)}),i.resolvedUri=dl(e.uri,i.uri),e.playlists[i.id]=i,(e.playlists[i.uri]=i).attributes.BANDWIDTH||ml.warn("Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.")}}(o),au(i=o,function(e){e.uri&&(e.resolvedUri=dl(i.uri,e.uri))})}function uu(e,t,i){var n=e.slice(),r=t.slice();i=i||0;for(var a,s=[],o=0;o<r.length;o++){var u=n[o+i],l=r[o];u?(a=u.map||a,s.push(function(e,t){if(!e)return t;var i=gl(e,t);if(e.preloadHints&&!t.preloadHints&&delete i.preloadHints,e.parts&&!t.parts)delete i.parts;else if(e.parts&&t.parts)for(var n=0;n<t.parts.length;n++)e.parts&&e.parts[n]&&(i.parts[n]=gl(e.parts[n],t.parts[n]));return!e.skipped&&t.skipped&&(i.skipped=!1),e.preload&&!t.preload&&(i.preload=!1),i}
4716(u,l))):(a&&!l.map&&(l.map=a),s.push(l))}return s}function lu(e,t){!e.resolvedUri&&e.uri&&(e.resolvedUri=dl(t,e.uri)),e.key&&!e.key.resolvedUri&&(e.key.resolvedUri=dl(t,e.key.uri)),e.map&&!e.map.resolvedUri&&(e.map.resolvedUri=dl(t,e.map.uri)),e.map&&e.map.key&&!e.map.key.resolvedUri&&(e.map.key.resolvedUri=dl(t,e.map.key.uri)),e.parts&&e.parts.length&&e.parts.forEach(function(e){e.resolvedUri||(e.resolvedUri=dl(t,e.uri))}),e.preloadHints&&e.preloadHints.length&&e.preloadHints.forEach(function(e){e.resolvedUri||(e.resolvedUri=dl(t,e.uri))})}function cu(e){var t=e.segments||[],i=e.preloadSegment;if(i&&i.parts&&i.parts.length){if(i.preloadHints)for(var n=0;n<i.preloadHints.length;n++)if("MAP"===i.preloadHints[n].type)return t;i.duration=e.targetDuration,i.preload=!0,t.push(i)}return t}function du(e,t){return e===t||e.segments&&t.segments&&e.segments.length===t.segments.length&&e.endList===t.endList&&e.mediaSequence===t.mediaSequence&&e.preloadSegment===t.preloadSegment}function hu(e,a,t){void 0===t&&(t=du);var i=gl(e,{}),n=i.playlists[a.id];if(!n)return null;if(t(n,a))return null;a.segments=cu(a);var r=gl(n,a);if(r.preloadSegment&&!a.preloadSegment&&delete r.preloadSegment,n.segments){if(a.skip){a.segments=a.segments||[];for(var s=0;s<a.skip.skippedSegments;s++)a.segments.unshift({skipped:!0})}r.segments=uu(n.segments,a.segments,a.mediaSequence-n.mediaSequence)}r.segments.forEach(function(e){lu(e,r.resolvedUri)});for(var o=0;o<i.playlists.length;o++)i.playlists[o].id===a.id&&(i.playlists[o]=r);return i.playlists[a.id]=r,i.playlists[a.uri]=r,au(e,function(e,t,i,n){if(e.playlists)for(var r=0;r<e.playlists.length;r++)a.id===e.playlists[r].id&&(e.playlists[r]=a)}),i}function pu(e,t){var i=e.segments||[],n=i[i.length-1],n=(i=n&&n.parts&&n.parts[n.parts.length-1])&&i.duration||n&&n.duration;return t&&n?1e3*n:500*(e.partTargetDuration||e.targetDuration||10)}function fu(e,t,i,n){var r="arraybuffer"===e.responseType?e.response:e.responseText;!t&&r&&(e.responseTime=Date.now(),e.roundTripTime=e.responseTime-e.requestTime,e.bytesReceived=r.byteLength||r.length,e.bandwidth||(e.bandwidth=Math.floor(e.bytesReceived/e.roundTripTime*8*1e3))),i.headers&&(e.responseHeaders=i.headers),t&&"ETIMEDOUT"===t.code&&(e.timedout=!0),n(t=!t&&!e.aborted&&200!==i.statusCode&&206!==i.statusCode&&0!==i.statusCode?new Error("XHR Failed with a response of: "+(e&&(r||e.responseText))):t,e)}function mu(){function a(e,i){e=_l({timeout:45e3},e);var t=a.beforeRequest||tr.Vhs.xhr.beforeRequest;!t||"function"!=typeof t||(t=t(e))&&(e=t);var n=(!0===tr.Vhs.xhr.original?vl:tr.Vhs.xhr)(e,function(e,t){return fu(n,e,t,i)}),r=n.abort;return n.abort=function(){return n.aborted=!0,r.apply(n,arguments)},n.uri=e.uri,n.requestTime=Date.now(),n}return a.original=!0,a}function gu(e){var t,i={};return e.byterange&&(i.Range=(t=e.byterange,e=t.offset,t="bigint"==typeof t.offset||"bigint"==typeof t.length?window.BigInt(t.offset)+window.BigInt(t.length)-window.BigInt(1):t.offset+t.length-1,"bytes="+e+"-"+t)),i}function yu(e,t){return e=e.toString(16),"00".substring(0,2-e.length)+e+(t%2?" ":"")}function vu(e){return 32<=e&&e<126?String.fromCharCode(e):"."}function _u(i){var n={};
4716return Object.keys(i).forEach(function(e){var t=i[e];ArrayBuffer.isView(t)?n[e]={bytes:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength}:n[e]=t}),n}function bu(e){var t=e.byterange||{length:1/0,offset:0};return[t.length,t.offset,e.resolvedUri].join(",")}function Tu(e){return e.resolvedUri}function Su(e){for(var t=Array.prototype.slice.call(e),i="",n=0;n<t.length/16;n++)i+=t.slice(16*n,16*n+16).map(yu).join("")+" "+t.slice(16*n,16*n+16).map(vu).join("")+"\n";return i}function wu(e){var t=e.playlist,i=e.time,n=void 0===i?void 0:i;if(!(i=e.callback))throw new Error("getProgramTime: callback must be provided");return t&&void 0!==n?(e=function(e,t){if(!t||!t.segments||0===t.segments.length)return null;for(var i,n=0,r=0;r<t.segments.length&&!(e<=(n=(i=t.segments[r]).videoTimingInfo?i.videoTimingInfo.transmuxedPresentationEnd:n+i.duration));r++);var a=t.segments[t.segments.length-1];if(a.videoTimingInfo&&a.videoTimingInfo.transmuxedPresentationEnd<e)return null;if(n<e){if(e>n+.25*a.duration)return null;i=a}return{segment:i,estimatedStart:i.videoTimingInfo?i.videoTimingInfo.transmuxedPresentationStart:n-i.duration,type:i.videoTimingInfo?"accurate":"estimate"}}(n,t))?"estimate"===e.type?i({message:"Accurate programTime could not be determined. Please seek to e.seekTime and try again",seekTime:e.estimatedStart}):(t={mediaSeconds:n},(e=function(e,t){if(!t.dateTimeObject)return null;var i=t.videoTimingInfo.transmuxerPrependedSeconds,i=e-(t.videoTimingInfo.transmuxedPresentationStart+i);return new Date(t.dateTimeObject.getTime()+1e3*i)}(n,e.segment))&&(t.programDateTime=e.toISOString()),i(null,t)):i({message:"valid programTime was not found"}):i({message:"getProgramTime: playlist and time must be provided"})}function Eu(e){var t=e.programTime,i=e.playlist,n=e.retryCount,r=void 0===n?2:n,a=e.seekTo,s=e.pauseAfterSeek,o=void 0===s||s,u=e.tech,l=e.callback;if(!l)throw new Error("seekToProgramTime: callback must be provided");return"undefined"!=typeof t&&i&&a?i.endList||u.hasStarted_?function(e){if(!e.segments||0===e.segments.length)return!1;for(var t=0;t<e.segments.length;t++)if(!e.segments[t].dateTimeObject)return!1;return!0}(i)?(n=function(e,t){var i;try{i=new Date(e)}catch(e){return null}if(!t||!t.segments||0===t.segments.length)return null;if(i<(r=t.segments[0]).dateTimeObject)return null;for(var n=0;n<t.segments.length-1;n++){var r=t.segments[n];if(i<t.segments[n+1].dateTimeObject)break}var a,s=t.segments[t.segments.length-1],e=s.dateTimeObject,a=s.videoTimingInfo?(a=s.videoTimingInfo).transmuxedPresentationEnd-a.transmuxedPresentationStart-a.transmuxerPrependedSeconds:s.duration+.25*s.duration;return new Date(e.getTime()+1e3*a)<i?null:{segment:r=e<i?s:r,estimatedStart:r.videoTimingInfo?r.videoTimingInfo.transmuxedPresentationStart:fl.duration(t,t.mediaSequence+t.segments.indexOf(r)),type:r.videoTimingInfo?"accurate":"estimate"}}(t,i))?(s=n.segment,e=function(e,t){var i;try{n=new Date(e),i=new Date(t)}catch(e){}var n=n.getTime();return(i.getTime()-n)/1e3}(s.dateTimeObject,t),"estimate"===n.type?0===r?l({message:t+" is not buffered yet. Try again"}):(a(n.estimatedStart+e),void u.one("seeked",function(){Eu({programTime:t,playlist:i,retryCount:r-1,seekTo:a,pauseAfterSeek:o,tech:u,callback:l})})):(e=s.start+e,u.one("seeked",function(){return l(null,u.currentTime())}),o&&u.pause(),void a(e))):l({message:t+" was not found in the stream"}):l({message:"programDateTime tags must be provided in the manifest "+i.resolvedUri}):l({message:"player must be playing a live stream to start buffering"}):l({message:"seekToProgramTime: programTime, seekTo and playlist must be provided"})}function ku(e,t){if(4===e.readyState)return t()}function Cu(e,t,r){function n(e,t,i,n){return t.abort(),o=!0,r(e,t,i,n)}function i(e,t){if(!o){if(e)return n(e,t,"",s);var i=t.responseText.substring(s&&s.byteLength||0,t.responseText.length);if(s=function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];if((t=t.filter(function(e){return e&&(e.byteLength||e.length)&&"string"!=typeof e})).length<=1)return zs(t[0]);var n=t.reduce(function(e,t,i){return e+(t.byteLength||t.length)}
4716,0),r=new Uint8Array(n),a=0;return t.forEach(function(e){e=zs(e),r.set(e,a),a+=e.byteLength}),r}(s,Ks(i,!0)),a=a||Qs(s),s.length<10||a&&s.length<a+2)return ku(t,function(){return n(e,t,"",s)});i=Lo(s);return"ts"===i&&s.length<188||!i&&s.length<376?ku(t,function(){return n(e,t,"",s)}):n(null,t,i,s)}}var a,s=[],o=!1,u=t({uri:e,beforeSend:function(t){t.overrideMimeType("text/plain; charset=x-user-defined"),t.addEventListener("progress",function(e){return e.total,e.loaded,fu(t,null,{statusCode:t.status},i)})}},function(e,t){return fu(u,e,t,i)});return u}function Iu(e,t){if(!du(e,t))return!1;if(e.sidx&&t.sidx&&(e.sidx.offset!==t.sidx.offset||e.sidx.length!==t.sidx.length))return!1;if(!e.sidx&&t.sidx||e.sidx&&!t.sidx)return!1;if(e.segments&&!t.segments||!e.segments&&t.segments)return!1;if(!e.segments&&!t.segments)return!0;for(var i=0;i<e.segments.length;i++){var n=e.segments[i],r=t.segments[i];if(n.uri!==r.uri)return!1;if(n.byterange||r.byterange){n=n.byterange,r=r.byterange;if(n&&!r||!n&&r)return!1;if(n.offset!==r.offset||n.length!==r.length)return!1}}return!0}function xu(e,t){var i,n={};for(i in e){var r=e[i].sidx;if(r){var a=bs(r);if(!t[a])break;var s=t[a].sidxInfo;s=s,r=r,(Boolean(!s.map&&!r.map)||Boolean(s.map&&r.map&&s.map.byterange.offset===r.map.byterange.offset&&s.map.byterange.length===r.map.byterange.length))&&s.uri===r.uri&&s.byterange.offset===r.byterange.offset&&s.byterange.length===r.byterange.length&&(n[a]=t[a])}}return n}function Au(e){return e.on=e.addEventListener,e.off=e.removeEventListener,e}function Pu(i){var n=i.transmuxer,e=i.bytes,t=i.audioAppendStart,r=i.gopsToAlignWith,a=i.remux,s=i.onData,o=i.onTrackInfo,u=i.onAudioTimingInfo,l=i.onVideoTimingInfo,c=i.onVideoSegmentTimingInfo,d=i.onAudioSegmentTimingInfo,h=i.onId3,p=i.onCaptions,f=i.onDone,m=i.onEndedTimeline,g=i.onTransmuxerLog,y=i.isEndOfTimeline,v={buffer:[]},_=y;n.onmessage=function(e){var t;n.currentTransmux===i&&("data"===e.data.action&&function(e,t,i){var n=e.data.segment,r=n.type,a=n.initSegment,s=n.captions,o=n.captionStreams,u=n.metadata,l=n.videoFrameDtsTime,n=n.videoFramePtsTime;t.buffer.push({captions:s,captionStreams:o,metadata:u});e=e.data.segment.boxes||{data:e.data.segment.data},a={type:r,data:new Uint8Array(e.data,e.data.byteOffset,e.data.byteLength),initSegment:new Uint8Array(a.data,a.byteOffset,a.byteLength)};"undefined"!=typeof l&&(a.videoFrameDtsTime=l),"undefined"!=typeof n&&(a.videoFramePtsTime=n),i(a)}(e,v,s),"trackinfo"===e.data.action&&o(e.data.trackInfo),"gopInfo"===e.data.action&&(v.gopInfo=e.data.gopInfo),"audioTimingInfo"===e.data.action&&u(e.data.audioTimingInfo),"videoTimingInfo"===e.data.action&&l(e.data.videoTimingInfo),"videoSegmentTimingInfo"===e.data.action&&c(e.data.videoSegmentTimingInfo),"audioSegmentTimingInfo"===e.data.action&&d(e.data.audioSegmentTimingInfo),"id3Frame"===e.data.action&&h([e.data.id3Frame],e.data.id3Frame.dispatchType),"caption"===e.data.action&&p(e.data.caption),"endedtimeline"===e.data.action&&(_=!1,m()),"log"===e.data.action&&g(e.data.log),"transmuxed"===e.data.type&&(_||(n.onmessage=null,e=(t={transmuxedData:v,callback:f}).transmuxedData,t=t.callback,e.buffer=[],t(e),El(n))))},t&&n.postMessage({action:"setAudioAppendStart",appendStart:t}),Array.isArray(r)&&n.postMessage({action:"alignGopsWith",gopsToAlignWith:r}),"undefined"!=typeof a&&n.postMessage({action:"setRemux",remux:a}),e.byteLength&&(r=e instanceof ArrayBuffer?e:e.buffer,a=e instanceof ArrayBuffer?0:e.byteOffset,n.postMessage({action:"push",data:r,byteOffset:a,byteLength:e.byteLength},[r])),y&&n.postMessage({action:"endTimeline"}),n.postMessage({action:"flush"})}function Lu(e,t){e.postMessage({action:t}),El(e)}function Du(e,t){if(!t.currentTransmux)return t.currentTransmux=e,Lu(t,e),0;t.transmuxQueue.push(Lu.bind(null,t,e))}function Ou(e){if(!e.transmuxer.currentTransmux)return e.transmuxer.currentTransmux=e,void Pu(e);e.transmuxer.transmuxQueue.push(e)}function Ru(i){var n=i.transmuxer,r=i.endAction||i.action,a=i.callback,e=g({},i,{endAction:null,transmuxer:null,callback:null}),t=function e(t){t.data.action===r&&(n.removeEventListener("message",e),t.data.data&&(t.data.data=new Uint8Array(t.data.data,i.byteOffset||0,i.byteLength||t.data.data.byteLength),i.data&&(i.data=t.data.data)),a(t.data))};n.addEventListener("message",t),i.data?(t=i.data instanceof ArrayBuffer,e.byteOffset=t?0:i.data.byteOffset,e.byteLength=i.data.byteLength,t=[t?i.data:i.data.buffer],n.postMessage(e,t)):n.postMessage(e)}function Mu(e){e.forEach(function(e){e.abort()})}function Nu(e,t){return t.timedout?{status:t.status,message:"HLS request timed-out at URL: "+t.uri,code:xl,xhr:t}:t.aborted?{status:t.status,message:"HLS request aborted at URL: "+t.uri,code:Al,xhr:t}:e?{status:t.status,message:"HLS request errored at URL: "+t.uri,code:Il,xhr:t}:"arraybuffer"===t.responseType&&0===t.response.byteLength?{status:t.status,message:"Empty HLS response at URL: "+t.uri,code:Il,xhr:t}:null}function Uu(a,s,o){return function(e,t){var i=t.response,e=Nu(e,t);if(e)return o(e,a);if(16!==i.byteLength)return o({status:t.status,message:"Invalid HLS key at URL: "+t.uri,code:Il,xhr:t},a);for(var i=new DataView(i),n=new Uint32Array([i.getUint32(0),i.getUint32(4),i.getUint32(8),i.getUint32(12)]),r=0;r<s.length;r++)s[r].bytes=n;return o(null,a)}}function Bu(i,n){var e=Lo(i.map.bytes);if("mp4"!==e){var t=i.map.resolvedUri||i.map.uri;return n({internal:!0,message:"Found unsupported "+(e||"unknown")+" container for initialization segment at URL: "+t,code:Il})}Ru({action:"probeMp4Tracks",data:i.map.bytes,transmuxer:i.transmuxer,callback:function(e){var t=e.tracks,e=e.data;return i.map.bytes=e,t.forEach(function(e){i.map.tracks=i.map.tracks||{},i.map.tracks[e.type]||"number"==typeof(i.map.tracks[e.type]=e).id&&e.timescale&&(i.map.timescales=i.map.timescales||{},i.map.timescales[e.id]=e.timescale)}),n(null)}})}function Fu(e){var i=e.segment,n=e.finishProcessingFn,r=e.responseType;return function(e,t){e=Nu(e,t);if(e)return n(e,i);e="arraybuffer"!==r&&t.responseText?function(e){for(var t=new Uint8Array(new ArrayBuffer(e.length)),i=0;i<e.length;i++)t[i]=e.charCodeAt(i);return t.buffer}(t.responseText.substring(i.lastReachedChar||0)):t.response;return i.stats={bandwidth:(t=t).bandwidth,bytesReceived:t.bytesReceived||0,roundTripTime:t.roundTripTime||0},i.key?i.encryptedBytes=new Uint8Array(e):i.bytes=new Uint8Array(e),n(null,i)}}function ju(e){var i=e.segment,t=e.bytes,n=e.trackInfoFn,r=e.timingInfoFn,a=e.videoSegmentTimingInfoFn,s=e.audioSegmentTimingInfoFn,o=e.id3Fn,u=e.captionsFn,l=e.isEndOfTimeline,c=e.endedTimelineFn,d=e.dataFn,h=e.doneFn,p=e.onTransmuxerLog,e=i.map&&i.map.tracks||{},f=Boolean(e.audio&&e.video),m=r.bind(null,i,"audio","start"),g=r.bind(null,i,"audio","end"),y=r.bind(null,i,"video","start"),v=r.bind(null,i,"video","end");Ru({action:"probeTs",transmuxer:i.transmuxer,data:t,baseStartTime:i.baseStartTime,callback:function(e){i.bytes=t=e.data;e=e.result;e&&(n(i,{hasAudio:e.hasAudio,hasVideo:e.hasVideo,isMuxed:f}),n=null,e.hasAudio&&!f&&m(e.audioStart),e.hasVideo&&y(e.videoStart),y=m=null),Ou({bytes:t,transmuxer:i.transmuxer,audioAppendStart:i.audioAppendStart,gopsToAlignWith:i.gopsToAlignWith,remux:f,onData:function(e){e.type="combined"===e.type?"video":e.type,d(i,e)},onTrackInfo:function(e){n&&(f&&(e.isMuxed=!0),n(i,e))},onAudioTimingInfo:function(e){m&&"undefined"!=typeof e.start&&(m(e.start),m=null),g&&"undefined"!=typeof e.end&&g(e.end)},onVideoTimingInfo:function(e){y&&"undefined"!=typeof e.start&&(y(e.start),y=null),v&&"undefined"!=typeof e.end&&v(e.end)},onVideoSegmentTimingInfo:function(e){a(e)},onAudioSegmentTimingInfo:function(e){s(e)},onId3:function(e,t){o(i,e,t)},onCaptions:function(e){u(i,[e])},isEndOfTimeline:l,onEndedTimeline:function(){c()},onTransmuxerLog:p,onDone:function(e){h&&(e.type="combined"===e.type?"video":e.type,h(null,i,e))}})}})}function Hu(e){var i=e.segment,n=e.bytes,t=e.trackInfoFn,r=e.timingInfoFn,a=e.videoSegmentTimingInfoFn,s=e.audioSegmentTimingInfoFn,o=e.id3Fn,u=e.captionsFn,l=e.isEndOfTimeline,c=e.endedTimelineFn,d=e.dataFn,h=e.doneFn,p=e.onTransmuxerLog,f=new 
4716Uint8Array(n);if(0<Js(f,["moof"]).length){i.isFmp4=!0;var m=i.map.tracks,g={isFmp4:!0,hasVideo:!!m.video,hasAudio:!!m.audio};m.audio&&m.audio.codec&&"enca"!==m.audio.codec&&(g.audioCodec=m.audio.codec),m.video&&m.video.codec&&"encv"!==m.video.codec&&(g.videoCodec=m.video.codec),m.video&&m.audio&&(g.isMuxed=!0),t(i,g);var y=function(e){d(i,{data:f,type:g.hasAudio&&!g.isMuxed?"audio":"video"}),e&&e.length&&u(i,e),h(null,i,{})};Ru({action:"probeMp4StartTime",timescales:i.map.timescales,data:f,transmuxer:i.transmuxer,callback:function(e){var t=e.data,e=e.startTime;n=t.buffer,i.bytes=f=t,g.hasAudio&&!g.isMuxed&&r(i,"audio","start",e),g.hasVideo&&r(i,"video","start",e),m.video&&t.byteLength&&i.transmuxer?Ru({action:"pushMp4Captions",endAction:"mp4Captions",transmuxer:i.transmuxer,data:f,timescales:i.map.timescales,trackIds:[m.video.id],callback:function(e){n=e.data.buffer,i.bytes=f=e.data,e.logs.forEach(function(e){p(tr.mergeOptions(e,{stream:"mp4CaptionParser"}))}),y(e.captions)}}):y()}})}else if(i.transmuxer){if("undefined"==typeof i.container&&(i.container=Lo(f)),"ts"!==i.container&&"aac"!==i.container)return t(i,{hasAudio:!1,hasVideo:!1}),h(null,i,{}),0;ju({segment:i,bytes:n,trackInfoFn:t,timingInfoFn:r,videoSegmentTimingInfoFn:a,audioSegmentTimingInfoFn:s,id3Fn:o,captionsFn:u,isEndOfTimeline:l,endedTimelineFn:c,dataFn:d,doneFn:h,onTransmuxerLog:p})}else h(null,i,{})}function qu(e,i){var n=e.id,t=e.key,r=e.encryptedBytes,a=e.decryptionWorker,e=function e(t){t.data.source===n&&(a.removeEventListener("message",e),t=t.data.decrypted,i(new Uint8Array(t.bytes,t.byteOffset,t.byteLength)))};a.addEventListener("message",e),e=t.bytes.slice?t.bytes.slice():new Uint32Array(Array.prototype.slice.call(t.bytes)),a.postMessage(_u({source:n,encrypted:r,key:e,iv:t.iv}),[r.buffer,e.buffer])}function Vu(e){var i=e.activeXhrs,m=e.decryptionWorker,g=e.trackInfoFn,y=e.timingInfoFn,v=e.videoSegmentTimingInfoFn,_=e.audioSegmentTimingInfoFn,b=e.id3Fn,T=e.captionsFn,S=e.isEndOfTimeline,w=e.endedTimelineFn,E=e.dataFn,k=e.doneFn,C=e.onTransmuxerLog,n=0,r=!1;return function(e,f){if(!r){if(e)return r=!0,Mu(i),k(e,f);if((n+=1)===i.length){var t=function(){if(f.encryptedBytes)return t=(e={decryptionWorker:m,segment:f,trackInfoFn:g,timingInfoFn:y,videoSegmentTimingInfoFn:v,audioSegmentTimingInfoFn:_,id3Fn:b,captionsFn:T,isEndOfTimeline:S,endedTimelineFn:w,dataFn:E,doneFn:k,onTransmuxerLog:C}).decryptionWorker,i=e.segment,n=e.trackInfoFn,r=e.timingInfoFn,a=e.videoSegmentTimingInfoFn,s=e.audioSegmentTimingInfoFn,o=e.id3Fn,u=e.captionsFn,l=e.isEndOfTimeline,c=e.endedTimelineFn,d=e.dataFn,h=e.doneFn,p=e.onTransmuxerLog,void qu({id:i.requestId,key:i.key,encryptedBytes:i.encryptedBytes,decryptionWorker:t},function(e){i.bytes=e,Hu({segment:i,bytes:i.bytes,trackInfoFn:n,timingInfoFn:r,videoSegmentTimingInfoFn:a,audioSegmentTimingInfoFn:s,id3Fn:o,captionsFn:u,isEndOfTimeline:l,endedTimelineFn:c,dataFn:d,doneFn:h,onTransmuxerLog:p})});var e,t,i,n,r,a,s,o,u,l,c,d,h,p;Hu({segment:f,bytes:f.bytes,trackInfoFn:g,timingInfoFn:y,videoSegmentTimingInfoFn:v,audioSegmentTimingInfoFn:_,id3Fn:b,captionsFn:T,isEndOfTimeline:S,endedTimelineFn:w,dataFn:E,doneFn:k,onTransmuxerLog:C})};if(f.endOfAllRequests=Date.now(),f.map&&f.map.encryptedBytes&&!f.map.bytes)return qu({decryptionWorker:m,id:f.requestId+"-init",encryptedBytes:f.map.encryptedBytes,key:f.map.key},function(e){f.map.bytes=e,Bu(f,function(e){return e?(Mu(i),k(e,f)):void t()})});t()}}}}function Wu(e){var n=e.segment,r=e.progressFn;return e.trackInfoFn,e.timingInfoFn,e.videoSegmentTimingInfoFn,e.audioSegmentTimingInfoFn,e.id3Fn,e.captionsFn,e.isEndOfTimeline,e.endedTimelineFn,e.dataFn,function(e){var t,i=e.target;if(!i.aborted)return n.stats=tr.mergeOptions(n.stats,(i=(t=e).target,(i={bandwidth:1/0,bytesReceived:0,roundTripTime:Date.now()-i.requestTime||0}).bytesReceived=t.loaded,i.bandwidth=Math.floor(i.bytesReceived/i.roundTripTime*8*1e3),i)),!n.stats.firstBytesReceivedAt&&n.stats.bytesReceived&&(n.stats.firstBytesReceivedAt=Date.now()),r(e,n)}}function Gu(e){var t,i,n,r=e.xhr,a=e.xhrOptions,s=e.decryptionWorker,o=e.segment,u=e.abortFn,l=e.progressFn,c=e.trackInfoFn,d=e.timingInfoFn,h=e.videoSegmentTimingInfoFn,p=e.audioSegmentTimingInfoFn,f=e.id3Fn,m=e.captionsFn,g=e.isEndOfTimeline,y=e.endedTimelineFn,v=e.dataFn,_=e.doneFn,e=e.onTransmuxerLog,b=[],_=Vu({activeXhrs:b,decryptionWorker:s,trackInfoFn:c,timingInfoFn:d,videoSegmentTimingInfoFn:h,audioSegmentTimingInfoFn:p,id3Fn:f,captionsFn:m,isEndOfTimeline:g,endedT
4716imelineFn:y,dataFn:v,doneFn:_,onTransmuxerLog:e});o.key&&!o.key.bytes&&(e=[o.key],o.map&&!o.map.bytes&&o.map.key&&o.map.key.resolvedUri===o.key.resolvedUri&&e.push(o.map.key),e=r(tr.mergeOptions(a,{uri:o.key.resolvedUri,responseType:"arraybuffer"}),Uu(o,e,_)),b.push(e)),o.map&&!o.map.bytes&&(!o.map.key||o.key&&o.key.resolvedUri===o.map.key.resolvedUri||(t=r(tr.mergeOptions(a,{uri:o.map.key.resolvedUri,responseType:"arraybuffer"}),Uu(o,[o.map.key],_)),b.push(t)),t=r(tr.mergeOptions(a,{uri:o.map.resolvedUri,responseType:"arraybuffer",headers:gu(o.map)}),(i=(t={segment:o,finishProcessingFn:_}).segment,n=t.finishProcessingFn,function(e,t){e=Nu(e,t);if(e)return n(e,i);e=new Uint8Array(t.response);if(i.map.key)return i.map.encryptedBytes=e,n(null,i);i.map.bytes=e,Bu(i,function(e){return e?(e.xhr=t,e.status=t.status,n(e,i)):void n(null,i)})})),b.push(t)),a=tr.mergeOptions(a,{uri:o.part&&o.part.resolvedUri||o.resolvedUri,responseType:"arraybuffer",headers:gu(o)}),(a=r(a,Fu({segment:o,finishProcessingFn:_,responseType:a.responseType}))).addEventListener("progress",Wu({segment:o,progressFn:l,trackInfoFn:c,timingInfoFn:d,videoSegmentTimingInfoFn:h,audioSegmentTimingInfoFn:p,id3Fn:f,captionsFn:m,isEndOfTimeline:g,endedTimelineFn:y,dataFn:v})),b.push(a);var T={};return b.forEach(function(e){var t,i;e.addEventListener("loadend",(t=(e={loadendState:T,abortFn:u}).loadendState,i=e.abortFn,function(e){e.target.aborted&&i&&!t.calledAbortFn&&(i(),t.calledAbortFn=!0)}))}),function(){return Mu(b)}}function zu(e,t){return t=t.attributes||{},e&&e.mediaGroups&&e.mediaGroups.AUDIO&&t.AUDIO&&e.mediaGroups.AUDIO[t.AUDIO]}function Xu(e){var n={};return e.forEach(function(e){var t=e.mediaType,i=e.type,e=e.details;n[t]=n[t]||[],n[t].push(hr(""+i+e))}),Object.keys(n).forEach(function(e){return 1<n[e].length?(Pl("multiple "+e+" codecs found as attributes: "+n[e].join(", ")+". Setting playlist codecs to null so that we wait for mux.js to probe segments for real codecs."),void(n[e]=null)):void(n[e]=n[e][0])}),n}function Ku(e){var t=0;return e.audio&&t++,e.video&&t++,t}function Yu(e,t){var i,n=t.attributes||{},r=Xu(function(e){e=e.attributes||{};if(e.CODECS)return pr(e.CODECS)}(t)||[]);return zu(e,t)&&!r.audio&&!function(e,t){if(!zu(e,t))return!0;var i,t=t.attributes||{},n=e.mediaGroups.AUDIO[t.AUDIO];for(i in n)if(!n[i].uri&&!n[i].playlists)return!0;return!1}(e,t)&&(i=Xu(function(e,t){if(!e.mediaGroups.AUDIO||!t)return null;var i,n=e.mediaGroups.AUDIO[t];if(!n)return null;for(i in n){var r=n[i];if(r.default&&r.playlists)return pr(r.playlists[0].attributes.CODECS)}return null}(e,n.AUDIO)||[])).audio&&(r.audio=i.audio),r}function Qu(e){if(e&&e.playlist){var t=e.playlist;return JSON.stringify({id:t.id,bandwidth:e.bandwidth,width:e.width,height:e.height,codecs:t.attributes&&t.attributes.CODECS||""})}}function $u(e,t){return(e=e&&window.getComputedStyle(e))?e[t]:""}function Ju(e,n){var r=e.slice();e.sort(function(e,t){var i=n(e,t);return 0===i?r.indexOf(e)-r.indexOf(t):i})}function Zu(e,t){var i,n;return(i=(i=e.attributes.BANDWIDTH?e.attributes.BANDWIDTH:i)||window.Number.MAX_VALUE)-(n=(n=t.attributes.BANDWIDTH?t.attributes.BANDWIDTH:n)||window.Number.MAX_VALUE)}function el(e,t,i,n,r,a){if(e){var s={bandwidth:t,width:i,height:n,limitRenditionByPlayerDimensions:r},o=e.playlists;fl.isAudioOnly(e)&&(o=a.getAudioTrackPlaylists_(),s.audioOnly=!0);var u=o.map(function(e){var t=e.attributes&&e.attributes.RESOLUTION&&e.attributes.RESOLUTION.width,i=e.attributes&&e.attributes.RESOLUTION&&e.attributes.RESOLUTION.height,n=e.attributes&&e.attributes.BANDWIDTH;return{bandwidth:n||window.Number.MAX_VALUE,width:t,height:i,playlist:e}});Ju(u,function(e,t){return e.bandwidth-t.bandwidth});var l=(u=u.filter(function(e){return!fl.isIncompatible(e.playlist)})).filter(function(e){return fl.isEnabled(e.playlist)}),e=(l=!l.length?u.filter(function(e){return!fl.isDisabled(e.playlist)}):l).filter(function(e){return e.bandwidth*Sl.BANDWIDTH_VARIANCE<t}),c=e[e.length-1],o=e.filter(function(e){return e.bandwidth===c.bandwidth})[0];if(!1===r){var d=o||l[0]||u[0];if(d&&d.playlist){r=o?"bandwidthBestRep":"sortedPlaylistReps";return l[0]&&(r="enabledPlaylistReps"),Ll("choosing "+Qu(d)+" using "+r+" with options",s),d.playlist}return Ll("could not choose a playlist with options",s),null}d=e.filter(function(e){return e.width&&e.height});Ju(d,function(e,t){return e.width-t.width});var h,p,f,e=d.filter(function(e){return e.width===i&&e.height===n}),c=e[e.length-1],e=e.filter(function(e){return e.bandwidth===c.bandwidth})[0];e||(p=(h=d.filter(function(e){return e.width>i||e.height>n})).filter(function(e){return e.width===h[0].width&&e.height===h[0].height}),c=p[p.length-1],p=p.filter(function(e){return e.bandwidth===c.bandwidth})[0]),a.experimentalLeastPixelDiffSelector&&(m=d.map(function(e){return e.pixelDiff=Math.abs(e.width-i)+Math.abs(e.height-n),e}),Ju(m,function(e,t){return e.pixelDiff===t.pixelDiff?t.bandwidth-e.bandwidth:e.pixelDiff-t.pixelDiff}),f=m[0]);var m=f||p||e||o||l[0]||u[0];if(m&&m.playlist){u="sortedPlaylistReps";return f?u="leastPixelDiffRep":p?u="resolutionPlusOneRep":e?u="resolutionBestRep":o?u="bandwidthBestRep":l[0]&&(u="enabledPlaylistReps"),Ll("choosing "+Qu(m)+" using "+u+" with options",s),m.playlist}return Ll("could not choose a playlist with options",s),null}}function tl(e){var t=e.inbandTextTracks,i=e.metadataArray,r=e.timestampOffset,n=e.videoDuration;if(i){var a=window.WebKitDataCue||window.VTTCue,s=t.metadataTrack_;if(s&&(i.forEach(function(e){var n=e.cueTime+r;!("number"!=typeof n||window.isNaN(n)||n<0)&&n<1/0&&e.frames.forEac
4716h(function(e){var t,i=new a(n,n,e.value||e.url||e.data||"");i.frame=e,i.value=e,t=i,Object.defineProperties(t.frame,{id:{get:function(){return tr.log.warn("cue.frame.id is deprecated. Use cue.value.key instead."),t.value.key}},value:{get:function(){return tr.log.warn("cue.frame.value is deprecated. Use cue.value.data instead."),t.value.data}},privateData:{get:function(){return tr.log.warn("cue.frame.privateData is deprecated. Use cue.value.data instead."),t.value.data}}}),s.addCue(i)})}),s.cues&&s.cues.length)){for(var o=s.cues,u=[],l=0;l<o.length;l++)o[l]&&u.push(o[l]);var c=u.reduce(function(e,t){var i=e[t.startTime]||[];return i.push(t),e[t.startTime]=i,e},{}),d=Object.keys(c).sort(function(e,t){return Number(e)-Number(t)});d.forEach(function(e,t){var e=c[e],i=Number(d[t+1])||n;e.forEach(function(e){e.endTime=i})})}}}function il(e,t,i){var n,r;if(i&&i.cues)for(n=i.cues.length;n--;)(r=i.cues[n]).startTime>=e&&r.endTime<=t&&i.removeCue(r)}function nl(e){return"number"==typeof e&&isFinite(e)}function rl(e){var t=e.startOfSegment,i=e.duration,n=e.segment,r=e.part,a=e.playlist,s=a.mediaSequence,o=a.id,u=a.segments,l=e.mediaIndex,c=e.partIndex,d=e.timeline,h=(void 0===u?[]:u).length-1,p="mediaIndex/partIndex increment";return e.getMediaInfoForTime?p="getMediaInfoForTime ("+e.getMediaInfoForTime+")":e.isSyncRequest&&(p="getSyncSegmentCandidate (isSyncRequest)"),e.independent&&(p+=" with independent "+e.independent),a="number"==typeof c,u=e.segment.uri?"segment":"pre-segment",e=a?Wo({preloadSegment:n})-1:0,u+" ["+(s+l)+"/"+(s+h)+"]"+(a?" part ["+c+"/"+e+"]":"")+" segment start/end ["+n.start+" => "+n.end+"]"+(a?" part start/end ["+r.start+" => "+r.end+"]":"")+" startOfSegment ["+t+"] duration ["+i+"] timeline ["+d+"] selected by ["+p+"] playlist ["+o+"]"}function al(e){return e+"TimingInfo"}function sl(e){var t=e.timelineChangeController,i=e.currentTimeline,n=e.segmentTimeline,r=e.loaderType,e=e.audioDisabled;if(i!==n){if("audio"===r){i=t.lastTimelineChange({type:"main"});return!i||i.to!==n}if("main"===r&&e){t=t.pendingTimelineChange({type:"audio"});return t&&t.to===n?!1:!0}}}function ol(e){var t=e.segmentDuration,e=e.maxDuration;return!!t&&Math.round(t)>e+hl}function ul(e,t){if("hls"!==t)return null;var n,r,i=(n={audioTimingInfo:e.audioTimingInfo,videoTimingInfo:e.videoTimingInfo},r=0,["video","audio"].forEach(function(e){var t,i=n[e+"TimingInfo"];i&&(e=i.start,i=i.end,"bigint"==typeof e||"bigint"==typeof i?t=window.BigInt(i)-window.BigInt(e):"number"==typeof e&&"number"==typeof i&&(t=i-e),"undefined"!=typeof t&&r<t&&(r=t))}),r="bigint"==typeof r&&r<Number.MAX_SAFE_INTEGER?Number(r):r);if(!i)return null;var a=e.playlist.targetDuration,s=ol({segmentDuration:i,maxDuration:2*a}),t=ol({segmentDuration:i,maxDuration:a}),a="Segment with index "+e.mediaIndex+" from playlist "+e.playlist.id+" has a duration of "+i+" when the reported duration is "+e.duration+" and the target duration is "+a+". For HLS content, a duration in excess of the target duration may result in playback issues. See the HLS specification section on EXT-X-TARGETDURATION for more details: https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1";return s||t?{severity:s?"warn":"info",message:a}:null}var ll=Ao,cl=9e4,dl=ir,hl=1/30,pl=tr.createTimeRange,fl={liveEdgeDelay:Go,duration:Xo,seekable:function(e,t,i){var n=t||0,i=Yo(e,t,!0,i);return null===i?pl():pl(n,i)},getMediaInfoForTime:function(e){for(var t=e.playlist,i=e.currentTime,n=e.startingSegmentIndex,r=e.startingPartIndex,a=e.startTime,s=e.experimentalExactManifestTimings,o=i-a,u=qo(t),l=0,c=0;c<u.length;c++){var d=u[c];if(n===d.segmentIndex&&("number"!=typeof r||"number"!=typeof d.partIndex||r===d.partIndex)){l=c;break}}if(o<0){if(0<l)for(var h=l-1;0<=h;h--){var p=u[h];if(o+=p.duration,s){if(o<0)continue}else if(o+hl<=0)continue;return{partIndex:p.partIndex,segmentIndex:p.segmentIndex,startTime:a-Ko({defaultDuration:t.targetDuration,durationList:u,startIndex:l,endIndex:h})}}return{partIndex:u[0]&&u[0].partIndex||null,segmentIndex:u[0]&&u[0].segmentIndex||0,startTime:i}}if(l<0){for(var f=l;f<0;f++)if((o-=t.targetDuration)<0)return{partIndex:u[0]&&u[0].partIndex||null,segmentIndex:u[0]&&u[0].segmentIndex||0,startTime:i};l=0}for(var m=l;m<u.length;m++){var g=u[m];
4716if(o-=g.duration,s){if(0<o)continue}else if(0<=o-hl)continue;return{partIndex:g.partIndex,segmentIndex:g.segmentIndex,startTime:a+Ko({defaultDuration:t.targetDuration,durationList:u,startIndex:l,endIndex:m})}}return{segmentIndex:u[u.length-1].segmentIndex,partIndex:u[u.length-1].partIndex,startTime:i}},isEnabled:Jo,isDisabled:function(e){return e.disabled},isBlacklisted:Qo,isIncompatible:$o,playlistEnd:Yo,isAes:function(e){for(var t=0;t<e.segments.length;t++)if(e.segments[t].key)return!0;return!1},hasAttribute:Zo,estimateSegmentRequestTime:function(e,t,i,n){return Zo("BANDWIDTH",i)?(e*i.attributes.BANDWIDTH-8*(n=void 0===n?0:n))/t:NaN},isLowestEnabledRendition:eu,isAudioOnly:nu,playlistMatch:tu,segmentDurationWithParts:Ho},ml=tr.log,gl=tr.mergeOptions,W=tr.EventTarget,yl=function(a){function e(e,t,i){var n;if(void 0===i&&(i={}),n=a.call(this)||this,!e)throw new Error("A non-empty playlist URL or object is required");n.logger_=Oo("PlaylistLoader");var r=i.withCredentials,r=void 0!==r&&r,i=i.handleManifestRedirects,i=void 0!==i&&i;n.src=e,n.vhs_=t,n.withCredentials=r,n.handleManifestRedirects=i;t=t.options_;return n.customTagParsers=t&&t.customTagParsers||[],n.customTagMappers=t&&t.customTagMappers||[],n.experimentalLLHLS=t&&t.experimentalLLHLS||!1,tr.browser.IE_VERSION&&(n.experimentalLLHLS=!1),n.state="HAVE_NOTHING",n.handleMediaupdatetimeout_=n.handleMediaupdatetimeout_.bind(ft(n)),n.on("mediaupdatetimeout",n.handleMediaupdatetimeout_),n}mt(e,a);var t=e.prototype;return t.handleMediaupdatetimeout_=function(){var e,t,i=this;"HAVE_METADATA"===this.state&&(e=this.media(),t=dl(this.master.uri,e.uri),this.experimentalLLHLS&&(t=function(e,t){if(t.endList||!t.serverControl)return e;var i,n,r,a,s={};return t.serverControl.canBlockReload&&(r=t.preloadSegment,i=t.mediaSequence+t.segments.length,r&&(n=r.parts||[],-1<(r=Wo(t)-1)&&r!=n.length-1&&(s._HLS_part=r),(-1<r||n.length)&&i--),s._HLS_msn=i),t.serverControl&&t.serverControl.canSkipUntil&&(s._HLS_skip=t.serverControl.canSkipDateranges?"v2":"YES"),Object.keys(s).length&&(a=new window.URL(e),["_HLS_skip","_HLS_msn","_HLS_part"].forEach(function(e){s.hasOwnProperty(e)&&a.searchParams.set(e,s[e])}),e=a.toString()),e}(t,e)),this.state="HAVE_CURRENT_METADATA",this.request=this.vhs_.xhr({uri:t,withCredentials:this.withCredentials},function(e,t){if(i.request)return e?i.playlistRequestError(i.request,i.media(),"HAVE_METADATA"):void i.haveMetadata({playlistString:i.request.responseText,url:i.media().uri,id:i.media().id})}))},t.playlistRequestError=function(e,t,i){var n=t.uri,t=t.id;this.request=null,i&&(this.state=i),this.error={playlist:this.master.playlists[t],status:e.status,message:"HLS playlist request error at URL: "+n+".",responseText:e.responseText,code:500<=e.status?4:2},this.trigger("error")},t.parseManifest_=function(e){var t=this,i=e.url;return function(e){var t=e.onwarn,i=e.oninfo,n=e.manifestString,r=e.customTagParsers,a=void 0===r?[]:r,r=e.customTagMappers,r=void 0===r?[]:r,e=e.experimentalLLHLS,s=new Sr;t&&s.on("warn",t),i&&s.on("info",i),a.forEach(function(e){return s.addParser(e)}),r.forEach(function(e){return s.addTagMapper(e)}),s.push(n),s.end();var o=s.manifest;e||(["preloadSegment","skip","serverControl","renditionReports","partInf","partTargetDuration"].forEach(function(e){o.hasOwnProperty(e)&&delete o[e]}),o.segments&&o.segments.forEach(function(t){["parts","preloadHints"].forEach(function(e){t.hasOwnProperty(e)&&delete t[e]})})),o.targetDuration||(u=10,o.segments&&o.segments.length&&(u=o.segments.reduce(function(e,t){return Math.max(e,t.duration)},0)),t&&t("manifest has no targetDuration defaulting to "+u),o.targetDuration=u);var u=Vo(o);return u.length&&!o.partTargetDuration&&(u=u.reduce(function(e,t){return Math.max(e,t.duration)},0),t&&(t("manifest has no partTargetDuration defaulting to "+u),ml.error("LL-HLS manifest has parts but lacks required #EXT-X-PART-INF:PART-TARGET value. See https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-09#section-4.4.3.7. Playback is not guaranteed.")),o.partTargetDuration=u),o}({onwarn:function(e){e=e.message;return t.logger_("m3u8-parser warn for "+i+": "+e)},oninfo:function(e){e=e.message;return t.logger_("m3u8-parser info for "+i+": "+e)},manifestString:e.manifestString,customTagParsers:this.customTagParsers,customTagMappers:this.customTagMappers,experimentalLLHLS:this.experimentalLLHLS})},t.haveMetadata=function(e){var t=e.playlistString,i=e.playlistOb
4716ject,n=e.url,e=e.id;this.request=null,this.state="HAVE_METADATA";t=i||this.parseManifest_({url:n,manifestString:t});t.lastRequest=Date.now(),su({playlist:t,uri:n,id:e});n=hu(this.master,t);this.targetDuration=t.partTargetDuration||t.targetDuration,this.pendingMedia_=null,n?(this.master=n,this.media_=this.master.playlists[e]):this.trigger("playlistunchanged"),this.updateMediaUpdateTimeout_(pu(this.media(),!!n)),this.trigger("loadedplaylist")},t.dispose=function(){this.trigger("dispose"),this.stopRequest(),window.clearTimeout(this.mediaUpdateTimeout),window.clearTimeout(this.finalRenditionTimeout),this.off()},t.stopRequest=function(){var e;this.request&&(e=this.request,this.request=null,e.onreadystatechange=null,e.abort())},t.media=function(i,e){var n=this;if(!i)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);if("string"==typeof i){if(!this.master.playlists[i])throw new Error("Unknown playlist URI: "+i);i=this.master.playlists[i]}if(window.clearTimeout(this.finalRenditionTimeout),e){var t=(i.partTargetDuration||i.targetDuration)/2*1e3||5e3;this.finalRenditionTimeout=window.setTimeout(this.media.bind(this,i,!1),t)}else{var r=this.state,e=!this.media_||i.id!==this.media_.id,t=this.master.playlists[i.id];if(t&&t.endList||i.endList&&i.segments.length)return this.request&&(this.request.onreadystatechange=null,this.request.abort(),this.request=null),this.state="HAVE_METADATA",this.media_=i,void(e&&(this.trigger("mediachanging"),"HAVE_MASTER"===r?this.trigger("loadedmetadata"):this.trigger("mediachange")));if(this.updateMediaUpdateTimeout_(pu(i,!0)),e){if(this.state="SWITCHING_MEDIA",this.request){if(i.resolvedUri===this.request.url)return;this.request.onreadystatechange=null,this.request.abort(),this.request=null}this.media_&&this.trigger("mediachanging"),this.pendingMedia_=i,this.request=this.vhs_.xhr({uri:i.resolvedUri,withCredentials:this.withCredentials},function(e,t){if(n.request){if(i.lastRequest=Date.now(),i.resolvedUri=Do(n.handleManifestRedirects,i.resolvedUri,t),e)return n.playlistRequestError(n.request,i,r);n.haveMetadata({playlistString:t.responseText,url:i.uri,id:i.id}),"HAVE_MASTER"===r?n.trigger("loadedmetadata"):n.trigger("mediachange")}})}}},t.pause=function(){this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null),this.stopRequest(),"HAVE_NOTHING"===this.state&&(this.started=!1),"SWITCHING_MEDIA"===this.state?this.media_?this.state="HAVE_METADATA":this.state="HAVE_MASTER":"HAVE_CURRENT_METADATA"===this.state&&(this.state="HAVE_METADATA")},t.load=function(e){var t=this;this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null);var i=this.media();e?(e=i?(i.partTargetDuration||i.targetDuration)/2*1e3:5e3,this.mediaUpdateTimeout=window.setTimeout(function(){t.mediaUpdateTimeout=null,t.load()},e)):this.started?i&&!i.endList?this.trigger("mediaupdatetimeout"):this.trigger("loadedplaylist"):this.start()},t.updateMediaUpdateTimeout_=function(e){var t=this;this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null),this.media()&&!this.media().endList&&(this.mediaUpdateTimeout=window.setTimeout(function(){t.mediaUpdateTimeout=null,t.trigger("mediaupdatetimeout"),t.updateMediaUpdateTimeout_(e)},e))},t.start=function(){var i=this;
4716if(this.started=!0,"object"==typeof this.src)return this.src.uri||(this.src.uri=window.location.href),this.src.resolvedUri=this.src.uri,void setTimeout(function(){i.setupInitialPlaylist(i.src)},0);this.request=this.vhs_.xhr({uri:this.src,withCredentials:this.withCredentials},function(e,t){if(i.request){if(i.request=null,e)return i.error={status:t.status,message:"HLS playlist request error at URL: "+i.src+".",responseText:t.responseText,code:2},"HAVE_NOTHING"===i.state&&(i.started=!1),i.trigger("error");i.src=Do(i.handleManifestRedirects,i.src,t);t=i.parseManifest_({manifestString:t.responseText,url:i.src});i.setupInitialPlaylist(t)}})},t.srcUri=function(){return"string"==typeof this.src?this.src:this.src.uri},t.setupInitialPlaylist=function(e){if(this.state="HAVE_MASTER",e.playlists)return this.master=e,ou(this.master,this.srcUri()),e.playlists.forEach(function(t){t.segments=cu(t),t.segments.forEach(function(e){lu(e,t.resolvedUri)})}),this.trigger("loadedplaylist"),void(this.request||this.media(this.master.playlists[0]));var t,i,n,r=this.srcUri()||window.location.href;this.master=(i=ru(0,t=r),(n={mediaGroups:{AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},uri:window.location.href,resolvedUri:window.location.href,playlists:[{uri:t,id:i,resolvedUri:t,attributes:{}}]}).playlists[i]=n.playlists[0],n.playlists[t]=n.playlists[0],n),this.haveMetadata({playlistObject:e,url:r,id:this.master.playlists[0].id}),this.trigger("loadedmetadata")},e}(W),vl=tr.xhr,_l=tr.mergeOptions,zt=Object.freeze({__proto__:null,createTransferableMessage:_u,initSegmentId:bu,segmentKeyId:Tu,hexDump:Su,tagDump:function(e){e=e.bytes;return Su(e)},textRanges:function(e){for(var t,i,n="",r=0;r<e.length;r++)n+=(i=r,(t=e).start(i)+"-"+t.end(i)+" ");return n}}),ar=tr.EventTarget,bl=tr.mergeOptions,Tl=function(a){function e(e,t,i,n){var r;void 0===i&&(i={}),(r=a.call(this)||this).masterPlaylistLoader_=n||ft(r),n||(r.isMaster_=!0);n=i.withCredentials,n=void 0!==n&&n,i=i.handleManifestRedirects,i=void 0!==i&&i;if(r.vhs_=t,r.withCredentials=n,r.handleManifestRedirects=i,!e)throw new Error("A non-empty playlist URL or object is required");return r.on("minimumUpdatePeriod",function(){r.refreshXml_()}),r.on("mediaupdatetimeout",function(){r.refreshMedia_(r.media().id)}),r.state="HAVE_NOTHING",r.loadedPlaylists_={},r.logger_=Oo("DashPlaylistLoader"),r.isMaster_?(r.masterPlaylistLoader_.srcUrl=e,r.masterPlaylistLoader_.sidxMapping_={}):r.childPlaylist_=e,r}mt(e,a);var t=e.prototype;return t.requestErrored_=function(e,t,i){return!this.request||(this.request=null,e?(this.error="object"!=typeof e||e instanceof Error?{status:t.status,message:"DASH request error at URL: "+t.uri,response:t.response,code:2}:e,i&&(this.state=i),this.trigger("error"),!0):void 0)},t.addSidxSegments_=function(a,n,r){var s,o,u=this,l=a.sidx&&bs(a.sidx);a.sidx&&l&&!this.masterPlaylistLoader_.sidxMapping_[l]?(s=Do(this.handleManifestRedirects,a.sidx.resolvedUri),o=function(e,t){if(!u.requestErrored_(e,t,n)){var i,e=u.masterPlaylistLoader_.sidxMapping_;try{i=_o(zs(t.response).subarray(8))}catch(e){return void u.requestErrored_(e,t,n)}return e[l]={sidxInfo:a.sidx,sidx:i},ms(a,i,a.sidx.resolvedUri),r(!0)}},this.request=Cu(s,this.vhs_.xhr,function(e,t,i,n){if(e)return o(e,t);if(!i||"mp4"!==i)return o({status:t.status,message:"Unsupported "+(i||"unknown")+" container type for sidx segment at URL: "+s,response:"",playlist:a,internal:!0,blacklistDuration:1/0,code:2},t);var r=a.sidx.byterange,i=r.offset,r=r.length;if(n.length>=r+i)return o(e,{response:n.subarray(i,i+r),status:t.status,uri:t.uri});u.request=u.vhs_.xhr({uri:s,responseType:"arraybuffer",headers:gu({byterange:a.sidx.byterange})},o)})):this.mediaRequest_=window.setTimeout(function(){return r(!1)},0)},t.dispose=function(){this.trigger("dispose"),this.stopRequest(),this.loadedPlaylists_={},window.clearTimeout(this.minimumUpdatePeriodTimeout_),window.clearTimeout(this.mediaRequest_),window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null,this.mediaRequest_=null,this.minimumUpdatePeriodTimeout_=null,this.masterPlaylistLoader_.createMupOnMedia_&&(this.off("loadedmetadata",this.masterPlaylistLoader_.createMupOnMedia_),this.masterPlaylistLoader_.createMupOnMedia_=null),this.off()},t.hasPendingRequest=function(){return this.request||this.mediaRequest_},t.stopRequest=function(){var e;this.request&&(e=this.request,this.request=null,e.onreadystatechange=null,e.abort())},t.media=function(t){var i=this;if(!t)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);var n=this.state;if("string"==typeof t){if(!this.masterPlaylistLoader_.master.playlists[t])throw new Error("Unknown playlist URI: "+t);t=this.masterPlaylistLoader_.master.playlists[t]}var e=!this.media_||t.id!==this.media_.id;if(e&&this.loadedPlaylists_[t.id]&&this.loadedPlaylists_[t.id].endList)return this.state="HAVE_METADATA",this.media_=t,void(e&&(this.trigger("mediachanging"),this.trigger("mediachange")));e&&(this.media_&&this.trigger("mediachanging"),this.addSidxSegments_(t,n,function(e){i.haveMetadata({startingState:n,playlist:t})}))},t.haveMetadata=function(e){var t=e.startingState,e=e.playlist;this.state="HAVE_METADATA",this.loadedPlaylists_[e.id]=e,this.mediaRequest_=null,this.refreshMedia_(e.id),"HAVE_MASTER"===t?this.trigger("loadedmetadata"):this.trigger("mediachange")},t.pause=function(){this.masterPlaylistLoader_.createMupOnMedia_&&(this.off("loadedmetadata",this.masterPlaylistLoader_.createMupOnMedia_),this.masterPlaylistLoader_.createMupOnMedia_=null),this.stopRequest(),window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null,this.isMaster_&&(window.clearTimeout(this.masterPlaylistLoader_.minimumUpdatePeriodTimeout_),this.masterPlaylistLoader_.minimumUpdatePeriodTimeout_=null),"HAVE_NOTHING"===this.state&&(this.started=!1)},t.load=function(e){var t=this;window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null;var i=this.media();e?(e=i?i.targetDuration/2*1e3:5e3,this.mediaUpdateTimeout=window.setTimeout(function(){return t.load()},e)):this.started?i&&!i.endList?(this.isMaster_&&!this.minimumUpdatePeriodTimeout_&&(this.trigger("minimumUpdatePeriod"),this.updateMinimumUpdatePeriodTimeout_()),this.trigger("mediaupdatetimeout")):this.trigger("loadedplaylist"):this.start()},t.start=function(){var i=this;this.started=!0,this.isMaster_?this.requestMaster_(function(e,t){i.haveMaster_(),i.hasPendingRequest()||i.media_||i.media(i.masterPlaylistLoader_.master.playlists[0])}):this.mediaRequest_=window.setTimeout(function(){return i.haveMaster_()},0)},t.requestMaster_=function(n){var r=this;this.request=this.vhs_.xhr({uri:this.masterPlaylistLoader_.srcUrl,withCredentials:this.withCredentials},function(e,t){if(!r.requestErrored_(e,t)){var i=t.responseText!==r.masterPlaylistLoader_.masterXml_;return r.masterPlaylistLoader_.masterXml_=t.responseText,t.responseHeaders&&t.responseHeaders.date?r.masterLoaded_=Date.parse(t.responseHeaders.date):r.masterLoaded_=Date.now(),r.masterPlaylistLoader_.srcUrl=Do(r.handleManifestRedirects,r.masterPlaylistLoader_.srcUrl,t),i?(r.handleMaster_(),void r.syncClientServerClock_(function(){return n(t,i)})):n(t,i)}"HAVE_NOTHING"===r.state&&(r.started=!1)})},t.syncClientServerClock_=function(i){var n=this,r=Gs(this.masterPlaylistLoader_.masterXml_);return null===r?(this.masterPlaylistLoader_.clientOffset_=this.masterLoaded_-Date.now(),i()):"DIRECT"===r.method?(this.masterPlaylistLoader_.clientOffset_=r.value-Date.now(),i()):void(this.request=this.vhs_.xhr({uri:dl(this.masterPlaylistLoader_.srcUrl,r.value),method:r.method,withCredentials:this.withCredentials},function(e,t){if(n.request){if(e)return n.masterPlaylistLoader_.clientOffset_=n.masterLoaded_-Date.now(),i();t="HEAD"===r.method?t.responseHeaders&&t.responseHeaders.date?Date.parse(t.responseHeaders.date):n.masterLoaded_:Date.parse(t.responseText);n.masterPlaylistLoader_.clientOffset_=t-Date.now(),i()}}))},t.haveMaster_=function(){this.state="HAVE_MASTER",this.isMaster_?this.trigger("loadedplaylist"):this.media_||this.media(this.childPlaylist_)},t.handleMaster_=function(){this.mediaRequest_=null;var e,t,i,n,r=this.masterPlaylistLoader_.master,t=(a={masterXml:this.masterPlaylistLoader_.masterXml_,srcUrl:this.masterPlaylistLoader_.srcUrl,clientOffset:this.masterPlaylistLoader_.clientOffset_,sidxMapping:this.masterPlaylistLoader_.sidxMapping_,previousManifest:r},e=a.masterXml,t=a.srcUrl,i=a.clientOffset,n=a.sidxMapping,a=a.previousManifest,a=Ws(e,{manifestUri:t,clientOffset:i,sidxMapping:n,previousManifest:a}),ou(a,t),a);r&&(t=function(e,t,i){for(var a=!0,s=bl(e,{duration:t.duration,minimumUpdatePeriod:t.minimumUpdatePeriod,timelineStarts:t.timelineStarts}),n=0;n<t.playlists.length;n++){var r,o=t.playlists[n];
4716o.sidx&&(r=bs(o.sidx),i&&i[r]&&i[r].sidx&&ms(o,i[r].sidx,o.sidx.resolvedUri));o=hu(s,o,Iu);o&&(s=o,a=!1)}return au(t,function(e,t,i,n){var r;e.playlists&&e.playlists.length&&(r=e.playlists[0].id,(e=hu(s,e.playlists[0],Iu))&&((s=e).mediaGroups[t][i][n].playlists[0]=s.playlists[r],a=!1))}),(a=t.minimumUpdatePeriod===e.minimumUpdatePeriod&&a)?null:s}(r,t,this.masterPlaylistLoader_.sidxMapping_)),this.masterPlaylistLoader_.master=t||r;var a=this.masterPlaylistLoader_.master.locations&&this.masterPlaylistLoader_.master.locations[0];return a&&a!==this.masterPlaylistLoader_.srcUrl&&(this.masterPlaylistLoader_.srcUrl=a),(!r||t&&t.minimumUpdatePeriod!==r.minimumUpdatePeriod)&&this.updateMinimumUpdatePeriodTimeout_(),Boolean(t)},t.updateMinimumUpdatePeriodTimeout_=function(){var e=this.masterPlaylistLoader_;e.createMupOnMedia_&&(e.off("loadedmetadata",e.createMupOnMedia_),e.createMupOnMedia_=null),e.minimumUpdatePeriodTimeout_&&(window.clearTimeout(e.minimumUpdatePeriodTimeout_),e.minimumUpdatePeriodTimeout_=null);var t=e.master&&e.master.minimumUpdatePeriod;0===t&&(e.media()?t=1e3*e.media().targetDuration:(e.createMupOnMedia_=e.updateMinimumUpdatePeriodTimeout_,e.one("loadedmetadata",e.createMupOnMedia_))),"number"!=typeof t||t<=0?t<0&&this.logger_("found invalid minimumUpdatePeriod of "+t+", not setting a timeout"):this.createMUPTimeout_(t)},t.createMUPTimeout_=function(e){var t=this.masterPlaylistLoader_;t.minimumUpdatePeriodTimeout_=window.setTimeout(function(){t.minimumUpdatePeriodTimeout_=null,t.trigger("minimumUpdatePeriod"),t.createMUPTimeout_(e)},e)},t.refreshXml_=function(){var i=this;this.requestMaster_(function(e,t){var r,a;t&&(i.media_&&(i.media_=i.masterPlaylistLoader_.master.playlists[i.media_.id]),i.masterPlaylistLoader_.sidxMapping_=(t=i.masterPlaylistLoader_.master,r=i.masterPlaylistLoader_.sidxMapping_,a=xu(t.playlists,r),au(t,function(e,t,i,n){e.playlists&&e.playlists.length&&(e=e.playlists,a=bl(a,xu(e,r)))}),a),i.addSidxSegments_(i.media(),i.state,function(e){i.refreshMedia_(i.media().id)}))})},t.refreshMedia_=function(e){var t=this;if(!e)throw new Error("refreshMedia_ must take a media id");this.media_&&this.isMaster_&&this.handleMaster_();var i=this.masterPlaylistLoader_.master.playlists,n=!this.media_||this.media_!==i[e];n?this.media_=i[e]:this.trigger("playlistunchanged"),this.mediaUpdateTimeout||function e(){t.media().endList||(t.mediaUpdateTimeout=window.setTimeout(function(){t.trigger("mediaupdatetimeout"),e()},pu(t.media(),Boolean(n))))}(),this.trigger("loadedplaylist")},e}(ar),Sl={GOAL_BUFFER_LENGTH:30,MAX_GOAL_BUFFER_LENGTH:60,BACK_BUFFER_LENGTH:30,GOAL_BUFFER_LENGTH_RATE:1,INITIAL_BANDWIDTH:4194304,BANDWIDTH_VARIANCE:1.2,BUFFER_LOW_WATER_LINE:0,MAX_BUFFER_LOW_WATER_LINE:30,EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE:16,BUFFER_LOW_WATER_LINE_RATE:1,BUFFER_HIGH_WATER_LINE:30},x=function(n){return function(){var e=function(t){try{return URL.createObjectURL(new Blob([t],{type:"application/javascript"}))}catch(e){var i=new BlobBuilder;return i.append(t),URL.createObjectURL(i.getBlob())}}(n),t=Au(new Worker(e));t.objURL=e;var i=t.terminate;return t.on=t.addEventListener,t.off=t.removeEventListener,t.terminate=function(){return URL.revokeObjectURL(e),i.call(this)},t}},U=function(e){return"var browserWorkerPolyFill = "+Au.toString()+";\nbrowserWorkerPolyFill(self);\n"+e},W=function(e){return e.toString().replace(/^function.+?{/,"").slice(0,-1)},wl=x(U(W(function(){var e=function(){this.init=function(){var a={};this.on=function(e,t){a[e]||(a[e]=[]),a[e]=a[e].concat(t)},this.off=function(e,t){return!!a[e]&&(t=a[e].indexOf(t),a[e]=a[e].slice(),a[e].splice(t,1),-1<t)},this.trigger=function(e){var t,i,n,r=a[e];if(r)if(2===arguments.length)for(i=r.length,t=0;t<i;++t)r[t].call(this,arguments[1]);else{for(n=[],t=arguments.length,t=1;t<arguments.length;++t)n.push(arguments[t]);for(i=r.length,t=0;t<i;++t)r[t].apply(this,n)}},this.dispose=function(){a={}}}};e.prototype.pipe=function(t){return this.on("data",function(e){t.push(e)}),this.on("done",function(e){t.flush(e)}),this.on("partialdone",function(e){t.partialFlush(e)}),this.on("endedtimeline",function(e){t.endTimeline(e)}),this.on("reset",function(e){t.reset(e)}),t},e.prototype.push=function(e){this.trigger("data",e)},e.prototype.flush=function(e){this.trigger("done",e)},e.prototype.partialFlush=function(e){this.trigger("partialdone",e)},e.prototype.endTimeline=function(e){this.trigger("endedtimeline",e)},e.prototype.reset=function(e){this.trigger("reset",e)};var u,t,i,n,r,a,s,o,l,c,d,h,p,f,m,g,y,v,_,b,T,S,w,E,k,C,I,x,A,P,L,D,O,R,M,N,U,B,F,j=e,H=Math.pow(2,32),q={getUint64:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);return t.getBigUint64?(e=t.getBigUint64(0))<Number.MAX_SAFE_INTEGER?
vendor: 7,949 bytes, line 4716
4716Number(e):e:t.getUint32(0)*H+t.getUint32(4)},MAX_UINT32:H},V=q.MAX_UINT32;!function(){if(T={avc1:[],avcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],pasp:[],sdtp:[],smhd:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],styp:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[]},"undefined"!=typeof Uint8Array){for(var e in T)T.hasOwnProperty(e)&&(T[e]=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]);S=new Uint8Array(["i".charCodeAt(0),"s".charCodeAt(0),"o".charCodeAt(0),"m".charCodeAt(0)]),E=new Uint8Array(["a".charCodeAt(0),"v".charCodeAt(0),"c".charCodeAt(0),"1".charCodeAt(0)]),w=new Uint8Array([0,0,0,1]),k=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),C=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),I={video:k,audio:C},P=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),A=new Uint8Array([0,0,0,0,0,0,0,0]),L=new Uint8Array([0,0,0,0,0,0,0,0]),D=L,O=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),R=L,x=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}}(),u=function(e){for(var t,i=[],n=0,r=1;r<arguments.length;r++)i.push(arguments[r]);for(r=i.length;r--;)n+=i[r].byteLength;for(t=new Uint8Array(n+8),new DataView(t.buffer,t.byteOffset,t.byteLength).setUint32(0,t.byteLength),t.set(e,4),r=0,n=8;r<i.length;r++)t.set(i[r],n),n+=i[r].byteLength;return t},t=function(){return u(T.dinf,u(T.dref,P))},i=function(e){return u(T.esds,new Uint8Array([0,0,0,0,3,25,0,0,0,4,17,64,21,0,6,0,0,0,218,192,0,0,218,192,5,2,e.audioobjecttype<<3|e.samplingfrequencyindex>>>1,e.samplingfrequencyindex<<7|e.channelcount<<3,6,1,2]))},f=function(e){return u(T.hdlr,I[e])},p=function(e){var t=new Uint8Array([0,0,0,0,0,0,0,2,0,0,0,3,0,1,95,144,e.duration>>>24&255,e.duration>>>16&255,e.duration>>>8&255,255&e.duration,85,196,0,0]);return e.samplerate&&(t[12]=e.samplerate>>>24&255,t[13]=e.samplerate>>>16&255,t[14]=e.samplerate>>>8&255,t[15]=255&e.samplerate),u(T.mdhd,t)},h=function(e){return u(T.mdia,p(e),f(e.type),a(e))},r=function(e){return u(T.mfhd,new Uint8Array([0,0,0,0,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e]))},a=function(e){return u(T.minf,"video"===e.type?u(T.vmhd,x):u(T.smhd,A),t(),g(e))},We=function(e,t){for(var i=[],n=t.length;n--;)i[n]=v(t[n]);return u.apply(null,[T.moof,r(e)].concat(i))},s=function(e){for(var t=e.length,i=[];t--;)i[t]=c(e[t]);return u.apply(null,[T.moov,l(4294967295)].concat(i).concat(o(e)))},o=function(e){for(var t=e.length,i=[];t--;)i[t]=_(e[t]);return u.apply(null,[T.mvex].concat(i))},l=function(e){e=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,2,0,1,95,144,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return u(T.mvhd,e)},m=function(e){for(var t,i=e.samples||[],n=new Uint8Array(4+i.length),r=0;r<i.length;r++)t=i[r].flags,n[r+4]=t.dependsOn<<4|t.isDependedOn<<2|t.hasRedundancy;return u(T.sdtp,n)},g=function(e){return u(T.stbl,y(e),u(T.stts,R),u(T.stsc,D),u(T.stsz,O),u(T.stco,L))},y=function(e){return u(T.stsd,new Uint8Array([0,0,0,0,0,0,0,1]),("video"===e.type?M:N)(e))},M=function(e){for(var t,i,n=e.sps||[],r=e.pps||[],a=[],s=[],o=0;o<n.length;o++)a.push((65280&n[o].byteLength)>>>8),a.push(255&n[o].byteLength),a=a.concat(Array.prototype.slice.call(n[o]));for(o=0;o<r.length;o++)s.push((65280&r[o].byteLength)>>>8),s.push(255&r[o].byteLength),s=s.concat(Array.prototype.slice.call(r[o]));return t=[T.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(65280&e.width)>>8,255&e.width,(65280&e.height)>>8,255&e.height,0,72,0,0,0,72,0,0,0,0,0,0,0,1,19,118,105,100,101,111,106,115,45,99,111,110,116,114,105,98,45,104,108,115,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),u(T.avcC,new Uint8Array([1,e.profileIdc,e.profileCompatibility,e.levelIdc,255].concat([n.length],a,[r.length],s))),u(T.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192]))],e.sarRatio&&(i=e.sarRatio[0],e=e.sarRatio[1],t.push(u(T.pasp,new Uint8Array([(4278190080&i)>>24,(16711680&i)>>16,(65280&i)>>8,255&i,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e])))),u.apply(null,t)},N=function(e){return u(T.mp4a,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,(65280&e.channelcount)>>8,255&e.channelcount,(65280&e.samplesize)>>8,255&e.samplesize,0,0,0,0,(65280&e.samplerate)>>8,255&e.samplerate,0,0]),i(e))},d=function(e){e=new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,0,(4278190080&e.duration)>>24,(16711680&e.duration)>>16,(65280&e.duration)>>8,255&e.duration,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,(65280&e.width)>>8,255&e.width,0,0,(65280&e.height)>>8,255&e.height,0,0]);return u(T.tkhd,e)},v=function(e){var t,i=u(T.tfhd,new Uint8Array([0,0,0,58,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0])),n=Math.floor(e.baseMediaDecodeTime/V),r=Math.floor(e.baseMediaDecodeTime%V),n=u(T.tfdt,new Uint8Array([1,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,r>>>24&255,r>>>16&255,r>>>8&255,255&r]));return"audio"===e.type?(t=b(e,92),u(T.traf,i,n,t)):(r=m(e),t=b(e,r.length+92),u(T.traf,i,n,t,r))},c=function(e){return e.duration=e.duration||4294967295,u(T.trak,d(e),h(e))},_=function(e){var t=new Uint8Array([0,0,0,0,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return"video"!==e.type&&(t[t.length-1]=0),u(T.trex,t)},U=function(e,t){var i=0,n=0,r=0,a=0;return e.length&&(void 0!==e[0].duration&&(i=1),void 0!==e[0].size&&(n=2),void 0!==e[0].flags&&(r=4),void 0!==e[0].compositionTimeOffset&&(a=8)),[0,0,i|n|r|a,1,(4278190080&e.length)>>>24,(16711680&e.length)>>>16,(65280&e.length)>>>8,255&e.length,(4278190080&t)>>>24,(16711680&t)>>>16,(65280&t)>>>8,255&t]},B=function(e,t){var i,n,r,a,s=e.samples||[];for(t+=20+16*s.length,t=U(s,t),(n=new Uint8Array(t.length+16*s.length)).set(t),i=t.length,a=0;a<s.length;a++)r=s[a],n[i++]=(4278190080&r.duration)>>>24,n[i++]=(16711680&r.duration)>>>16,n[i++]=(65280&r.duration)>>>8,n[i++]=255&r.duration,n[i++]=(4278190080&r.size)>>>24,n[i++]=(16711680&r.size)>>>16,n[i++]=(65280&r.size)>>>8,n[i++]=255&r.size,n[i++]=r.flags.isLeading<<2|r.flags.dependsOn,n[i++]=r.flags.isDependedOn<<6|r.flags.hasRedundancy<<4|r.flags.paddingValue<<1|r.flags.isNonSyncSample,n[i++]=61440&r.flags.degradationPriority,n[i++]=15&r.flags.degradationPriority,n[i++]=(4278190080&r.compositionTimeOffset)>>>24,n[i++]=(16711680&r.compositionTimeOffset)>>>16,n[i++]=(65280&r.compositionTimeOffset)>>>8,n[i++]=255&r.compositionTimeOffset;return u(T.trun,n)},F=function(e,t){var i,n,r,a,s=e.samples||[];for(t+=20+8*s.length,t=U(s,t),(i=new Uint8Array(t.length+8*s.length)).set(t),n=t.length,a=0;a<s.length;a++)r=s[a],i[n++]=(4278190080&r.duration)>>>24,i[n++]=(16711680&r.duration)>>>16,i[n++]=(65280&r.duration)>>>8,i[n++]=255&r.duration,i[n++]=(4278190080&r.size)>>>24,i[n++]=(16711680&r.size)>>>16,i[n++]=(65280&r.size)>>>8,i[n++]=255&r.size;return u(T.trun,i)},b=function(e,t){return("audio"===e.type?F:B)(e,t)};n=function(){return u(T.ftyp,S,w,S,E)};function W(e,t){var i={size:0,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0,degradationPriority:0,isNonSyncSample:1}};return i.dataOffset=t,i.compositionTimeOffset=e.pts-e.dts,i.duration=e.duration,i.size=4*e.length,i.size+=e.byteLength,e.keyFrame&&(i.flags.dependsOn=2,i.flags.isNonSyncSample=0),i}function G(e){for(var t=[];e--;)t.push(0);return t}function z(){var e,i;return X||(e={96e3:[ie,[227,64],G(154),[56]],88200:[ie,[231],G(170),[56]],64e3:[ie,[248,192],G(240),[56]],48e3:[ie,[255,192],G(268),[55,148,128],G(54),[112]],44100:[ie,[25
vendor: 6,584 bytes, line 4716
47165,192],G(268),[55,163,128],G(84),[112]],32e3:[ie,[255,192],G(268),[55,234],G(226),[112]],24e3:[ie,[255,192],G(268),[55,255,128],G(268),[111,112],G(126),[224]],16e3:[ie,[255,192],G(268),[55,255,128],G(268),[111,255],G(269),[223,108],G(195),[1,192]],12e3:[ne,G(268),[3,127,248],G(268),[6,255,240],G(268),[13,255,224],G(268),[27,253,128],G(259),[56]],11025:[ne,G(268),[3,127,248],G(268),[6,255,240],G(268),[13,255,224],G(268),[27,255,192],G(268),[55,175,128],G(108),[112]],8e3:[ne,G(268),[3,121,16],G(47),[7]]},i=e,X=Object.keys(i).reduce(function(e,t){return e[t]=new Uint8Array(i[t].reduce(function(e,t){return e.concat(t)},[])),e},{})),X}var X,K=function(e){return u(T.mdat,e)},Y=We,Q=function(e){var t=n(),i=s(e),e=new Uint8Array(t.byteLength+i.byteLength);return e.set(t),e.set(i,t.byteLength),e},$=function(e){var t,i,n=[],r=[];for(r.byteLength=0,r.nalCount=0,r.duration=0,t=n.byteLength=0;t<e.length;t++)"access_unit_delimiter_rbsp"===(i=e[t]).nalUnitType?(n.length&&(n.duration=i.dts-n.dts,r.byteLength+=n.byteLength,r.nalCount+=n.length,r.duration+=n.duration,r.push(n)),(n=[i]).byteLength=i.data.byteLength,n.pts=i.pts,n.dts=i.dts):("slice_layer_without_partitioning_rbsp_idr"===i.nalUnitType&&(n.keyFrame=!0),n.duration=i.dts-n.dts,n.byteLength+=i.data.byteLength,n.push(i));return r.length&&(!n.duration||n.duration<=0)&&(n.duration=r[r.length-1].duration),r.byteLength+=n.byteLength,r.nalCount+=n.length,r.duration+=n.duration,r.push(n),r},J=function(e){var t,i,n=[],r=[];for(n.byteLength=0,n.nalCount=0,n.duration=0,n.pts=e[0].pts,n.dts=e[0].dts,r.byteLength=0,r.nalCount=0,r.duration=0,r.pts=e[0].pts,r.dts=e[0].dts,t=0;t<e.length;t++)(i=e[t]).keyFrame?(n.length&&(r.push(n),r.byteLength+=n.byteLength,r.nalCount+=n.nalCount,r.duration+=n.duration),(n=[i]).nalCount=i.length,n.byteLength=i.byteLength,n.pts=i.pts,n.dts=i.dts,n.duration=i.duration):(n.duration+=i.duration,n.nalCount+=i.length,n.byteLength+=i.byteLength,n.push(i));return r.length&&n.duration<=0&&(n.duration=r[r.length-1].duration),r.byteLength+=n.byteLength,r.nalCount+=n.nalCount,r.duration+=n.duration,r.push(n),r},Z=function(e){var t;return!e[0][0].keyFrame&&1<e.length&&(t=e.shift(),e.byteLength-=t.byteLength,e.nalCount-=t.nalCount,e[0][0].dts=t.dts,e[0][0].pts=t.pts,e[0][0].duration+=t.duration),e},ee=function(e,t){for(var i,n,r,a=t||0,s=[],o=0;o<e.length;o++)for(n=e[o],i=0;i<n.length;i++)r=n[i],a+=(r=W(r,a)).size,s.push(r);return s},te=function(e){for(var t,i,n,r,a,s=0,o=e.byteLength,u=e.nalCount,l=new Uint8Array(o+4*u),c=new DataView(l.buffer),d=0;d<e.length;d++)for(n=e[d],t=0;t<n.length;t++)for(r=n[t],i=0;i<r.length;i++)a=r[i],c.setUint32(s,a.data.byteLength),l.set(a.data,s+=4),s+=a.data.byteLength;return l},ie=[33,16,5,32,164,27],ne=[33,65,108,84,1,2,4,8,168,2,4,8,17,191,252],re=function(e){return 9e4*e},ae=function(e,t){return e*t},se=function(e){return e/9e4},oe=function(e,t){return e/t},ue=9e4,le=re,ce=se,de=function(e,t){return re(oe(e,t))},he=function(e,t){return ae(se(e),t)},pe=function(e,t,i){return se(i?e:e-t)},fe=function(e,t,i,n){var r,a,s,o,u,l,c=0,d=0;if(t.length&&(r=de(e.baseMediaDecodeTime,e.samplerate),a=Math.ceil(ue/(e.samplerate/1024)),i&&n&&(s=r-Math.max(i,n),d=(c=Math.floor(s/a))*a),!(c<1||ue/2<d))){for(o=(o=z()[e.samplerate])||t[0].data,u=0;u<c;u++)l=t[0],t.splice(0,0,{data:o,dts:l.dts-a,pts:l.pts-a});return e.baseMediaDecodeTime-=Math.floor(he(d,e.samplerate)),d}},me=function(e,t,i){return t.minSegmentDts>=i?e:(t.minSegmentDts=1/0,e.filter(function(e){return e.dts>=i&&(t.minSegmentDts=Math.min(t.minSegmentDts,e.dts),t.minSegmentPts=t.minSegmentDts,!0)}))},ge=function(e){for(var t,i=[],n=0;n<e.length;n++)t=e[n],i.push({size:t.data.byteLength,duration:1024});return i},ye=function(e){for(var t,i=0,n=new Uint8Array(function(e){for(var t=0,i=0;i<e.length;i++)t+=e[i].data.byteLength;return t}(e)),r=0;r<e.length;r++)t=e[r],n.set(t.data,i),i+=t.data.byteLength;return n},ve=ue,_e=function(e){delete e.minSegmentDts,delete e.maxSegmentDts,delete e.minSegmentPts,delete e.maxSegmentPts},be=function(e,t){var i=e.minSegmentDts;return t||(i-=e.timelineStartInfo.dts),t=e.timelineStartInfo.baseMediaDecodeTime,t+=i,t=Math.max(0,t),"audio"===e.type&&(t*=e.samplerate/ve,t=Math.floor(t)),t},Te=function(e,t){"number"==typeof t.pts&&(void 0===e.timelineStartInfo.pts&&(e.timelineStartInfo.pts=t.pts),void 0===e.minSegmentPts?e.minSegmentPts=t.pts:e.minSegmentPts=Math.min(e.minSegmentPts,t.pts),void 0===e.maxSegmentPts?e.maxSegmentPts=t.pts:e.maxSegmentPts=Math.max(e.maxSegmentPts,t.pts)),"number"==typeof t.dts&&(void 0===e.timelineStartInfo.dts&&(e.timelineStartInfo.dts=t.dts),void 0===e.minSegmentDts?e.minSegmentDts=t.dts:e.minSegmentDts=Math.min(e.minSegmentDts,t.dts),void 0===e.maxSegmentDts?e.maxSegmentDts=t.dts:e.maxSegmentDts=Math.max(e.maxSegmentDts,t.dts))},Se=function(e){for(var t=0,i={payloadType:-1,payloadSize:0},n=0,r=0;t<e.byteLength&&128!==e[t];){for(;255===e[t];)n+=255,t++;for(n+=e[t++];255===e[t];)r+=255,t++;if(r+=e[t++],!i.payload&&4===n){if("GA94"===String.fromCharCode(e[t+3],e[t+4],e[t+5],e[t+6])){i.payloadType=n,i.payloadSize=r,i.payload=e.subarray(t,t+r);break}i.payload=void 0}t+=r,r=n=0}return i},we=function(e){return 181!==e.payload[0]||49!=(e.payload[1]<<8|e.payload[2])||"GA94"!==String.fromCharCode(e.payload[3],e.payload[4],e.payload[5],e.payload[6])||3!==e.payload[7]?null:e.payload.subarray(8,e.payload.length-1)},Ee=function(e,t){var i,n,r,a,s=[];if(!(64&t[0]))return s;for(n=31&t[0],i=0;i<n;i++)a={type:3&t[2+(r=3*i)],pts:e},4&t[2+r]&&(a.ccData=t[3+r]<<8|t[4+r],s.push(a));return s},ke=function(e){for(var t=e.byteLength,i=[],n=1;n<t-2;)0===e[n]&&0===e[n+1]&&3===e[n+2]?(i.push(n+2),n+=2):n++;if(0===i.length)return e;for(var r=t-i.length,a=new Uint8Array(r),s=0,n=0;n<r;s++,n++)s===i[0]&&(s++,i.shift()),a[n]=e[s];return a},Ce=4,Ie=function e(t){t=t||{},e.prototype.init.call(this),this.parse708captions_="boolean"!=typeof t.parse708captions||t.parse708captions,this.captionPackets_=[],this.ccStreams_=[new Ue(0,0),new Ue(0,1),new Ue(1,0),new Ue(1,1)],this.parse708captions_&&(this.cc708Stream_=new De({captionServices:t.captionServices})),this.reset(),this.ccStreams_.forEach(function(e){e.on("data",this.trigger.bind(this,"data")),e.on("partialdone",this.trigger.bind(this,"partialdone")),e.on("done",this.trigger.bind(this,"done"))},this),this.parse708captions_&&(this.cc708Stream_.on("data",this.trigger.bind(this,"data")),this.cc708Stream_.on("partialdone",this.trigger.bind(this,"partialdone")),this.cc708Stream_.on("done",this.trigger.bind(this,"done")))};(Ie.prototype=new j).push=function(e){var t,i;
4716if("sei_rbsp"===e.nalUnitType&&(t=Se(e.escapedRBSP)).payload&&t.payloadType===Ce&&(i=we(t)))if(e.dts<this.latestDts_)this.ignoreNextEqualDts_=!0;else{if(e.dts===this.latestDts_&&this.ignoreNextEqualDts_)return this.numSameDts_--,void(this.numSameDts_||(this.ignoreNextEqualDts_=!1));i=Ee(e.pts,i),this.captionPackets_=this.captionPackets_.concat(i),this.latestDts_!==e.dts&&(this.numSameDts_=0),this.numSameDts_++,this.latestDts_=e.dts}},Ie.prototype.flushCCStreams=function(t){this.ccStreams_.forEach(function(e){return"flush"===t?e.flush():e.partialFlush()},this)},Ie.prototype.flushStream=function(e){this.captionPackets_.length&&(this.captionPackets_.forEach(function(e,t){e.presortIndex=t}),this.captionPackets_.sort(function(e,t){return e.pts===t.pts?e.presortIndex-t.presortIndex:e.pts-t.pts}),this.captionPackets_.forEach(function(e){e.type<2?this.dispatchCea608Packet(e):this.dispatchCea708Packet(e)},this),this.captionPackets_.length=0),this.flushCCStreams(e)},Ie.prototype.flush=function(){return this.flushStream("flush")},Ie.prototype.partialFlush=function(){return this.flushStream("partialFlush")},Ie.prototype.reset=function(){this.latestDts_=null,this.ignoreNextEqualDts_=!1,this.numSameDts_=0,this.activeCea608Channel_=[null,null],this.ccStreams_.forEach(function(e){e.reset()})},Ie.prototype.dispatchCea608Packet=function(e){this.setsTextOrXDSActive(e)?this.activeCea608Channel_[e.type]=null:this.setsChannel1Active(e)?this.activeCea608Channel_[e.type]=0:this.setsChannel2Active(e)&&(this.activeCea608Channel_[e.type]=1),null!==this.activeCea608Channel_[e.type]&&this.ccStreams_[(e.type<<1)+this.activeCea608Channel_[e.type]].push(e)},Ie.prototype.setsChannel1Active=function(e){return 4096==(30720&e.ccData)},Ie.prototype.setsChannel2Active=function(e){return 6144==(30720&e.ccData)},Ie.prototype.setsTextOrXDSActive=function(e){return 256==(28928&e.ccData)||4138==(30974&e.ccData)||6186==(30974&e.ccData)},Ie.prototype.dispatchCea708Packet=function(e){this.parse708captions_&&this.cc708Stream_.push(e)};function xe(e){return 32<=e&&e<=127||160<=e&&e<=255}function Ae(e){this.windowNum=e,this.reset()}var Pe={127:9834,4128:32,4129:160,4133:8230,4138:352,4140:338,4144:9608,4145:8216,4146:8217,4147:8220,4148:8221,4149:8226,4153:8482,4154:353,4156:339,4157:8480,4159:376,4214:8539,4215:8540,4216:8541,4217:8542,4218:9168,4219:9124,4220:9123,4221:9135,4222:9126,4223:9121,4256:12600};Ae.prototype.reset=function(){this.clearText(),this.pendingNewLine=!1,this.winAttr={},this.penAttr={},this.penLoc={},this.penColor={},this.visible=0,this.rowLock=0,this.columnLock=0,this.priority=0,this.relativePositioning=0,this.anchorVertical=0,this.anchorHorizontal=0,this.anchorPoint=0,this.rowCount=1,this.virtualRowCount=this.rowCount+1,this.columnCount=41,this.windowStyle=0,this.penStyle=0},Ae.prototype.getText=function(){return this.rows.join("\n")},Ae.prototype.clearText=function(){this.rows=[""],this.rowIdx=0},Ae.prototype.newLine=function(e){for(this.rows.length>=this.virtualRowCount&&"function"==typeof this.beforeRowOverflow&&this.beforeRowOverflow(e),0<this.rows.length&&(this.rows.push(""),this.rowIdx++);this.rows.length>this.virtualRowCount;)this.rows.shift(),this.rowIdx--},Ae.prototype.isEmpty=function(){return 0===this.rows.length||1===this.rows.length&&""===this.rows[0]},Ae.prototype.addText=function(e){this.rows[this.rowIdx]+=e},Ae.prototype.backspace=function(){var e;this.isEmpty()||(e=this.rows[this.rowIdx],this.rows[this.rowIdx]=e.substr(0,e.length-1))};function Le(e,t,i){this.serviceNum=e,this.text="",this.currentWindow=new Ae(-1),this.windows=[],this.stream=i,"string"==typeof t&&this.createTextDecoder(t)}Le.prototype.init=function(e,t){this.startPts=e;for(var i=0;i<8;i++)this.windows[i]=new Ae(i),"function"==typeof t&&(this.windows[i].beforeRowOverflow=t)},Le.prototype.setCurrentWindow=function(e){this.currentWindow=this.windows[e]},Le.prototype.createTextDecoder=function(t){if("undefined"==typeof TextDecoder)this.stream.trigger("log",{level:"warn",message:"The `encoding` option is unsupported without TextDecoder support"});else try{this.textDecoder_=new TextDecoder(t)}catch(e){this.stream.trigger("log",{level:"warn",message:"TextDecoder could not be created with "+t+" encoding. "+e})}};var De=function e(t){t=t||{},e.prototype.init.call(this);var i,n=this,r=t.captionServices||{},a={};Object.keys(r).forEach(function(e){i=r[e],/^SERVICE/.test(e)&&(a[e]=i.encoding)}),this.serviceEncodings=a,this.current708Packet=null,this.services={},this.push=function(e){(3===e.type||null===n.current708Packet)&&n.new708Packet(),n.add708Bytes(e)}};De.prototype=new j,De.prototype.new708Packet=function(){null!==this.current708Packet&&this.push708Packet(),this.current708Packet={data:[],ptsVals:[]}},De.prototype.add708Bytes=function(e){var t=e.ccData,i=t>>>
vendor: 9,399 bytes, line 4716
47168,t=255&t;this.current708Packet.ptsVals.push(e.pts),this.current708Packet.data.push(i),this.current708Packet.data.push(t)},De.prototype.push708Packet=function(){var e,t=this.current708Packet,i=t.data,n=null,r=0,a=i[r++];for(t.seq=a>>6,t.sizeCode=63&a;r<i.length;r++)e=31&(a=i[r++]),7===(n=a>>5)&&0<e&&(n=i[r++]),this.pushServiceBlock(n,r,e),0<e&&(r+=e-1)},De.prototype.pushServiceBlock=function(e,t,i){for(var n,r=t,a=this.current708Packet.data,s=(s=this.services[e])||this.initService(e,r);r<t+i&&r<a.length;r++)n=a[r],xe(n)?r=this.handleText(r,s):24===n?r=this.multiByteCharacter(r,s):16===n?r=this.extendedCommands(r,s):128<=n&&n<=135?r=this.setCurrentWindow(r,s):152<=n&&n<=159?r=this.defineWindow(r,s):136===n?r=this.clearWindows(r,s):140===n?r=this.deleteWindows(r,s):137===n?r=this.displayWindows(r,s):138===n?r=this.hideWindows(r,s):139===n?r=this.toggleWindows(r,s):151===n?r=this.setWindowAttributes(r,s):144===n?r=this.setPenAttributes(r,s):145===n?r=this.setPenColor(r,s):146===n?r=this.setPenLocation(r,s):143===n?s=this.reset(r,s):8===n?s.currentWindow.backspace():12===n?s.currentWindow.clearText():13===n?s.currentWindow.pendingNewLine=!0:14===n?s.currentWindow.clearText():141===n&&r++},De.prototype.extendedCommands=function(e,t){var i=this.current708Packet.data[++e];return e=xe(i)?this.handleText(e,t,{isExtended:!0}):e},De.prototype.getPts=function(e){return this.current708Packet.ptsVals[Math.floor(e/2)]},De.prototype.initService=function(t,e){var i,n="SERVICE"+t,r=this;return n in this.serviceEncodings&&(i=this.serviceEncodings[n]),this.services[t]=new Le(t,i,r),this.services[t].init(this.getPts(e),function(e){r.flushDisplayed(e,r.services[t])}),this.services[t]},De.prototype.handleText=function(e,t,i){var n,r=i&&i.isExtended,a=i&&i.isMultiByte,s=this.current708Packet.data,o=r?4096:0,u=s[e],i=s[e+1],s=t.currentWindow,l=t.textDecoder_&&!r?(a?(n=[u,i],e++):n=[u],t.textDecoder_.decode(new Uint8Array(n))):(l=Pe[u=o|u]||u,4096&u&&u===l?"":String.fromCharCode(l));return s.pendingNewLine&&!s.isEmpty()&&s.newLine(this.getPts(e)),s.pendingNewLine=!1,s.addText(l),e},De.prototype.multiByteCharacter=function(e,t){var i=this.current708Packet.data,n=i[e+1],i=i[e+2];return e=xe(n)&&xe(i)?this.handleText(++e,t,{isMultiByte:!0}):e},De.prototype.setCurrentWindow=function(e,t){var i=this.current708Packet.data[e];return t.setCurrentWindow(7&i),e},De.prototype.defineWindow=function(e,t){var i=this.current708Packet.data,n=i[e];t.setCurrentWindow(7&n);t=t.currentWindow,n=i[++e];return t.visible=(32&n)>>5,t.rowLock=(16&n)>>4,t.columnLock=(8&n)>>3,t.priority=7&n,n=i[++e],t.relativePositioning=(128&n)>>7,t.anchorVertical=127&n,n=i[++e],t.anchorHorizontal=n,n=i[++e],t.anchorPoint=(240&n)>>4,t.rowCount=15&n,n=i[++e],t.columnCount=63&n,n=i[++e],t.windowStyle=(56&n)>>3,t.penStyle=7&n,t.virtualRowCount=t.rowCount+1,e},De.prototype.setWindowAttributes=function(e,t){var i=this.current708Packet.data,n=i[e],t=t.currentWindow.winAttr,n=i[++e];return t.fillOpacity=(192&n)>>6,t.fillRed=(48&n)>>4,t.fillGreen=(12&n)>>2,t.fillBlue=3&n,n=i[++e],t.borderType=(192&n)>>6,t.borderRed=(48&n)>>4,t.borderGreen=(12&n)>>2,t.borderBlue=3&n,n=i[++e],t.borderType+=(128&n)>>5,t.wordWrap=(64&n)>>6,t.printDirection=(48&n)>>4,t.scrollDirection=(12&n)>>2,t.justify=3&n,n=i[++e],t.effectSpeed=(240&n)>>4,t.effectDirection=(12&n)>>2,t.displayEffect=3&n,e},De.prototype.flushDisplayed=function(e,t){for(var i=[],n=0;n<8;n++)t.windows[n].visible&&!t.windows[n].isEmpty()&&i.push(t.windows[n].getText());t.endPts=e,t.text=i.join("\n\n"),this.pushCaption(t),t.startPts=e},De.prototype.pushCaption=function(e){""!==e.text&&(this.trigger("data",{startPts:e.startPts,endPts:e.endPts,text:e.text,stream:"cc708_"+e.serviceNum}),e.text="",e.startPts=e.endPts)},De.prototype.displayWindows=function(e,t){var i=this.current708Packet.data[++e],n=this.getPts(e);this.flushDisplayed(n,t);for(var r=0;r<8;r++)i&1<<r&&(t.windows[r].visible=1);return e},De.prototype.hideWindows=function(e,t){var i=this.current708Packet.data[++e],n=this.getPts(e);this.flushDisplayed(n,t);for(var r=0;r<8;r++)i&1<<r&&(t.windows[r].visible=0);return e},De.prototype.toggleWindows=function(e,t){var i=this.current708Packet.data[++e],n=this.getPts(e);this.flushDisplayed(n,t);for(var r=0;r<8;r++)i&1<<r&&(t.windows[r].visible^=1);return e},De.prototype.clearWindows=function(e,t){var i=this.current708Packet.data[++e],n=this.getPts(e);this.flushDisplayed(n,t);for(var r=0;r<8;r++)i&1<<r&&t.windows[r].clearText();return e},De.prototype.deleteWindows=function(e,t){var i=this.current708Packet.data[++e],n=this.getPts(e);this.flushDisplayed(n,t);for(var r=0;r<8;r++)i&1<<r&&t.windows[r].reset();return e},De.prototype.setPenAttributes=function(e,t){var i=this.current708Packet.data,n=i[e],t=t.currentWindow.penAttr,n=i[++e];return t.textTag=(240&n)>>4,t.offset=(12&n)>>2,t.penSize=3&n,n=i[++e],t.italics=(128&n)>>7,t.underline=(64&n)>>6,t.edgeType=(56&n)>>3,t.fontStyle=7&n,e},De.prototype.setPenColor=function(e,t){var i=this.current708Packet.data,n=i[e],t=t.currentWindow.penColor,n=i[++e];return t.fgOpacity=(192&n)>>6,t.fgRed=(48&n)>>4,t.fgGreen=(12&n)>>2,t.fgBlue=3&n,n=i[++e],t.bgOpacity=(192&n)>>6,t.bgRed=(48&n)>>4,t.bgGreen=(12&n)>>2,t.bgBlue=3&n,n=i[++e],t.edgeRed=(48&n)>>4,t.edgeGreen=(12&n)>>2,t.edgeBlue=3&n,e},De.prototype.setPenLocation=function(e,t){var i=this.current708Packet.data,n=i[e],r=t.currentWindow.penLoc;return t.currentWindow.pendingNewLine=!0,n=i[++e],r.row=15&n,n=i[++e],r.column=63&n,e},De.prototype.reset=function(e,t){var i=this.getPts(e);return this.flushDisplayed(i,t),this.initService(t.serviceNum,e)};function Oe(e){return null===e?"":(e=Me[e]||e,String.fromCharCode(e))}function Re(){for(var e=[],t=15;t--;)e.push("");return e}var Me={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,304:174,305:176,306:189,307:191,308:8482,309:162,310:163,311:9834,312:224,313:160,314:232,315:226,316:234,317:238,318:244,319:251,544:193,545:201,546:211,547:218,548:220,549:252,550:8216,551:161,552:42,553:39,554:8212,555:169,556:8480,557:8226,558:8220,559:8221,560:192,561:194,562:199,563:200,564:202,565:203,566:235,567:206,568:207,569:239,570:212,571:217,572:249,573:219,574:171,575:187,800:195,801:227,802:205,803:204,804:236,805:210,806:242,807:213,808:245,809:123,810:125,811:92,812:94,813:95,814:124,815:126,816:196,817:228,818:214,819:246,820:223,821:165,822:164,823:9474,824:197,825:229,826:216,827:248,828:9484,829:9488,830:9492,831:9496},Ne=[4352,4384,4608,4640,5376,5408,5632,5664,5888,5920,4096,4864,4896,5120,5152],Ue=function e(t,i){e.prototype.init.call(this),this.field_=t||0,this.dataChannel_=i||0,this.name_="CC"+(1+(this.field_<<1|this.dataChannel_)),this.setConstants(),this.reset(),this.push=function(e){var t,i,n,r,a=32639&e.ccData;a!==this.lastControlCode_?(4096==(61440&a)?this.lastControlCode_=a:a!==this.PADDING_&&(this.lastControlCode_=null),t=a>>>8,i=255&a,a===this.PADDING_||(a===this.RESUME_CAPTION_LOADING_?this.mode_="popOn":a===this.END_OF_CAPTION_?(this.mode_="popOn",this.clearFormatting(e.pts),this.flushDisplayed(e.pts),r=this.displayed_,this.displayed_=this.nonDisplayed_,this.nonDisplayed_=r,this.startPts_=e.pts):a===this.ROLL_UP_2_ROWS_?(this.rollUpRows_=2,this.setRollUp(e.pts)):a===this.ROLL_UP_3_ROWS_?(this.rollUpRows_=3,this.setRollUp(e.pts)):a===this.ROLL_UP_4_ROWS_?(this.rollUpRows_=4,this.setRollUp(e.pts)):a===this.CARRIAGE_RETURN_?(this.clearFormatting(e.pts),this.flushDisplayed(e.pts),this.shiftRowsUp_(),this.startPts_=e.pts):a===this.BACKSPACE_?"popOn"===this.mode_?this.nonDisplayed_[this.row_]=this.nonDisplayed_[this.row_].slice(0,-1):this.displayed_[this.row_]=this.displayed_[this.row_].slice(0,-1):a===this.ERASE_DISPLAYED_MEMORY_?(this.flushDisplayed(e.pts),this.displayed_=Re()):a===this.ERASE_NON_DISPLAYED_MEMORY_?this.nonDisplayed_=Re():a===this.RESUME_DIRECT_CAPTIONING_?("paintOn"!==this.mode_&&(this.flushDisplayed(e.pts),this.displayed_=Re()),this.mode_="paintOn",this.startPts_=e.pts):this.isSpecialCharacter(t,i)?(n=Oe((t=(3&t)<<8)|i),this[this.mode_](e.pts,n),this.column_++):this.isExtCharacter(t,i)?("popOn"===this.mode_?this.nonDisplayed_[this.row_]=this.nonDisplayed_[this.row_].slice(0,-1):this.displayed_[this.row_]=this.displayed_[this.row_].slice(0,-1),n=Oe((t=(3&t)<<8)|i),this[this.mode_](e.pts,n),this.column_++):this.isMidRowCode(t,i)?(this.clearFormatting(e.pts),this[this.mode_](e.pts," "),this.column_++,14==(14&i)&&this.addFormatting(e.pts,["i"]),1==(1&i)&&this.addFormatting(e.pts,["u"])):this.isOffsetControlCode(t,i)?this.column_+=3&i:this.isPAC(t,i)?(r=Ne.indexOf(7968&a),"rollUp"===this.mode_&&(r-this.rollUpRows_+1<0&&(r=this.rollUpRows_-1),this.setRollUp(e.pts,r)),r!==this.row_&&(this.clearFormatting(e.pts),this.row_=r),1&i&&-1===this.formatting_.indexOf("u")&&this.addFormatting(e.pts,["u"]),16==(16&a)&&(this.column_=4*((14&a)>>1)),this.isColorPAC(i)&&14==(14&i)&&this.addFormatting(e.pts,["i"])):this.isNormalChar(t)&&(0===i&&(i=null),n=Oe(t),n+=Oe(i),this[this.mode_](e.pts,n),this.column_+=n.length))):this.lastControlCode_=null}};Ue.prototype=new j,Ue.prototype.flushDisplayed=function(e){var t=this.displayed_.map(function(e,t){try{return e.trim()}catch(e){return this.trigger("log",{level:"warn",message:"Skipping a malformed 608 caption at index "+t+"."}),""}},this).join("\n").replace(/^\n+|\n+$/g,"");t.length&&this.trigger("data",{startPts:this.startPts_,endPts:e,text:t,stream
vendor: 5,760 bytes, line 4716
4716:this.name_})},Ue.prototype.reset=function(){this.mode_="popOn",this.topRow_=0,this.startPts_=0,this.displayed_=Re(),this.nonDisplayed_=Re(),this.lastControlCode_=null,this.column_=0,this.row_=14,this.rollUpRows_=2,this.formatting_=[]},Ue.prototype.setConstants=function(){0===this.dataChannel_?(this.BASE_=16,this.EXT_=17,this.CONTROL_=(20|this.field_)<<8,this.OFFSET_=23):1===this.dataChannel_&&(this.BASE_=24,this.EXT_=25,this.CONTROL_=(28|this.field_)<<8,this.OFFSET_=31),this.PADDING_=0,this.RESUME_CAPTION_LOADING_=32|this.CONTROL_,this.END_OF_CAPTION_=47|this.CONTROL_,this.ROLL_UP_2_ROWS_=37|this.CONTROL_,this.ROLL_UP_3_ROWS_=38|this.CONTROL_,this.ROLL_UP_4_ROWS_=39|this.CONTROL_,this.CARRIAGE_RETURN_=45|this.CONTROL_,this.RESUME_DIRECT_CAPTIONING_=41|this.CONTROL_,this.BACKSPACE_=33|this.CONTROL_,this.ERASE_DISPLAYED_MEMORY_=44|this.CONTROL_,this.ERASE_NON_DISPLAYED_MEMORY_=46|this.CONTROL_},Ue.prototype.isSpecialCharacter=function(e,t){return e===this.EXT_&&48<=t&&t<=63},Ue.prototype.isExtCharacter=function(e,t){return(e===this.EXT_+1||e===this.EXT_+2)&&32<=t&&t<=63},Ue.prototype.isMidRowCode=function(e,t){return e===this.EXT_&&32<=t&&t<=47},Ue.prototype.isOffsetControlCode=function(e,t){return e===this.OFFSET_&&33<=t&&t<=35},Ue.prototype.isPAC=function(e,t){return e>=this.BASE_&&e<this.BASE_+8&&64<=t&&t<=127},Ue.prototype.isColorPAC=function(e){return 64<=e&&e<=79||96<=e&&e<=127},Ue.prototype.isNormalChar=function(e){return 32<=e&&e<=127},Ue.prototype.setRollUp=function(e,t){if("rollUp"!==this.mode_&&(this.row_=14,this.mode_="rollUp",this.flushDisplayed(e),this.nonDisplayed_=Re(),this.displayed_=Re()),void 0!==t&&t!==this.row_)for(var i=0;i<this.rollUpRows_;i++)this.displayed_[t-i]=this.displayed_[this.row_-i],this.displayed_[this.row_-i]="";void 0===t&&(t=this.row_),this.topRow_=t-this.rollUpRows_+1},Ue.prototype.addFormatting=function(e,t){this.formatting_=this.formatting_.concat(t);t=t.reduce(function(e,t){return e+"<"+t+">"},"");this[this.mode_](e,t)},Ue.prototype.clearFormatting=function(e){var t;this.formatting_.length&&(t=this.formatting_.reverse().reduce(function(e,t){return e+"</"+t+">"},""),this.formatting_=[],this[this.mode_](e,t))},Ue.prototype.popOn=function(e,t){var i=this.nonDisplayed_[this.row_];this.nonDisplayed_[this.row_]=i+=t},Ue.prototype.rollUp=function(e,t){var i=this.displayed_[this.row_];this.displayed_[this.row_]=i+=t},Ue.prototype.shiftRowsUp_=function(){for(var e=0;e<this.topRow_;e++)this.displayed_[e]="";for(e=this.row_+1;e<15;e++)this.displayed_[e]="";for(e=this.topRow_;e<this.row_;e++)this.displayed_[e]=this.displayed_[e+1];this.displayed_[this.row_]=""},Ue.prototype.paintOn=function(e,t){var i=this.displayed_[this.row_];this.displayed_[this.row_]=i+=t};function Be(e,t){var i=1;for(t<e&&(i=-1);4294967296<Math.abs(t-e);)e+=8589934592*i;return e}var Fe={CaptionStream:Ie,Cea608Stream:Ue,Cea708Stream:De},je={H264_STREAM_TYPE:27,ADTS_STREAM_TYPE:15,METADATA_STREAM_TYPE:21},e=function e(t){var i,n;e.prototype.init.call(this),this.type_=t||"shared",this.push=function(e){"shared"!==this.type_&&e.type!==this.type_||(void 0===n&&(n=e.dts),e.dts=Be(e.dts,n),e.pts=Be(e.pts,n),i=e.dts,this.trigger("data",e))},this.flush=function(){n=i,this.trigger("done")},this.endTimeline=function(){this.flush(),this.trigger("endedtimeline")},this.discontinuity=function(){i=n=void 0},this.reset=function(){this.discontinuity(),this.trigger("reset")}};e.prototype=new j;function He(e,t,i){for(var n="",r=t;r<i;r++)n+="%"+("00"+e[r].toString(16)).slice(-2);return n}function qe(e,t,i){return decodeURIComponent(He(e,t,i))}function Ve(e){return e[0]<<21|e[1]<<14|e[2]<<7|e[3]}var We=e,Ie=Be,Ge={TXXX:function(e){var t;if(3===e.data[0]){for(t=1;t<e.data.length;t++)if(0===e.data[t]){e.description=qe(e.data,1,t),e.value=qe(e.data,t+1,e.data.length).replace(/\0*$/,"");break}e.data=e.value}},WXXX:function(e){var t;if(3===e.data[0])for(t=1;t<e.data.length;t++)if(0===e.data[t]){e.description=qe(e.data,1,t),e.url=qe(e.data,t+1,e.data.length);break}},PRIV:function(e){for(var t,i=0;i<e.data.length;i++)if(0===e.data[i]){e.owner=(t=e.data,unescape(He(t,0,i)));break}e.privateData=e.data.subarray(i+1),e.data=e.privateData}},ze=function(e){var t,i={descriptor:e&&e.descriptor},u=0,l=[],c=0;if(ze.prototype.init.call(this),this.dispatchType=je.METADATA_STREAM_TYPE.toString(16),i.descriptor)for(t=0;t<i.descriptor.length;t++)this.dispatchType+=("00"+i.descriptor[t].toString(16)).slice(-2);this.push=function(e){var t,i,n,r,a,s,o;if("timed-metadata"===e.type)if(e.dataAlignmentIndicator&&(c=0,l.length=0),0===l.length&&(e.data.length<10||e.data[0]!=="I".charCodeAt(0)||e.data[1]!=="D".charCodeAt(0)||e.data[2]!=="3".charCodeAt(0)))this.trigger("log",{level:"warn",message:"Skipping unrecognized metadata packet"});else if(l.push(e),c+=e.data.byteLength,1===l.length&&(u=Ve(e.data.subarray(6,10)),u+=10),!(c<u)){for(t={data:new Uint8Array(u),frames:[],pts:l[0].pts,dts:l[0].dts},r=0;r<u;)t.data.set(l[0].data.subarray(0,u-r),r),r+=l[0].data.byteLength,c-=l[0].data.byteLength,l.shift();i=10,64&t.data[5]&&(i+=4,i+=Ve(t.data.subarray(10,14)),u-=Ve(t.data.subarray(16,20)));do{if((n=Ve(t.data.subarray(i+4,i+8)))<1)return void this.trigger("log",{level:"warn",message:"Malformed ID3 frame encountered. Skipping metadata parsing."})}while((o={id:String.fromCharCode(t.data[i],t.data[i+1],t.data[i+2],t.data[i+3]),data:t.data.subarray(i+10,i+n+10)}).key=o.id,Ge[o.id]&&(Ge[o.id](o),"com.apple.streaming.transportStreamTimestamp"===o.owner&&(s=(1&(a=o.data)[3])<<30|a[4]<<22|a[5]<<14|a[6]<<6|a[7]>>>2,s*=4,s+=3&a[7],o.timeStamp=s,void 0===t.pts&&void 0===t.dts&&(t.pts=o.timeStamp,t.dts=o.timeStamp),this.trigger("timestamp",o))),t.frames.push(o),i+=10,(i+=n)<u);this.trigger("data",t)}}};ze.prototype=new j;
vendor: 11,044 bytes, line 4716
4716var Xe,Ke,e=ze,We=We,Ye=function(){var r=new Uint8Array(188),a=0;Ye.prototype.init.call(this),this.push=function(e){var t,i=0,n=188;for(a?((t=new Uint8Array(e.byteLength+a)).set(r.subarray(0,a)),t.set(e,a),a=0):t=e;n<t.byteLength;)71!==t[i]||71!==t[n]?(i++,n++):(this.trigger("data",t.subarray(i,n)),i+=188,n+=188);i<t.byteLength&&(r.set(t.subarray(i),0),a=t.byteLength-i)},this.flush=function(){188===a&&71===r[0]&&(this.trigger("data",r),a=0),this.trigger("done")},this.endTimeline=function(){this.flush(),this.trigger("endedtimeline")},this.reset=function(){a=0,this.trigger("reset")}};Ye.prototype=new j,(Xe=function(){var n,r,a,s;Xe.prototype.init.call(this),(s=this).packetsWaitingForPmt=[],this.programMapTable=void 0,n=function(e,t){var i=0;t.payloadUnitStartIndicator&&(i+=e[i]+1),("pat"===t.type?r:a)(e.subarray(i),t)},r=function(e,t){t.section_number=e[7],t.last_section_number=e[8],s.pmtPid=(31&e[10])<<8|e[11],t.pmtPid=s.pmtPid},a=function(e,t){var i,n;if(1&e[5]){for(s.programMapTable={video:null,audio:null,"timed-metadata":{}},i=3+((15&e[1])<<8|e[2])-4,n=12+((15&e[10])<<8|e[11]);n<i;){var r=e[n],a=(31&e[n+1])<<8|e[n+2];r===je.H264_STREAM_TYPE&&null===s.programMapTable.video?s.programMapTable.video=a:r===je.ADTS_STREAM_TYPE&&null===s.programMapTable.audio?s.programMapTable.audio=a:r===je.METADATA_STREAM_TYPE&&(s.programMapTable["timed-metadata"][a]=r),n+=5+((15&e[n+3])<<8|e[n+4])}t.programMapTable=s.programMapTable}},this.push=function(e){var t={},i=4;if(t.payloadUnitStartIndicator=!!(64&e[1]),t.pid=31&e[1],t.pid<<=8,t.pid|=e[2],1<(48&e[3])>>>4&&(i+=e[i]+1),0===t.pid)t.type="pat",n(e.subarray(i),t),this.trigger("data",t);else if(t.pid===this.pmtPid)for(t.type="pmt",n(e.subarray(i),t),this.trigger("data",t);this.packetsWaitingForPmt.length;)this.processPes_.apply(this,this.packetsWaitingForPmt.shift());else void 0===this.programMapTable?this.packetsWaitingForPmt.push([e,i,t]):this.processPes_(e,i,t)},this.processPes_=function(e,t,i){i.pid===this.programMapTable.video?i.streamType=je.H264_STREAM_TYPE:i.pid===this.programMapTable.audio?i.streamType=je.ADTS_STREAM_TYPE:i.streamType=this.programMapTable["timed-metadata"][i.pid],i.type="pes",i.data=e.subarray(t),this.trigger("data",i)}}).prototype=new j,Xe.STREAM_TYPES={h264:27,adts:15},(Ke=function(){function n(e,t,i){var n,r,a,s,o=new Uint8Array(e.size),u={type:t},l=0,c=0;if(e.data.length&&!(e.size<9)){for(u.trackId=e.data[0].pid,l=0;l<e.data.length;l++)n=e.data[l],o.set(n.data,c),c+=n.data.byteLength;a=u,s=(r=o)[0]<<16|r[1]<<8|r[2],a.data=new Uint8Array,1==s&&(a.packetLength=6+(r[4]<<8|r[5]),a.dataAlignmentIndicator=0!=(4&r[6]),192&(s=r[7])&&(a.pts=(14&r[9])<<27|(255&r[10])<<20|(254&r[11])<<12|(255&r[12])<<5|(254&r[13])>>>3,a.pts*=4,a.pts+=(6&r[13])>>>1,a.dts=a.pts,64&s&&(a.dts=(14&r[14])<<27|(255&r[15])<<20|(254&r[16])<<12|(255&r[17])<<5|(254&r[18])>>>3,a.dts*=4,a.dts+=(6&r[18])>>>1)),a.data=r.subarray(9+r[8])),t="video"===t||u.packetLength<=e.size,(i||t)&&(e.size=0,e.data.length=0),t&&d.trigger("data",u)}}var t,d=this,r=!1,a={data:[],size:0},s={data:[],size:0},o={data:[],size:0};Ke.prototype.init.call(this),this.push=function(i){({pat:function(){},pes:function(){var e,t;switch(i.streamType){case je.H264_STREAM_TYPE:e=a,t="video";break;case je.ADTS_STREAM_TYPE:e=s,t="audio";break;case je.METADATA_STREAM_TYPE:e=o,t="timed-metadata";break;default:return}i.payloadUnitStartIndicator&&n(e,t,!0),e.data.push(i),e.size+=i.data.byteLength},pmt:function(){var e={type:"metadata",tracks:[]};null!==(t=i.programMapTable).video&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.video,codec:"avc",type:"video"}),null!==t.audio&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.audio,codec:"adts",type:"audio"}),r=!0,d.trigger("data",e)}})[i.type]()},this.reset=function(){a.size=0,a.data.length=0,s.size=0,s.data.length=0,this.trigger("reset")},this.flushStreams_=function(){n(a,"video"),n(s,"audio"),n(o,"timed-metadata")},this.flush=function(){var e;!r&&t&&(e={type:"metadata",tracks:[]},null!==t.video&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.video,codec:"avc",type:"video"}),null!==t.audio&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.audio,codec:"adts",type:"audio"}),d.trigger("data",e)),r=!1,this.flushStreams_(),this.trigger("done")}}).prototype=new j;var Qe,$e={PAT_PID:0,MP2T_PACKET_LENGTH:188,TransportPacketStream:Ye,TransportParseStream:Xe,ElementaryStream:Ke,TimestampRolloverStream:We,CaptionStream:Fe.CaptionStream,Cea608Stream:Fe.Cea608Stream,Cea708Stream:Fe.Cea708Stream,MetadataStream:e};for(Qe in je)je.hasOwnProperty(Qe)&&($e[Qe]=je[Qe]);var Je=$e,Ze=ue,et=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],tt=function(u){var l,c=0;tt.prototype.init.call(this),this.skipWarn_=function(e,t){this.trigger("log",{level:"warn",message:"adts skiping bytes "+e+" to "+t+" in frame "+c+" outside syncword"})},this.push=function(e){var t,i,n,r,a,s,o=0;if(u||(c=0),"audio"===e.type){for(l&&l.length?(n=l,(l=new Uint8Array(n.byteLength+e.data.byteLength)).set(n),l.set(e.data,n.byteLength)):l=e.data;o+7<l.length;)if(255===l[o]&&240==(246&l[o+1])){if("number"==typeof s&&(this.skipWarn_(s,o),s=null),i=2*(1&~l[o+1]),t=(3&l[o+3])<<11|l[o+4]<<3|(224&l[o+5])>>5,a=(r=1024*(1+(3&l[o+6])))*Ze/et[(60&l[o+2])>>>2],l.byteLength-o<t)break;this.trigger("data",{pts:e.pts+c*a,dts:e.dts+c*a,sampleCount:r,audioobjecttype:1+(l[o+2]>>>6&3),channelcount:(1&l[o+2])<<2|(192&l[o+3])>>>6,samplerate:et[(60&l[o+2])>>>2],samplingfrequencyindex:(60&l[o+2])>>>2,samplesize:16,data:l.subarray(o+7+i,o+t)}),c++,o+=t}else"number"!=typeof s&&(s=o),o++;"number"==typeof s&&(this.skipWarn_(s,o),s=null),l=l.subarray(o)}},this.flush=function(){c=0,this.trigger("done")},this.reset=function(){l=void 0,this.trigger("reset")},this.endTimeline=function(){l=void 0,this.trigger("endedtimeline")}};tt.prototype=new j;var it,nt,rt=tt,at=function(n){var r=n.byteLength,a=0,s=0;this.length=function(){return 8*r},this.bitsAvailable=function(){return 8*r+s},this.loadWord=function(){var e=n.byteLength-r,t=new Uint8Array(4),i=Math.min(4,r);if(0===i)throw new Error("no bytes available");t.set(n.subarray(e,e+i)),a=new DataView(t.buffer).getUint32(0),s=8*i,r-=i},this.skipBits=function(e){var t;e<s||(e-=s,e-=8*(t=Math.floor(e/8)),r-=t,this.loadWord()),a<<=e,s-=e},this.readBits=function(e){var t=Math.min(s,e),i=a>>>32-t;return 0<(s-=t)?a<<=t:0<r&&this.loadWord(),0<(t=e-t)?i<<t|this.readBits(t):i},this.skipLeadingZeros=function(){for(var e=0;e<s;++e)if(0!=(a&2147483648>>>e))return a<<=e,s-=e,e;return this.loadWord(),e+this.skipLeadingZeros()},this.skipUnsignedExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.skipExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.readUnsignedExpGolomb=function(){var e=this.skipLeadingZeros();return this.readBits(e+1)-1},this.readExpGolomb=function(){var e=this.readUnsignedExpGolomb();return 1&e?1+e>>>1:-1*(e>>>1)},this.readBoolean=function(){return 1===this.readBits(1)},this.readUnsignedByte=function(){return this.readBits(8)},this.loadWord()},st=function(){var n,r,a=0;st.prototype.init.call(this),this.push=function(e){for(var t,i=(r=r?((t=new Uint8Array(r.byteLength+e.data.byteLength)).set(r),t.set(e.data,r.byteLength),t):e.data).byteLength;a<i-3;a++)if(1===r[a+2]){n=a+5;break}for(;n<i;)switch(r[n]){case 0:if(0!==r[n-1]){n+=2;break}if(0!==r[n-2]){n++;break}for(a+3!==n-2&&this.trigger("data",r.subarray(a+3,n-2));1!==r[++n]&&n<i;);a=n-2,n+=3;break;case 1:if(0!==r[n-1]||0!==r[n-2]){n+=3;break}this.trigger("data",r.subarray(a+3,n-2)),a=n-2,n+=3;break;default:n+=3}r=r.subarray(a),n-=a,a=0},this.reset=function(){r=null,a=0,this.trigger("reset")},this.flush=function(){r&&3<r.byteLength&&this.trigger("data",r.subarray(a+3)),r=null,a=0,this.trigger("done")},this.endTimeline=function(){this.flush(),this.trigger("endedtimeline")}};st.prototype=new j,nt={100:!0,110:!0,122:!0,244:!0,44:!0,83:!0,86:!0,118:!0,128:!0,138:!0,139:!0,134:!0},(it=function(){var i,n,r,a,s,o,m,t=new st;it.prototype.init.call(this),(i=this).push=function(e){"video"===e.type&&(n=e.trackId,r=e.pts,a=e.dts,t.push(e))},t.on("data",function(e){var t={trackId:n,pts:r,dts:a,data:e,nalUnitTypeCode:31&e[0]};switch(t.nalUnitTypeCode){case 5:t.nalUnitType="slice_layer_without_partitioning_rbsp_idr";break;case 6:t.nalUnitType="sei_rbsp",t.escapedRBSP=s(e.subarray(1));break;case 7:t.nalUnitType="seq_parameter_set_rbsp",t.escapedRBSP=s(e.subarray(1)),t.config=o(t.escapedRBSP);break;case 8:t.nalUnitType="pic_parameter_set_rbsp";break;case 9:t.nalUnitType="access_unit_delimiter_rbsp"}i.trigger("data",t)}),t.on("done",function(){i.trigger("done")}),t.on("partialdone",function(){i.trigger("partialdone")}),t.on("reset",function(){i.trigger("reset")}),t.on("endedtimeline",function(){i.trigger("endedtimeline")}),this.flush=function(){t.flush()},this.partialFlush=function(){t.partialFlush()},this.reset=function(){t.reset()},this.endTimeline=function(){t.endTimeline()},m=function(e,t){for(var i=8,n=8,r=0;r<e;r++)i=0===(n=0!==n?(i+t.readExpGolomb()+256)%256:n)?i:n},s=function(e){for(var t=e.byteLength,i=[],n=1;n<t-2;)0===e[n]&&0===e[n+1]&&3===e[n+2]?(i.push(n+2),n+=2):n++;if(0===i.length)return e;for(var r=t-i.length,a=new Uint8Array(r),s=0,n=0;n<r;s++,n++)s===i[0]&&(s++,i.shift()),a[n]=e[s];return a},o=function(e){var t,i,n,r,a,s=0,o=0,u=0,l=0,c=[1,1],d=new at(e),h=d.readUnsignedByte(),p=d.readUnsignedByte(),f=d.readUnsignedByte();if(d.skipUnsignedExpGolomb(),nt[h]&&(3===(i=d.readUnsignedExpGolomb())&&d.skipBits(1),d.skipUnsignedExpGolomb(),d.skipUnsignedExpGolomb(),d.skipBits(1),d.readBoolean()))for(r=3!==i?8:12,a=0;a<r;a++)d.readBoolean()&&m(a<6?16:64,d);if(d.skipUnsignedExpGolomb(),0===(n=d.readUnsignedExpGolomb()))d.readUnsignedExpGolomb();else if(1===n)for(d.skipBits(1),d.skipExpGolomb(),d.skipExpGolomb(),t=d.readUnsignedExpGolomb(),a=0;a<t;a++)d.skipExpGolomb();if(d.skipUnsignedExpGolomb(),d.skipBits(1),e=d.readUnsignedExpGolomb(),i=d.readUnsignedExpGolomb(),0===(n=d.readBits(1))&&d.skipBits(1),d.skipBits(1),d.readBoolean()&&(s=d.readUnsignedExpGolomb(),o=d.readUnsignedExpGolomb(),u=d.readUnsignedExpGolomb(),l=d.readUnsignedExpGolomb()),d.readBoolean()&&d.readBoolean()){switch(d.readUnsignedByte()){case 1:c=[1,1];break;case 2:c=[12,11];break;case 3:c=[10,11];break;case 4:c=[16,11];break;case 5:c=[40,33];break;case 6:c=[24,11];break;case 7:c=[20,11];break;case 8:c=[32,11];break;case 9:c=[80,33];break;case 10:c=[18,11];break;case 11:c=[15,11];break;case 12:c=[64,33];break;case 13:c=[160,99];break;case 14:c=[4,3];break;case 15:c=[3,2];break;case 16:c=[2,1];break;case 255:c=[d.readUnsignedByte()<<8|d.readUnsignedByte(),d.readUnsignedByte()<<8|d.readUnsignedByte()]}c&&(c[0],c[1])}return{profileIdc:h,levelIdc:f,profileCompatibility:p,width:16*(e+1)-2*s-2*o,height:(2-n)*(i+1)*16-2*u-2*l,sarRatio:c}}}).prototype=new j;function ot(e,t){var i=0<=(i=e[t+6]<<21|e[t+7]<<14|e[t+8]<<7|e[t+9])?i:0;return(16&e[t+5])>>4?i+20:i+10}function ut(e,t){return e.length-t<10||e[t]!=="I".charCodeAt(0)||e[t+1
4716]!=="D".charCodeAt(0)||e[t+2]!=="3".charCodeAt(0)?t:ut(e,t+=ot(e,t))}function lt(e){return e[0]<<21|e[1]<<14|e[2]<<7|e[3]}var e={H264Stream:it,NalByteStream:st},ct=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],dt={isLikelyAacData:function(e){var t=ut(e,0);return e.length>=t+2&&255==(255&e[t])&&240==(240&e[t+1])&&16==(22&e[t+1])},parseId3TagSize:ot,parseAdtsSize:function(e,t){var i=(224&e[t+5])>>5,n=e[t+4]<<3;return 6144&e[t+3]|n|i},parseType:function(e,t){return e[t]==="I".charCodeAt(0)&&e[t+1]==="D".charCodeAt(0)&&e[t+2]==="3".charCodeAt(0)?"timed-metadata":!0&e[t]&&240==(240&e[t+1])?"audio":null},parseSampleRate:function(e){for(var t=0;t+5<e.length;){if(255===e[t]&&240==(246&e[t+1]))return ct[(60&e[t+2])>>>2];t++}return null},parseAacTimestamp:function(e){var t,i=10;64&e[5]&&(i+=4,i+=lt(e.subarray(10,14)));do{if((t=lt(e.subarray(i+4,i+8)))<1)return null;if("PRIV"===String.fromCharCode(e[i],e[i+1],e[i+2],e[i+3]))for(var n=e.subarray(i+10,i+t+10),r=0;r<n.byteLength;r++)if(0===n[r]){if("com.apple.streaming.transportStreamTimestamp"!==unescape(function(e,t,i){for(var n="",r=t;r<i;r++)n+="%"+("00"+e[r].toString(16)).slice(-2);return n}(n,0,r)))break;var a=n.subarray(r+1),s=(1&a[3])<<30|a[4]<<22|a[5]<<14|a[6]<<6|a[7]>>>2;return s*=4,s+=3&a[7]}}while(i+=10,(i+=t)<e.byteLength);return null}},ht=function(){var a=new Uint8Array,s=0;ht.prototype.init.call(this),this.setTimestamp=function(e){s=e},this.push=function(e){var t,i,n=0,r=0;for(a.length?(i=a.length,(a=new Uint8Array(e.byteLength+i)).set(a.subarray(0,i)),a.set(e,i)):a=e;3<=a.length-r;)if(a[r]!=="I".charCodeAt(0)||a[r+1]!=="D".charCodeAt(0)||a[r+2]!=="3".charCodeAt(0))if(255!=(255&a[r])||240!=(240&a[r+1]))r++;else{if(a.length-r<7)break;if(r+(n=dt.parseAdtsSize(a,r))>a.length)break;t={type:"audio",data:a.subarray(r,r+n),pts:s,dts:s},this.trigger("data",t),r+=n}else{if(a.length-r<10)break;if(r+(n=dt.parseId3TagSize(a,r))>a.length)break;t={type:"timed-metadata",data:a.subarray(r,r+n)},this.trigger("data",t),r+=n}e=a.length-r,a=0<e?a.subarray(r):new Uint8Array},this.reset=function(){a=new Uint8Array,this.trigger("reset")},this.endTimeline=function(){a=new Uint8Array,this.trigger("endedtimeline")}};ht.prototype=new j;function pt(e,t){t.stream=e,this.trigger("log",t)}function ft(e,t){for(var i=Object.keys(t),n=0;n<i.length;n++){var r=i[n];"headOfPipeline"!==r&&t[r].on&&t[r].on("log",pt.bind(e,r))}}function mt(e,t){var i;if(e.length===t.length){for(i=0;i<e.length;i++)if(e[i]!==t[i])return;return 1}}function gt(e,t,i,n,r,a){return{start:{dts:e,pts:e+(i-t)},end:{dts:e+(n-t),pts:e+(r-i)},prependedContentDuration:a,baseMediaDecodeTime:e}}var yt,vt,_t,bt=ht,Tt=["audioobjecttype","channelcount","samplerate","samplingfrequencyindex","samplesize"],St=["width","height","profileIdc","levelIdc","profileCompatibility","sarRatio"],wt=e.H264Stream,Et=dt.isLikelyAacData,kt=ue,Ct=function(a,s){var o=[],u=0,l=0,c=1/0,d=(s=s||{}).firstSequenceNumber||0;Ct.prototype.init.call(this),this.push=function(t){Te(a,t),a&&Tt.forEach(function(e){a[e]=t[e]}),o.push(t)},this.setEarliestDts=function(e){u=e},this.setVideoBaseMediaDecodeTime=function(e){c=e},this.setAudioAppendStart=function(e){l=e},this.flush=function(){var e,t,i,n,r;0!==o.length&&(e=me(o,a,u),a.baseMediaDecodeTime=be(a,s.keepOriginalTimestamps),r=fe(a,e,l,c),a.samples=ge(e),t=K(ye(e)),o=[],n=Y(d,[a]),i=new Uint8Array(n.byteLength+t.byteLength),d++,i.set(n),i.set(t,n.byteLength),_e(a),n=Math.ceil(1024*kt/a.samplerate),e.length&&(n=e.length*n,this.trigger("segmentTimingInfo",gt(de(a.baseMediaDecodeTime,a.samplerate),e[0].dts,e[0].pts,e[0].dts+n,e[0].pts+n,r||0)),this.trigger("timingInfo",{start:e[0].pts,end:e[0].pts+n})),this.trigger("data",{track:a,boxes:i})),this.trigger("done","AudioSegmentStream")},this.reset=function(){_e(a),o=[],this.trigger("reset")}};Ct.prototype=new j,(yt=function(s,a){var t,i,o=[],l=[],u=(a=a||{}).firstSequenceNumber||0;yt.prototype.init.call(this),delete s.minPTS,this.gopCache_=[],this.push=function(e){Te(s,e),"seq_parameter_set_rbsp"!==e.nalUnitType||t||(t=e.config,s.sps=[e.data],St.forEach(function(e){s[e]=t[e]}
vendor: 5,015 bytes, line 4716
4716,this)),"pic_parameter_set_rbsp"!==e.nalUnitType||i||(i=e.data,s.pps=[e.data]),o.push(e)},this.flush=function(){for(var e,t,i,n=0;o.length&&"access_unit_delimiter_rbsp"!==o[0].nalUnitType;)o.shift();if(0===o.length)return this.resetStream_(),void this.trigger("done","VideoSegmentStream");if(e=$(o),(t=J(e))[0][0].keyFrame||((i=this.getGopForFusion_(o[0],s))?(n=i.duration,t.unshift(i),t.byteLength+=i.byteLength,t.nalCount+=i.nalCount,t.pts=i.pts,t.dts=i.dts,t.duration+=i.duration):t=Z(t)),l.length){var r=a.alignGopsAtEnd?this.alignGopsAtEnd_(t):this.alignGopsAtStart_(t);if(!r)return this.gopCache_.unshift({gop:t.pop(),pps:s.pps,sps:s.sps}),this.gopCache_.length=Math.min(6,this.gopCache_.length),o=[],this.resetStream_(),void this.trigger("done","VideoSegmentStream");_e(s),t=r}Te(s,t),s.samples=ee(t),e=K(te(t)),s.baseMediaDecodeTime=be(s,a.keepOriginalTimestamps),this.trigger("processedGopsInfo",t.map(function(e){return{pts:e.pts,dts:e.dts,byteLength:e.byteLength}})),i=t[0],r=t[t.length-1],this.trigger("segmentTimingInfo",gt(s.baseMediaDecodeTime,i.dts,i.pts,r.dts+r.duration,r.pts+r.duration,n)),this.trigger("timingInfo",{start:t[0].pts,end:t[t.length-1].pts+t[t.length-1].duration}),this.gopCache_.unshift({gop:t.pop(),pps:s.pps,sps:s.sps}),this.gopCache_.length=Math.min(6,this.gopCache_.length),o=[],this.trigger("baseMediaDecodeTime",s.baseMediaDecodeTime),this.trigger("timelineStartInfo",s.timelineStartInfo),n=Y(u,[s]),t=new Uint8Array(n.byteLength+e.byteLength),u++,t.set(n),t.set(e,n.byteLength),this.trigger("data",{track:s,boxes:t}),this.resetStream_(),this.trigger("done","VideoSegmentStream")},this.reset=function(){this.resetStream_(),o=[],this.gopCache_.length=0,l.length=0,this.trigger("reset")},this.resetStream_=function(){_e(s),i=t=void 0},this.getGopForFusion_=function(e){for(var t,i,n,r=1/0,a=0;a<this.gopCache_.length;a++)i=(n=this.gopCache_[a]).gop,s.pps&&mt(s.pps[0],n.pps[0])&&s.sps&&mt(s.sps[0],n.sps[0])&&(i.dts<s.timelineStartInfo.dts||-1e4<=(i=e.dts-i.dts-i.duration)&&i<=45e3&&(!t||i<r)&&(t=n,r=i));return t?t.gop:null},this.alignGopsAtStart_=function(e){for(var t,i,n,r,a=e.byteLength,s=e.nalCount,o=e.duration,u=t=0;u<l.length&&t<e.length&&(i=l[u],n=e[t],i.pts!==n.pts);)n.pts>i.pts?u++:(t++,a-=n.byteLength,s-=n.nalCount,o-=n.duration);return 0===t?e:t===e.length?null:((r=e.slice(t)).byteLength=a,r.duration=o,r.nalCount=s,r.pts=r[0].pts,r.dts=r[0].dts,r)},this.alignGopsAtEnd_=function(e){for(var t,i,n=l.length-1,r=e.length-1,a=null,s=!1;0<=n&&0<=r;){if(t=l[n],i=e[r],t.pts===i.pts){s=!0;break}t.pts>i.pts?n--:(n===l.length-1&&(a=r),r--)}if(!s&&null===a)return null;if(0===(u=s?r:a))return e;var o=e.slice(u),u=o.reduce(function(e,t){return e.byteLength+=t.byteLength,e.duration+=t.duration,e.nalCount+=t.nalCount,e},{byteLength:0,duration:0,nalCount:0});return o.byteLength=u.byteLength,o.duration=u.duration,o.nalCount=u.nalCount,o.pts=o[0].pts,o.dts=o[0].dts,o},this.alignGopsWith=function(e){l=e}}).prototype=new j,(_t=function(e,t){this.numberOfTracks=0,this.metadataStream=t,"undefined"!=typeof(e=e||{}).remux?this.remuxTracks=!!e.remux:this.remuxTracks=!0,"boolean"==typeof e.keepOriginalTimestamps?this.keepOriginalTimestamps=e.keepOriginalTimestamps:this.keepOriginalTimestamps=!1,this.pendingTracks=[],this.videoTrack=null,this.pendingBoxes=[],this.pendingCaptions=[],this.pendingMetadata=[],this.pendingBytes=0,this.emittedTracks=0,_t.prototype.init.call(this),this.push=function(e){return e.text?this.pendingCaptions.push(e):e.frames?this.pendingMetadata.push(e):(this.pendingTracks.push(e.track),this.pendingBytes+=e.boxes.byteLength,"video"===e.track.type&&(this.videoTrack=e.track,this.pendingBoxes.push(e.boxes)),void("audio"===e.track.type&&(this.audioTrack=e.track,this.pendingBoxes.unshift(e.boxes))))}}).prototype=new j,_t.prototype.flush=function(e){var t,i,n,r=0,a={captions:[],captionStreams:{},metadata:[],info:{}},s=0;if(this.pendingTracks.length<this.numberOfTracks){if("VideoSegmentStream"!==e&&"AudioSegmentStream"!==e)return;if(this.remuxTracks)return;if(0===this.pendingTracks.length)return this.emittedTracks++,void(this.emittedTracks>=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0))}if(this.videoTrack?(s=this.videoTrack.timelineStartInfo.pts,St.forEach(function(e){a.info[e]=this.videoTrack[e]},this)):this.audioTrack&&(s=this.audioTrack.timelineStartInfo.pts,Tt.forEach(function(e){a.info[e]=this.audioTrack[e]},this)),this.videoTrack||this.audioTrack){for(1===this.pendingTracks.length?a.type=this.pendingTracks[0].type:a.type="combined",this.emittedTracks+=this.pendingTracks.length,e=Q(this.pendingTracks),a.initSegment=new Uint8Array(e.byteLength),a.initSegment.set(e),a.data=new Uint8Array(this.pendingBytes),n=0;n<this.pendingBoxes.length;n++)a.data.set(this.pendingBoxes[n],r),r+=this.pendingBoxes[n].byteLength;for(n=0;n<this.pendingCaptions.length;n++)(t=this.pendingCaptions[n]).startTime=pe(t.startPts,s,this.keepOriginalTimestamps),t.endTime=pe(t.endPts,s,this.keepOriginalTimestamps),a.captionStream
vendor: 6,438 bytes, line 4716
4716s[t.stream]=!0,a.captions.push(t);for(n=0;n<this.pendingMetadata.length;n++)(i=this.pendingMetadata[n]).cueTime=pe(i.pts,s,this.keepOriginalTimestamps),a.metadata.push(i);for(a.metadata.dispatchType=this.metadataStream.dispatchType,this.pendingTracks.length=0,this.videoTrack=null,this.pendingBoxes.length=0,this.pendingCaptions.length=0,this.pendingBytes=0,this.pendingMetadata.length=0,this.trigger("data",a),n=0;n<a.captions.length;n++)t=a.captions[n],this.trigger("caption",t);for(n=0;n<a.metadata.length;n++)i=a.metadata[n],this.trigger("id3Frame",i)}this.emittedTracks>=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0)},_t.prototype.setRemux=function(e){this.remuxTracks=e},(vt=function(n){var r,a,s=this,i=!0;vt.prototype.init.call(this),this.baseMediaDecodeTime=(n=n||{}).baseMediaDecodeTime||0,this.transmuxPipeline_={},this.setupAacPipeline=function(){var t={};(this.transmuxPipeline_=t).type="aac",t.metadataStream=new Je.MetadataStream,t.aacStream=new bt,t.audioTimestampRolloverStream=new Je.TimestampRolloverStream("audio"),t.timedMetadataTimestampRolloverStream=new Je.TimestampRolloverStream("timed-metadata"),t.adtsStream=new rt,t.coalesceStream=new _t(n,t.metadataStream),t.headOfPipeline=t.aacStream,t.aacStream.pipe(t.audioTimestampRolloverStream).pipe(t.adtsStream),t.aacStream.pipe(t.timedMetadataTimestampRolloverStream).pipe(t.metadataStream).pipe(t.coalesceStream),t.metadataStream.on("timestamp",function(e){t.aacStream.setTimestamp(e.timeStamp)}),t.aacStream.on("data",function(e){"timed-metadata"!==e.type&&"audio"!==e.type||t.audioSegmentStream||(a=a||{timelineStartInfo:{baseMediaDecodeTime:s.baseMediaDecodeTime},codec:"adts",type:"audio"},t.coalesceStream.numberOfTracks++,t.audioSegmentStream=new Ct(a,n),t.audioSegmentStream.on("log",s.getLogTrigger_("audioSegmentStream")),t.audioSegmentStream.on("timingInfo",s.trigger.bind(s,"audioTimingInfo")),t.adtsStream.pipe(t.audioSegmentStream).pipe(t.coalesceStream),s.trigger("trackinfo",{hasAudio:!!a,hasVideo:!!r}))}),t.coalesceStream.on("data",this.trigger.bind(this,"data")),t.coalesceStream.on("done",this.trigger.bind(this,"done")),ft(this,t)},this.setupTsPipeline=function(){var i={};(this.transmuxPipeline_=i).type="ts",i.metadataStream=new Je.MetadataStream,i.packetStream=new Je.TransportPacketStream,i.parseStream=new Je.TransportParseStream,i.elementaryStream=new Je.ElementaryStream,i.timestampRolloverStream=new Je.TimestampRolloverStream,i.adtsStream=new rt,i.h264Stream=new wt,i.captionStream=new Je.CaptionStream(n),i.coalesceStream=new _t(n,i.metadataStream),i.headOfPipeline=i.packetStream,i.packetStream.pipe(i.parseStream).pipe(i.elementaryStream).pipe(i.timestampRolloverStream),i.timestampRolloverStream.pipe(i.h264Stream),i.timestampRolloverStream.pipe(i.adtsStream),i.timestampRolloverStream.pipe(i.metadataStream).pipe(i.coalesceStream),i.h264Stream.pipe(i.captionStream).pipe(i.coalesceStream),i.elementaryStream.on("data",function(e){var t;if("metadata"===e.type){for(t=e.tracks.length;t--;)r||"video"!==e.tracks[t].type?a||"audio"!==e.tracks[t].type||((a=e.tracks[t]).timelineStartInfo.baseMediaDecodeTime=s.baseMediaDecodeTime):(r=e.tracks[t]).timelineStartInfo.baseMediaDecodeTime=s.baseMediaDecodeTime;r&&!i.videoSegmentStream&&(i.coalesceStream.numberOfTracks++,i.videoSegmentStream=new yt(r,n),i.videoSegmentStream.on("log",s.getLogTrigger_("videoSegmentStream")),i.videoSegmentStream.on("timelineStartInfo",function(e){a&&!n.keepOriginalTimestamps&&(a.timelineStartInfo=e,i.audioSegmentStream.setEarliestDts(e.dts-s.baseMediaDecodeTime))}),i.videoSegmentStream.on("processedGopsInfo",s.trigger.bind(s,"gopInfo")),i.videoSegmentStream.on("segmentTimingInfo",s.trigger.bind(s,"videoSegmentTimingInfo")),i.videoSegmentStream.on("baseMediaDecodeTime",function(e){a&&i.audioSegmentStream.setVideoBaseMediaDecodeTime(e)}),i.videoSegmentStream.on("timingInfo",s.trigger.bind(s,"videoTimingInfo")),i.h264Stream.pipe(i.videoSegmentStream).pipe(i.coalesceStream)),a&&!i.audioSegmentStream&&(i.coalesceStream.numberOfTracks++,i.audioSegmentStream=new Ct(a,n),i.audioSegmentStream.on("log",s.getLogTrigger_("audioSegmentStream")),i.audioSegmentStream.on("timingInfo",s.trigger.bind(s,"audioTimingInfo")),i.audioSegmentStream.on("segmentTimingInfo",s.trigger.bind(s,"audioSegmentTimingInfo")),i.adtsStream.pipe(i.audioSegmentStream).pipe(i.coalesceStream)),s.trigger("trackinfo",{hasAudio:!!a,hasVideo:!!r})}}),i.coalesceStream.on("data",this.trigger.bind(this,"data")),i.coalesceStream.on("id3Frame",function(e){e.dispatchType=i.metadataStream.dispatchType,s.trigger("id3Frame",e)}),i.coalesceStream.on("caption",this.trigger.bind(this,"caption")),i.coalesceStream.on("done",this.trigger.bind(this,"done")),ft(this,i)},this.setBaseMediaDecodeTime=function(e){var t=this.transmuxPipeline_;n.keepOriginalTimestamps||(this.baseMediaDecodeTime=e),a&&(a.timelineStartInfo.dts=void 0,a.timelineStartInfo.pts=void 0,_e(a),t.audioTimestampRolloverStream&&t.audioTimestampRolloverStream.discontinuity()),r&&(t.videoSegmentStream&&(t.videoSegmentStream.gopCache_=[]),r.timelineStartInfo.dts=void 0,r.timelineStartInfo.pts=void 0,_e(r),t.captionStream.reset()),t.timestampRolloverStream&&t.timestampRolloverStream.discontinuity()},this.setAudioAppendStart=function(e){a&&this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(e)},this.setRemux=function(e){var t=this.transmuxPipeline_;n.remux=e,t&&t.coalesceStream&&t.coalesceStream.setRemux(e)},this.alignGopsWith=function(e){r&&this.transmuxPipeline_.videoSegmentStream&&this.transmuxPipeline_.videoSegmentStream.alignGopsWith(e)},this.getLogTrigger_=function(t){var i=this;return function(e){e.stream=t,i.trigger("log",e)}},this.push=function(e){var t;i&&((t=Et(e))&&"aac"!==this.transmuxPipeline_.type?this.setupAacPipeline():t||"ts"===this.transmuxPipeline_.type||this.setupTsPipeline(),i=!1),this.transmuxPipeline_.headOfPipeline.push(e)},this.flush=function(){i=!0,this.transmuxPipeline_.headOfPipeline.flush()},this.endTimeline=function(){this.transmuxPipeline_.headOfPipeline.endTimeline()},this.reset=function(){this.transmuxPipeline_.headOfPipeline&&this.transmuxPipeline_.headOfPipeline.reset()},this.resetCaptions=function(){this.transmuxPipeline_.captionStream&&this.transmuxPipeline_.captionStream.reset()}}).prototype=new j;function It(e,c){var i=Mt(e,["moof","traf"]),e=Mt(e,["mdat"]),d={},n=[];return e.forEach(function(e,t){t=i[t];n.push({mdat:e,traf:t})}
4716),n.forEach(function(e){var t,i,n,r,a,s=e.mdat,o=e.traf,u=Mt(o,["tfhd"]),l=Ht(u[0]),e=l.trackId,u=Mt(o,["tfdt"]),u=0<u.length?Bt(u[0]).baseMediaDecodeTime:0,o=Mt(o,["trun"]);c===e&&0<o.length&&(o=o,t=u,i=(l=l).defaultSampleDuration||0,n=l.defaultSampleSize||0,r=l.trackId,a=[],o.forEach(function(e){e=jt(e).samples;e.forEach(function(e){void 0===e.duration&&(e.duration=i),void 0===e.size&&(e.size=n),e.trackId=r,e.dts=t,void 0===e.compositionTimeOffset&&(e.compositionTimeOffset=0),"bigint"==typeof t?(e.pts=t+qt.BigInt(e.compositionTimeOffset),t+=qt.BigInt(e.duration)):(e.pts=t+e.compositionTimeOffset,t+=e.duration)}),a=a.concat(e)}),s=function(e,t,i){for(var n,r,a=new DataView(e.buffer,e.byteOffset,e.byteLength),s={logs:[],seiNals:[]},o=0;o+4<e.length;o+=n)if(n=a.getUint32(o),o+=4,!(n<=0))switch(31&e[o]){case 6:var u=e.subarray(o+1,o+1+n),l=function(e,t){for(var i=e,n=0;n<t.length;n++){var r=t[n];if(i<r.size)return r;i-=r.size}return null}(o,t),u={nalUnitType:"sei_rbsp",size:n,data:u,escapedRBSP:Vt(u),trackId:i};if(l)u.pts=l.pts,u.dts=l.dts,r=l;else{if(!r){s.logs.push({level:"warn",message:"We've encountered a nal unit without data at "+o+" for trackId "+i+". See mux.js#223."});break}u.pts=r.pts,u.dts=r.dts}s.seiNals.push(u)}return s}(s,a,e),d[e]||(d[e]={seiNals:[],logs:[]}),d[e].seiNals=d[e].seiNals.concat(s.seiNals),d[e].logs=d[e].logs.concat(s.logs))}),d}function xt(e){var t=31&e[1];return t<<=8,t|=e[2]}function At(e){return!!(64&e[1])}function Pt(e){var t=0;return 1<(48&e[3])>>>4&&(t+=e[4]+1),t}function Lt(e){switch(e){case 5:return"slice_layer_without_partitioning_rbsp_idr";case 6:return"sei_rbsp";case 7:return"seq_parameter_set_rbsp";case 8:return"pic_parameter_set_rbsp";case 9:return"access_unit_delimiter_rbsp";default:return null}}var Dt={Transmuxer:vt,VideoSegmentStream:yt,AudioSegmentStream:Ct,AUDIO_PROPERTIES:Tt,VIDEO_PROPERTIES:St,generateSegmentTimingInfo:gt},e=function(e){return e>>>0},Ot=function(e){var t="";return t+=String.fromCharCode(e[0]),t+=String.fromCharCode(e[1]),t+=String.fromCharCode(e[2]),t+=String.fromCharCode(e[3])},Rt=e,Mt=function e(t,i){var n,r,a,s=[];if(!i.length)return null;for(n=0;n<t.byteLength;)r=Rt(t[n]<<24|t[n+1]<<16|t[n+2]<<8|t[n+3]),a=Ot(t.subarray(n+4,n+8)),r=1<r?n+r:t.byteLength,a===i[0]&&(1===i.length?s.push(t.subarray(n+8,r)):(a=e(t.subarray(n+8,r),i.slice(1))).length&&(s=s.concat(a))),n=r;return s},Nt=e,Ut=q.getUint64,Bt=function(e){var t={version:e[0],flags:new Uint8Array(e.subarray(1,4))};return 1===t.version?t.baseMediaDecodeTime=Ut(e.subarray(4)):t.baseMediaDecodeTime=Nt(e[4]<<24|e[5]<<16|e[6]<<8|e[7]),t},Ft=function(e){return{isLeading:(12&e[0])>>>2,dependsOn:3&e[0],isDependedOn:(192&e[1])>>>6,hasRedundancy:(48&e[1])>>>4,paddingValue:(14&e[1])>>>1,isNonSyncSample:1&e[1],degradationPriority:e[2]<<8|e[3]}},jt=function(e){var t,i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),samples:[]},n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=1&i.flags[2],a=4&i.flags[2],s=1&i.flags[1],o=2&i.flags[1],u=4&i.flags[1],l=8&i.flags[1],c=n.getUint32(4),d=8;for(r&&(i.dataOffset=n.getInt32(d),d+=4),a&&c&&(t={flags:Ft(e.subarray(d,d+4))},d+=4,s&&(t.duration=n.getUint32(d),d+=4),o&&(t.size=n.getUint32(d),d+=4),l&&(1===i.version?t.compositionTimeOffset=n.getInt32(d):t.compositionTimeOffset=n.getUint32(d),d+=4),i.samples.push(t),c--);c--;)t={},s&&(t.duration=n.getUint32(d),d+=4),o&&(t.size=n.getUint32(d),d+=4),u&&(t.flags=Ft(e.subarray(d,d+4)),d+=4),l&&(1===i.version?t.compositionTimeOffset=n.getInt32(d):t.compositionTimeOffset=n.getUint32(d),d+=4),i.samples.push(t);return i},Ht=function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),trackId:t.getUint32(4)},n=1&i.flags[2],r=2&i.flags[2],a=8&i.flags[2],s=16&i.flags[2],o=32&i.flags[2],u=65536&i.flags[0],l=131072&i.flags[0],e=8;return n&&(e+=4,i.baseDataOffset=t.getUint32(12),e+=4),r&&(i.sampleDescriptionIndex=t.getUint32(e),e+=4),a&&(i.defaultSampleDuration=t.getUint32(e),e+=4),s&&(i.defaultSampleSize=t.getUint32(e),e+=4),o&&(i.defaultSampleFlags=t.getUint32(e)),u&&(i.durationIsEmpty=!0),!n&&l&&(i.baseDataOffsetIsMoof=!0),i},j="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},j="undefined"!=typeof window?window:"undefined"!=typeof j?j:"undefined"!=typeof self?self:{},qt=j,Vt=ke,Wt=Fe.CaptionStream,Gt=function(){var t,r,a,s,o,i,n=!1;this.isInitialized=function(){return n},this.init=function(e){t=new Wt,n=!0,i=!!e&&e.isPartial,t.on("data",function(e){e.startTime=e.startPts/s,e.endTime=e.endPts/s,o.captions.push(e),o.captionStream
4716s[e.stream]=!0}),t.on("log",function(e){o.logs.push(e)})},this.isNewInit=function(e,t){return!(e&&0===e.length||t&&"object"==typeof t&&0===Object.keys(t).length)&&(a!==e[0]||s!==t[a])},this.parse=function(e,t,i){if(!this.isInitialized())return null;if(!t||!i)return null;if(this.isNewInit(t,i))a=t[0],s=i[a];else if(null===a||!s)return r.push(e),null;for(;0<r.length;){var n=r.shift();this.parse(n,t,i)}return(e=function(e,t,i){if(null===t)return null;t=It(e,t)[t]||{};return{seiNals:t.seiNals,logs:t.logs,timescale:i}}(e,a,s))&&e.logs&&(o.logs=o.logs.concat(e.logs)),null!==e&&e.seiNals?(this.pushNals(e.seiNals),this.flushStream(),o):o.logs.length?{logs:o.logs,captions:[],captionStreams:[]}:null},this.pushNals=function(e){if(!this.isInitialized()||!e||0===e.length)return null;e.forEach(function(e){t.push(e)})},this.flushStream=function(){if(!this.isInitialized())return null;i?t.partialFlush():t.flush()},this.clearParsedCaptions=function(){o.captions=[],o.captionStreams={},o.logs=[]},this.resetCaptionStream=function(){if(!this.isInitialized())return null;t.reset()},this.clearAllCaptions=function(){this.clearParsedCaptions(),this.resetCaptionStream()},this.reset=function(){r=[],s=a=null,o?this.clearParsedCaptions():o={captions:[],captionStreams:{},logs:[]},this.resetCaptionStream()},this.reset()},zt=e,Xt=function(e){return("00"+e.toString(16)).slice(-2)},Kt=q.getUint64,j=function(e){return Mt(e,["moov","trak"]).reduce(function(e,t){var i,n,r=Mt(t,["tkhd"])[0];return r?(i=r[0],r=zt(r[n=0===i?12:20]<<24|r[1+n]<<16|r[2+n]<<8|r[3+n]),(t=Mt(t,["mdia","mdhd"])[0])?(i=t[0],e[r]=zt(t[n=0===i?12:20]<<24|t[1+n]<<16|t[2+n]<<8|t[3+n]),e):null):null},{})},ke=function(a,e){e=Mt(e,["moof","traf"]).reduce(function(e,t){var i,n=Mt(t,["tfhd"])[0],r=zt(n[4]<<24|n[5]<<16|n[6]<<8|n[7]),n=a[r]||9e4,r=Mt(t,["tfdt"])[0],t=new DataView(r.buffer,r.byteOffset,r.byteLength),t=1===r[0]?Kt(r.subarray(4,12)):t.getUint32(4);return"bigint"==typeof t?i=t/qt.BigInt(n):"number"!=typeof t||isNaN(t)||(i=t/n),e=(i=i<Number.MAX_SAFE_INTEGER?Number(i):i)<e?i:e},1/0);return"bigint"==typeof e||isFinite(e)?e:0},e=function(e){var e=Mt(e,["moov","trak"]),n=[];return e.forEach(function(e){var t=Mt(e,["mdia","hdlr"]),i=Mt(e,["tkhd"]);t.forEach(function(e,t){e=Ot(e.subarray(8,12)),t=i[t];"vide"===e&&(t=0===(t=new DataView(t.buffer,t.byteOffset,t.byteLength)).getUint8(0)?t.getUint32(12):t.getUint32(20),n.push(t))})}),n},Yt=function(e){var t=0===e[0]?12:20;return zt(e[t]<<24|e[1+t]<<16|e[2+t]<<8|e[3+t])},q=function(e){var e=Mt(e,["moov","trak"]),s=[];return e.forEach(function(e){var t={},i=Mt(e,["tkhd"])[0];i&&(i=(n=new DataView(i.buffer,i.byteOffset,i.byteLength)).getUint8(0),t.id=0===i?n.getUint32(12):n.getUint32(20));var n=Mt(e,["mdia","hdlr"])[0];n&&(a=Ot(n.subarray(8,12)),t.type="vide"===a?"video":"soun"===a?"audio":a);var r,a=Mt(e,["mdia","minf","stbl","stsd"])[0];a&&(a=a.subarray(8),t.codec=Ot(a.subarray(4,8)),(a=Mt(a,[t.codec])[0])&&(/^[asm]vc[1-9]$/i.test(t.codec)?(r=a.subarray(78),"avcC"===Ot(r.subarray(4,8))&&11<r.length?(t.codec+=".",t.codec+=Xt(r[9]),t.codec+=Xt(r[10]),t.codec+=Xt(r[11])):t.codec="avc1.4d400d"):/^mp4[a,v]$/i.test(t.codec)?(r=a.subarray(28),"esds"===Ot(r.subarray(4,8))&&20<r.length&&0!==r[19]?(t.codec+="."+Xt(r[19]),t.codec+="."+Xt(r[20]>>>2&63).replace(/^0/,"")):t.codec="mp4a.40.2"):t.codec=t.codec.toLowerCase()));e=Mt(e,["mdia","mdhd"])[0];e&&(t.timescale=Yt(e)),s.push(t)}),s},Qt=ke,$t=q,Jt=Ie,Zt={};Zt.ts={parseType:function(e,t){e=xt(e);return 0===e?"pat":e===t?"pmt":t?"pes":null},parsePat:function(e){var t=At(e),i=4+Pt(e);return t&&(i+=e[i]+1),(31&e[i+10])<<8|e[i+11]},parsePmt:function(e){var t={},i=At(e),n=4+Pt(e);if(i&&(n+=e[n]+1),1&e[n+5]){for(var r=3+((15&e[n+1])<<8|e[n+2])-4,a=12+((15&e[n+10])<<8|e[n+11]);a<r;){var s=n+a;t[(31&e[s+1])<<8|e[s+2]]=e[s],a+=5+((15&e[s+3])<<8|e[s+4])}return t}},parsePayloadUnitStartIndicator:At,parsePesType:function(e,t){switch(t[xt(e)]){case je.H264_STREAM_TYPE:return"video";case je.ADTS_STREAM_TYPE:return"audio";case je.METADATA_STREAM_TYPE:return"timed-metadata";default:return null}},parsePesTime:function(e){if(!At(e))return null;var t=4+Pt(e);if(t>=e.byteLength)return null;var i=null,n=e[t+7];return 192&n&&((i={}).pts=(14&e[t+9])<<27|(255&e[t+10])<<20|(254&e[t+11])<<12|(255&e[t+12])<<5|(254&e[t+13])>>>3,i.pts*=4,i.pts+=(6&e[t+13])>>>1,i.dts=i.pts,64&n&&(i.dts=(14&e[t+14])<<27|(255&e[t+15])<<20|(254&e[t+16])<<12|(255&e[t+17])<<5|(254&e[t+18])>>>3,i.dts*=4,i.dts+=(6&e[t+18])>>>1)),i},videoPacketContainsKeyFrame:function(e){for(var t=4+Pt(e),i=e.subarray(t),n=0,r=0,a=!1;r<i.byteLength-3;r++)if(1===i[r+2]){n=r+5;break}for(;n<i.byteLength;)switch(i[n]){case 0:if(0!==i[n-1]){n+=2;break}if(0!==i[n-2]){n++;break}for(r+3!==n-2&&"slice_layer_without_partitioning_rbsp_idr"===Lt(31&i[r+3])&&(a=!0);1!==i[++n]&&n<i.length;);r=n-2,n+=3;break;case 1:if(0!==i[n-1]||0!==i[n-2]){n+=3;break}"slice_layer_without_partitioning_rbsp_idr"===Lt(31&i[r+3])&&(a=!0),r=n-2,n+=3;break;default:n+=3}return i=i.subarray(r),n-=r,r=0,a=i&&3<i.byteLength&&"slice_layer_without_partitioning_rbsp_idr"===Lt(31&i[r+3])?!0:a}},Zt.aac=dt;function ei(e,t,i){for(var n,r,a,s,o=0,u=188,l=!1;u<=e.byteLength;
4716)if(71!==e[o]||71!==e[u]&&u!==e.byteLength)o++,u++;else{if(n=e.subarray(o,u),"pes"===Zt.ts.parseType(n,t.pid)&&(r=Zt.ts.parsePesType(n,t.table),a=Zt.ts.parsePayloadUnitStartIndicator(n),"audio"===r&&a&&(s=Zt.ts.parsePesTime(n))&&(s.type="audio",i.audio.push(s),l=!0)),l)break;o+=188,u+=188}for(o=(u=e.byteLength)-188,l=!1;0<=o;)if(71!==e[o]||71!==e[u]&&u!==e.byteLength)o--,u--;else{if(n=e.subarray(o,u),"pes"===Zt.ts.parseType(n,t.pid)&&(r=Zt.ts.parsePesType(n,t.table),a=Zt.ts.parsePayloadUnitStartIndicator(n),"audio"===r&&a&&(s=Zt.ts.parsePesTime(n))&&(s.type="audio",i.audio.push(s),l=!0)),l)break;o-=188,u-=188}}function ti(e){var t,i={pid:null,table:null},n={};for(t in!function(e,t){for(var i,n=0,r=188;r<e.byteLength;)if(71!==e[n]||71!==e[r])n++,r++;else{switch(i=e.subarray(n,r),Zt.ts.parseType(i,t.pid)){case"pat":t.pid=Zt.ts.parsePat(i);break;case"pmt":var a=Zt.ts.parsePmt(i);t.table=t.table||{},Object.keys(a).forEach(function(e){t.table[e]=a[e]})}n+=188,r+=188}}(e,i),i.table)if(i.table.hasOwnProperty(t))switch(i.table[t]){case je.H264_STREAM_TYPE:n.video=[],function(e,t,i){for(var n,r,a,s,o,u,l,c,d=0,h=188,p=!1,f={data:[],size:0};h<e.byteLength;)if(71!==e[d]||71!==e[h])d++,h++;else{if(n=e.subarray(d,h),"pes"===Zt.ts.parseType(n,t.pid))if(r=Zt.ts.parsePesType(n,t.table),a=Zt.ts.parsePayloadUnitStartIndicator(n),"video"===r&&(a&&!p&&(s=Zt.ts.parsePesTime(n))&&(s.type="video",i.video.push(s),p=!0),!i.firstKeyFrame)){if(a&&0!==f.size){for(o=new Uint8Array(f.size),u=0;f.data.length;)l=f.data.shift(),o.set(l,u),u+=l.byteLength;!Zt.ts.videoPacketContainsKeyFrame(o)||(c=Zt.ts.parsePesTime(o))&&(i.firstKeyFrame=c,i.firstKeyFrame.type="video"),f.size=0}f.data.push(n),f.size+=n.byteLength}if(p&&i.firstKeyFrame)break;d+=188,h+=188}for(d=(h=e.byteLength)-188,p=!1;0<=d;)if(71!==e[d]||71!==e[h])d--,h--;else{if(n=e.subarray(d,h),"pes"===Zt.ts.parseType(n,t.pid)&&(r=Zt.ts.parsePesType(n,t.table),a=Zt.ts.parsePayloadUnitStartIndicator(n),"video"===r&&a&&(s=Zt.ts.parsePesTime(n))&&(s.type="video",i.video.push(s),p=!0)),p)break;d-=188,h-=188}}(e,i,n),0===n.video.length&&delete n.video;break;case je.ADTS_STREAM_TYPE:n.audio=[],ei(e,i,n),0===n.audio.length&&delete n.audio}return n}var ii=ue,ni=function(e,t){var i,n,r=(Zt.aac.isLikelyAacData(e)?function(e){for(var t,i=!1,n=0,r=null,a=null,s=0,o=0;3<=e.length-o;){switch(Zt.aac.parseType(e,o)){case"timed-metadata":if(e.length-o<10){i=!0;break}if((s=Zt.aac.parseId3TagSize(e,o))>e.length){i=!0;break}null===a&&(t=e.subarray(o,o+s),a=Zt.aac.parseAacTimestamp(t)),o+=s;break;case"audio":if(e.length-o<7){i=!0;break}if((s=Zt.aac.parseAdtsSize(e,o))>e.length){i=!0;break}null===r&&(t=e.subarray(o,o+s),r=Zt.aac.parseSampleRate(t)),n++,o+=s;break;default:o++}if(i)return null}if(null===r||null===a)return null;var u=ii/r;return{audio:[{type:"audio",dts:a,pts:a},{type:"audio",dts:a+1024*n*u,pts:a+1024*n*u}]}}:ti)(e);return r&&(r.audio||r.video)?(e=t,(t=r).audio&&t.audio.length&&("undefined"!=typeof(i=e)&&!isNaN(i)||(i=t.audio[0].dts),t.audio.forEach(function(e){e.dts=Jt(e.dts,i),e.pts=Jt(e.pts,i),e.dtsTime=e.dts/ii,e.ptsTime=e.pts/ii})),t.video&&t.video.length&&("undefined"!=typeof(n=e)&&!isNaN(n)||(n=t.video[0].dts),t.video.forEach(function(e){e.dts=Jt(e.dts,n),e.pts=Jt(e.pts,n),e.dtsTime=e.dts/ii,e.ptsTime=e.pts/ii}),t.firstKeyFrame&&((t=t.firstKeyFrame).dts=Jt(t.dts,n),t.pts=Jt(t.pts,n),t.dtsTime=t.dts/ii,t.ptsTime=t.pts/ii)),r):null},ri=function(){function e(e,t){this.options=t||{},this.self=e,this.init()}var t=e.prototype;return t.init=function(){var i,e;this.transmuxer&&this.transmuxer.dispose(),this.transmuxer=new Dt.Transmuxer(this.options),i=this.self,(e=this.transmuxer).on("data",function(e){var t=e.initSegment;e.initSegment={data:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength};t=e.data;e.data=t.buffer,i.postMessage({action:"data",segment:e,byteOffset:t.byteOffset,byteLength:t.byteLength},[e.data])}),e.on("done",function(e){i.postMessage({action:"done"})}),e.on("gopInfo",function(e){i.postMessage({action:"gopInfo",gopInfo:e})}),e.on("videoSegmentTimingInfo",function(e){var t={start:{decode:ce(e.start.dts),presentation:ce(e.start.pts)},end:{decode:ce(e.end.dts),presentation:ce(e.end.pts)},baseMediaDecodeTime:ce(e.baseMediaDecodeTime)};
vendor: 5,685 bytes, line 4716
4716e.prependedContentDuration&&(t.prependedContentDuration=ce(e.prependedContentDuration)),i.postMessage({action:"videoSegmentTimingInfo",videoSegmentTimingInfo:t})}),e.on("audioSegmentTimingInfo",function(e){var t={start:{decode:ce(e.start.dts),presentation:ce(e.start.pts)},end:{decode:ce(e.end.dts),presentation:ce(e.end.pts)},baseMediaDecodeTime:ce(e.baseMediaDecodeTime)};e.prependedContentDuration&&(t.prependedContentDuration=ce(e.prependedContentDuration)),i.postMessage({action:"audioSegmentTimingInfo",audioSegmentTimingInfo:t})}),e.on("id3Frame",function(e){i.postMessage({action:"id3Frame",id3Frame:e})}),e.on("caption",function(e){i.postMessage({action:"caption",caption:e})}),e.on("trackinfo",function(e){i.postMessage({action:"trackinfo",trackInfo:e})}),e.on("audioTimingInfo",function(e){i.postMessage({action:"audioTimingInfo",audioTimingInfo:{start:ce(e.start),end:ce(e.end)}})}),e.on("videoTimingInfo",function(e){i.postMessage({action:"videoTimingInfo",videoTimingInfo:{start:ce(e.start),end:ce(e.end)}})}),e.on("log",function(e){i.postMessage({action:"log",log:e})})},t.pushMp4Captions=function(e){this.captionParser||(this.captionParser=new Gt,this.captionParser.init());var t=new Uint8Array(e.data,e.byteOffset,e.byteLength),e=this.captionParser.parse(t,e.trackIds,e.timescales);this.self.postMessage({action:"mp4Captions",captions:e&&e.captions||[],logs:e&&e.logs||[],data:t.buffer},[t.buffer])},t.probeMp4StartTime=function(e){var t=e.timescales,e=e.data,t=Qt(t,e);this.self.postMessage({action:"probeMp4StartTime",startTime:t,data:e},[e.buffer])},t.probeMp4Tracks=function(e){var t=e.data,e=$t(t);this.self.postMessage({action:"probeMp4Tracks",tracks:e,data:t},[t.buffer])},t.probeTs=function(e){var t=e.data,i=e.baseStartTime,e="number"!=typeof i||isNaN(i)?void 0:i*ue,i=ni(t,e),e=null;i&&((e={hasVideo:i.video&&2===i.video.length||!1,hasAudio:i.audio&&2===i.audio.length||!1}).hasVideo&&(e.videoStart=i.video[0].ptsTime),e.hasAudio&&(e.audioStart=i.audio[0].ptsTime)),this.self.postMessage({action:"probeTs",result:e,data:t},[t.buffer])},t.clearAllMp4Captions=function(){this.captionParser&&this.captionParser.clearAllCaptions()},t.clearParsedMp4Captions=function(){this.captionParser&&this.captionParser.clearParsedCaptions()},t.push=function(e){e=new Uint8Array(e.data,e.byteOffset,e.byteLength);this.transmuxer.push(e)},t.reset=function(){this.transmuxer.reset()},t.setTimestampOffset=function(e){e=e.timestampOffset||0;this.transmuxer.setBaseMediaDecodeTime(Math.round(le(e)))},t.setAudioAppendStart=function(e){this.transmuxer.setAudioAppendStart(Math.ceil(le(e.appendStart)))},t.setRemux=function(e){this.transmuxer.setRemux(e.remux)},t.flush=function(e){this.transmuxer.flush(),self.postMessage({action:"done",type:"transmuxed"})},t.endTimeline=function(){this.transmuxer.endTimeline(),self.postMessage({action:"endedtimeline",type:"transmuxed"})},t.alignGopsWith=function(e){this.transmuxer.alignGopsWith(e.gopsToAlignWith.slice())},e}();self.onmessage=function(e){"init"===e.data.action&&e.data.options?this.messageHandlers=new ri(self,e.data.options):(this.messageHandlers||(this.messageHandlers=new ri(self)),e.data&&e.data.action&&"init"!==e.data.action&&this.messageHandlers[e.data.action]&&this.messageHandlers[e.data.action](e.data))}}))),El=function(e){e.currentTransmux=null,e.transmuxQueue.length&&(e.currentTransmux=e.transmuxQueue.shift(),"function"==typeof e.currentTransmux?e.currentTransmux():Pu(e.currentTransmux))},kl=function(e){Du("reset",e)},Cl=function(e){var t=new wl;t.currentTransmux=null,t.transmuxQueue=[];var i=t.terminate;return t.terminate=function(){return t.currentTransmux=null,t.transmuxQueue.length=0,i.call(t)},t.postMessage({action:"init",options:e}),t},Il=2,xl=-101,Al=-102,Pl=Oo("CodecUtils"),Ll=Oo("PlaylistSelector"),ar=function(){var e=this.useDevicePixelRatio&&window.devicePixelRatio||1;return el(this.playlists.master,this.systemBandwidth,parseInt($u(this.tech_.el(),"width"),10)*e,parseInt($u(this.tech_.el(),"height"),10)*e,this.limitRenditionByPlayerDimensions,this.masterPlaylistController_)},Dl=function(n){function e(e,t){var i=n.call(this)||this;if(!e)throw new TypeError("Initialization settings are required");if("function"!=typeof e.currentTime)throw new TypeError("No currentTime getter specified");if(!e.mediaSource)throw new TypeError("No MediaSource specified");return i.bandwidth=e.bandwidth,i.throughput={rate:0,count:0},i.roundTrip=NaN,i.resetStats_(),i.mediaIndex=null,i.partIndex=null,i.hasPlayed_=e.hasPlayed,i.currentTime_=e.currentTime,i.seekable_=e.seekable,i.seeking_=e.seeking,i.duration_=e.duration,i.mediaSource_=e.mediaSource,i.vhs_=e.vhs,i.loaderType_=e.loaderType,i.currentMediaInfo_=void 0,i.startingMediaInfo_=void 0,i.segmentMetadataTrack_=e.segmentMetadataTrack,i.goalBufferLength_=e.goalBufferLength,i.sourceType_=e.sourceType,i.sourceUpdater_=e.sourceUpdater,i.inbandTextTracks_=e.inbandTextTracks,i.state_="INIT",i.timelineChangeController_=e.timelineChangeController,i.shouldSaveSegmentTimingInfo_=!0,i.parse708captions_=e.parse708captions,i.captionServices_=e.captionServices,i.experimentalExactManifestTimings=e.experimentalExactManifestTimings,i.checkBufferTimeout_=null,i.error_=void 0,i.currentTimeline_=-1,i.pendingSegment_=null,i.xhrOptions_=null,i.pendingSegments_=[],i.audioDisabled_=!1,i.isPendingTimestampOffset_=!1,i.gopBuffer_=[],i.timeMapping_=0,i.safeAppend_=11<=tr.browser.IE_VERSION,i.appendInitSegment_={audio:!0,video:!0},i.playlistOfLastInitSegment_={audio:null,video:null},i.callQueue_=[],i.loadQueue_=[],i.metadataQueue_={id3:[],caption:[]},i.waitingOnRemove_=!1,i.quotaExceededErrorRetryTimeout_=null,i.activeInitSegmentId_=null,i.initSegments_={}
vendor: 4,729 bytes, line 4716
4716,i.cacheEncryptionKeys_=e.cacheEncryptionKeys,i.keyCache_={},i.decrypter_=e.decrypter,i.syncController_=e.syncController,i.syncPoint_={segmentIndex:0,time:0},i.transmuxer_=i.createTransmuxer_(),i.triggerSyncInfoUpdate_=function(){return i.trigger("syncinfoupdate")},i.syncController_.on("syncinfoupdate",i.triggerSyncInfoUpdate_),i.mediaSource_.addEventListener("sourceopen",function(){i.isEndOfStream_()||(i.ended_=!1)}),i.fetchAtBuffer_=!1,i.logger_=Oo("SegmentLoader["+i.loaderType_+"]"),Object.defineProperty(ft(i),"state",{get:function(){return this.state_},set:function(e){e!==this.state_&&(this.logger_(this.state_+" -> "+e),this.state_=e,this.trigger("statechange"))}}),i.sourceUpdater_.on("ready",function(){i.hasEnoughInfoToAppend_()&&i.processCallQueue_()}),"main"===i.loaderType_&&i.timelineChangeController_.on("pendingtimelinechange",function(){i.hasEnoughInfoToAppend_()&&i.processCallQueue_()}),"audio"===i.loaderType_&&i.timelineChangeController_.on("timelinechange",function(){i.hasEnoughInfoToLoad_()&&i.processLoadQueue_(),i.hasEnoughInfoToAppend_()&&i.processCallQueue_()}),i}mt(e,n);var t=e.prototype;return t.createTransmuxer_=function(){return Cl({remux:!1,alignGopsAtEnd:this.safeAppend_,keepOriginalTimestamps:!0,parse708captions:this.parse708captions_,captionServices:this.captionServices_})},t.resetStats_=function(){this.mediaBytesTransferred=0,this.mediaRequests=0,this.mediaRequestsAborted=0,this.mediaRequestsTimedout=0,this.mediaRequestsErrored=0,this.mediaTransferDuration=0,this.mediaSecondsLoaded=0,this.mediaAppends=0},t.dispose=function(){this.trigger("dispose"),this.state="DISPOSED",this.pause(),this.abort_(),this.transmuxer_&&this.transmuxer_.terminate(),this.resetStats_(),this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.syncController_&&this.triggerSyncInfoUpdate_&&this.syncController_.off("syncinfoupdate",this.triggerSyncInfoUpdate_),this.off()},t.setAudio=function(e){this.audioDisabled_=!e,e?this.appendInitSegment_.audio=!0:this.sourceUpdater_.removeAudio(0,this.duration_())},t.abort=function(){"WAITING"===this.state?(this.abort_(),this.state="READY",this.paused()||this.monitorBuffer_()):this.pendingSegment_&&(this.pendingSegment_=null)},t.abort_=function(){this.pendingSegment_&&this.pendingSegment_.abortRequests&&this.pendingSegment_.abortRequests(),this.pendingSegment_=null,this.callQueue_=[],this.loadQueue_=[],this.metadataQueue_.id3=[],this.metadataQueue_.caption=[],this.timelineChangeController_.clearPendingTimelineChange(this.loaderType_),this.waitingOnRemove_=!1,window.clearTimeout(this.quotaExceededErrorRetryTimeout_),this.quotaExceededErrorRetryTimeout_=null},t.checkForAbort_=function(e){return"APPENDING"!==this.state||this.pendingSegment_?!this.pendingSegment_||this.pendingSegment_.requestId!==e:(this.state="READY",!0)},t.error=function(e){return"undefined"!=typeof e&&(this.logger_("error occurred:",e),this.error_=e),this.pendingSegment_=null,this.error_},t.endOfStream=function(){this.ended_=!0,this.transmuxer_&&kl(this.transmuxer_),this.gopBuffer_.length=0,this.pause(),this.trigger("ended")},t.buffered_=function(){var e=this.getMediaInfo_();if(!this.sourceUpdater_||!e)return tr.createTimeRanges();if("main"===this.loaderType_){var t=e.hasAudio,i=e.hasVideo,e=e.isMuxed;if(i&&t&&!this.audioDisabled_&&!e)return this.sourceUpdater_.buffered();if(i)return this.sourceUpdater_.videoBuffered()}return this.sourceUpdater_.audioBuffered()},t.initSegmentForMap=function(e,t){if(void 0===t&&(t=!1),!e)return null;var i=bu(e),n=this.initSegments_[i];return t&&!n&&e.bytes&&(this.initSegments_[i]=n={resolvedUri:e.resolvedUri,byterange:e.byterange,bytes:e.bytes,tracks:e.tracks,timescales:e.timescales}),n||e},t.segmentKey=function(e,t){if(void 0===t&&(t=!1),!e)return null;var i=Tu(e),n=this.keyCache_[i];this.cacheEncryptionKeys_&&t&&!n&&e.bytes&&(this.keyCache_[i]=n={resolvedUri:e.resolvedUri,bytes:e.bytes});e={resolvedUri:(n||e).resolvedUri};return n&&(e.bytes=n.bytes),e},t.couldBeginLoading_=function(){return this.playlist_&&!this.paused()},t.load=function(){if(this.monitorBuffer_(),this.playlist_)return"INIT"===this.state&&this.couldBeginLoading_()?this.init_():void(!this.couldBeginLoading_()||"READY"!==this.state&&"INIT"!==this.state||(this.state="READY"))},t.init_=function(){return this.state="READY",this.resetEverything(),this.monitorBuffer_()},t.playlist=function(e,t){if(void 0===t&&(t={}),e){var i=this.playlist_,n=this.pendingSegment_;this.playlist_=e,this.xhrOptions_=t,"INIT"===this.state&&(e.syncInfo={mediaSequence:e.mediaSequence,time:0},"main"===this.loaderType_&&this.syncController_.setDateTimeMappingForStart(e));var r=null;if(i&&(i.id?r=i.id:i.uri&&(r=i.uri)),this.logger_("playlist update ["+r
4716+" => "+(e.id||e.uri)+"]"),this.trigger("syncinfoupdate"),"INIT"===this.state&&this.couldBeginLoading_())return this.init_();if(!i||i.uri!==e.uri)return null!==this.mediaIndex&&(e.endList?this.resyncLoader():this.resetLoader()),this.currentMediaInfo_=void 0,void this.trigger("playlistupdate");t=e.mediaSequence-i.mediaSequence;this.logger_("live window shift ["+t+"]"),null!==this.mediaIndex&&(this.mediaIndex-=t,this.mediaIndex<0?(this.mediaIndex=null,this.partIndex=null):(r=this.playlist_.segments[this.mediaIndex],!this.partIndex||r.parts&&r.parts.length&&r.parts[this.partIndex]||(r=this.mediaIndex,this.logger_("currently processing part (index "+this.partIndex+") no longer exists."),this.resetLoader(),this.mediaIndex=r))),n&&(n.mediaIndex-=t,n.mediaIndex<0?(n.mediaIndex=null,n.partIndex=null):(0<=n.mediaIndex&&(n.segment=e.segments[n.mediaIndex]),0<=n.partIndex&&n.segment.parts&&(n.part=n.segment.parts[n.partIndex]))),this.syncController_.saveExpiredSegmentInfo(i,e)}},t.pause=function(){this.checkBufferTimeout_&&(window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=null)},t.paused=function(){return null===this.checkBufferTimeout_},t.resetEverything=function(e){this.ended_=!1,this.appendInitSegment_={audio:!0,video:!0},this.resetLoader(),this.remove(0,1/0,e),this.transmuxer_&&(this.transmuxer_.postMessage({action:"clearAllMp4Captions"}),this.transmuxer_.postMessage({action:"reset"}))},t.resetLoader=function(){this.fetchAtBuffer_=!1,this.resyncLoader()},t.resyncLoader=function(){this.transmuxer_&&kl(this.transmuxer_),this.mediaIndex=null,this.partIndex=null,this.syncPoint_=null,this.isPendingTimestampOffset_=!1,this.callQueue_=[],this.loadQueue_=[],this.metadataQueue_.id3=[],this.metadataQueue_.caption=[],this.abort(),this.transmuxer_&&this.transmuxer_.postMessage({action:"clearParsedMp4Captions"})},t.remove=function(e,t,i,n){if(void 0===i&&(i=function(){}),void 0===n&&(n=!1),(t=t===1/0?this.duration_():t)<=e)this.logger_("skipping remove because end ${end} is <= start ${start}");else if(this.sourceUpdater_&&this.getMediaInfo_()){var r,a=1,s=function(){0===--a&&i()};for(r in!n&&this.audioDisabled_||(a++,this.sourceUpdater_.removeAudio(e,t,s)),!n&&"main"!==this.loaderType_||(this.gopBuffer_=function(e,t,i,n){for(var r=Math.ceil((t-n)*cl),a=Math.ceil((i-n)*cl),n=e.slice(),s=e.length;s--&&!(e[s].pts<=a););if(-1===s)return n;for(var o=s+1;o--&&!(e[o].pts<=r););return o=Math.max(o,0),n.splice(o,s-o+1),n}(this.gopBuffer_,e,t,this.timeMapping_),a++,this.sourceUpdater_.removeVideo(e,t,s)),this.inbandTextTracks_)il(e,t,this.inbandTextTracks_[r]);il(e,t,this.segmentMetadataTrack_),s()}else this.logger_("skipping remove because no source updater or starting media info")},t.monitorBuffer_=function(){this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=window.setTimeout(this.monitorBufferTick_.bind(this),1)},t.monitorBufferTick_=function(){"READY"===this.state&&this.fillBuffer_(),this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=window.setTimeout(this.monitorBufferTick_.bind(this),500)},t.fillBuffer_=function(){var e;
4716this.sourceUpdater_.updating()||(e=this.chooseNextRequest_())&&("number"==typeof e.timestampOffset&&(this.isPendingTimestampOffset_=!1,this.timelineChangeController_.pendingTimelineChange({type:this.loaderType_,from:this.currentTimeline_,to:e.timeline})),this.loadSegment_(e))},t.isEndOfStream_=function(e,t,i){if(void 0===e&&(e=this.mediaIndex),void 0===t&&(t=this.playlist_),void 0===i&&(i=this.partIndex),!t||!this.mediaSource_)return!1;var n="number"==typeof e&&t.segments[e],e=e+1===t.segments.length,n=!n||!n.parts||i+1===n.parts.length;return t.endList&&"open"===this.mediaSource_.readyState&&e&&n},t.chooseNextRequest_=function(){var e=this.buffered_(),t=Fo(e)||0,i=jo(e,this.currentTime_()),n=!this.hasPlayed_()&&1<=i,r=i>=this.goalBufferLength_(),e=this.playlist_.segments;if(!e.length||n||r)return null;this.syncPoint_=this.syncPoint_||this.syncController_.getSyncPoint(this.playlist_,this.duration_(),this.currentTimeline_,this.currentTime_());var a,n={partIndex:null,mediaIndex:null,startOfSegment:null,playlist:this.playlist_,isSyncRequest:Boolean(!this.syncPoint_)};n.isSyncRequest?n.mediaIndex=function(e,t,i){t=t||[];for(var n=[],r=0,a=0;a<t.length;a++){var s=t[a];if(e===s.timeline&&(n.push(a),i<(r+=s.duration)))return a}return 0===n.length?0:n[n.length-1]}(this.currentTimeline_,e,t):null!==this.mediaIndex?(r=e[this.mediaIndex],a="number"==typeof this.partIndex?this.partIndex:-1,n.startOfSegment=r.end||t,r.parts&&r.parts[a+1]?(n.mediaIndex=this.mediaIndex,n.partIndex=a+1):n.mediaIndex=this.mediaIndex+1):(a=(o=fl.getMediaInfoForTime({experimentalExactManifestTimings:this.experimentalExactManifestTimings,playlist:this.playlist_,currentTime:this.fetchAtBuffer_?t:this.currentTime_(),startingPartIndex:this.syncPoint_.partIndex,startingSegmentIndex:this.syncPoint_.segmentIndex,startTime:this.syncPoint_.time})).segmentIndex,s=o.startTime,o=o.partIndex,n.getMediaInfoForTime=this.fetchAtBuffer_?"bufferedEnd "+t:"currentTime "+this.currentTime_(),n.mediaIndex=a,n.startOfSegment=s,n.partIndex=o);var s=e[n.mediaIndex],o=s&&"number"==typeof n.partIndex&&s.parts&&s.parts[n.partIndex];if(!s||"number"==typeof n.partIndex&&!o)return null;"number"!=typeof n.partIndex&&s.parts&&(n.partIndex=0,o=s.parts[0]),i||!o||o.independent||(0===n.partIndex?(o=(i=e[n.mediaIndex-1]).parts&&i.parts.length&&i.parts[i.parts.length-1])&&o.independent&&(--n.mediaIndex,n.partIndex=i.parts.length-1,n.independent="previous segment"):s.parts[n.partIndex-1].independent&&(--n.partIndex,n.independent="previous part"));s=this.mediaSource_&&"ended"===this.mediaSource_.readyState;return n.mediaIndex>=e.length-1&&s&&!this.seeking_()?null:this.generateSegmentInfo_(n)},t.generateSegmentInfo_=function(e){var t=e.independent,i=e.playlist,n=e.mediaIndex,r=e.startOfSegment,a=e.isSyncRequest,s=e.partIndex,o=e.forceTimestampOffset,u=e.getMediaInfoForTime,l=i.segments[n],e="number"==typeof s&&l.parts[s],t={requestId:"segment-loader-"+Math.random(),uri:e&&e.resolvedUri||l.resolvedUri,mediaIndex:n,partIndex:e?s:null,isSyncRequest:a,startOfSegment:r,playlist:i,bytes:null,encryptedBytes:null,timestampOffset:null,timeline:l.timeline,duration:e&&e.duration||l.duration,segment:l,part:e,byteLength:0,transmuxer:this.transmuxer_,getMediaInfoForTime:u,independent:t},o="undefined"!=typeof o?o:this.isPendingTimestampOffset_;t.timestampOffset=this.timestampOffsetForSegment_({segmentTimeline:l.timeline,currentTimeline:this.currentTimeline_,startOfSegment:r,buffered:this.buffered_(),overrideCheck:o});o=Fo(this.sourceUpdater_.audioBuffered());return"number"==typeof o&&(t.audioAppendStart=o-this.sourceUpdater_.audioTimestampOffset()),this.sourceUpdater_.videoBuffered().length&&(t.gopsToAlignWith=function(e,t,i){if("undefined"==typeof t||null===t||!e.length)return[];for(var n=Math.ceil((t-i+3)*cl),r=0;r<e.length&&!(e[r].pts>n);r++);return e.slice(r)}(this.gopBuffer_,this.currentTime_()-this.sourceUpdater_.videoTimestampOffset(),this.timeMapping_)),t},t.timestampOffsetForSegment_=function(e){return i=(t=e).segmentTimeline,n=t.currentTimeline,r=t.startOfSegment,e=t.buffered,t.overrideCheck||i!==n?!(i<n)&&e.length?e.end(e.length-1):r:null;var t,i,n,r},t.earlyAbortWhenNeeded_=function(e){var t,i,n,r,a,s,o,u,l,c,d,h,p;!this.vhs_.tech_.paused()&&this.xhrOptions_.timeout&&this.playlist_.attributes.BANDWIDTH&&(Date.now()-(e.firstBytesReceivedAt||Date.now())<1e3||(t=this.currentTime_(),r=e.bandwidth,a=this.pendingSegment_.duration,p=fl.estimateSegmentRequestTime(a,r,this.playlist_,e.bytesReceived),i=this.buffered_(),n=t,void 0===(e=this.vhs_.tech_.playbackRate())&&
4716(e=1),p<=(e=((i.length?i.end(i.length-1):0)-n)/e-1)||(r={master:this.vhs_.playlists.master,currentTime:t,bandwidth:r,duration:this.duration_(),segmentDuration:a,timeUntilRebuffer:e,currentTimeline:this.currentTimeline_,syncController:this.syncController_},a=r.master,s=r.currentTime,o=r.bandwidth,u=r.duration,l=r.segmentDuration,c=r.timeUntilRebuffer,d=r.currentTimeline,h=r.syncController,a=(r=(a=!(a=(r=a.playlists.filter(function(e){return!fl.isIncompatible(e)})).filter(fl.isEnabled)).length?r.filter(function(e){return!fl.isDisabled(e)}):a).filter(fl.hasAttribute.bind(null,"BANDWIDTH")).map(function(e){var t=h.getSyncPoint(e,u,d,s)?1:2;return{playlist:e,rebufferingImpact:fl.estimateSegmentRequestTime(l,o,e)*t-c}})).filter(function(e){return e.rebufferingImpact<=0}),Ju(a,function(e,t){return Zu(t.playlist,e.playlist)}),(r=a.length?a[0]:(Ju(r,function(e,t){return e.rebufferingImpact-t.rebufferingImpact}),r[0]||null))&&(p=p-e-r.rebufferingImpact,!r.playlist||r.playlist.uri===this.playlist_.uri||p<(e<=hl?1:.5)||(this.bandwidth=r.playlist.attributes.BANDWIDTH*Sl.BANDWIDTH_VARIANCE+1,this.trigger("earlyabort"))))))},t.handleAbort_=function(e){this.logger_("Aborting "+rl(e)),this.mediaRequestsAborted+=1},t.handleProgress_=function(e,t){this.earlyAbortWhenNeeded_(t.stats),this.checkForAbort_(t.requestId)||this.trigger("progress")},t.handleTrackInfo_=function(e,t){this.earlyAbortWhenNeeded_(e.stats),this.checkForAbort_(e.requestId)||this.checkForIllegalMediaSwitch(t)||(function(e,t){if(!e&&!t||!e&&t||e&&!t)return!1;if(e===t)return!0;var i=Object.keys(e).sort(),n=Object.keys(t).sort();if(i.length!==n.length)return!1;for(var r=0;r<i.length;r++){var a=i[r];if(a!==n[r])return!1;if(e[a]!==t[a])return!1}return!0}(this.currentMediaInfo_,t=t||{})||(this.appendInitSegment_={audio:!0,video:!0},this.startingMediaInfo_=t,this.currentMediaInfo_=t,this.logger_("trackinfo update",t),this.trigger("trackinfo")),this.checkForAbort_(e.requestId)||(this.pendingSegment_.trackInfo=t,this.hasEnoughInfoToAppend_()&&this.processCallQueue_()))},t.handleTimingInfo_=function(e,t,i,n){var r;this.earlyAbortWhenNeeded_(e.stats),this.checkForAbort_(e.requestId)||((r=this.pendingSegment_)[e=al(t)]=r[e]||{},r[e][i]=n,this.logger_("timinginfo: "+t+" - "+i+" - "+n),this.hasEnoughInfoToAppend_()&&this.processCallQueue_())},t.handleCaptions_=function(e,t){var g,y,v=this;this.earlyAbortWhenNeeded_(e.stats),this.checkForAbort_(e.requestId)||(0!==t.length?this.pendingSegment_.hasAppendedData_?(g=null===this.sourceUpdater_.videoTimestampOffset()?this.sourceUpdater_.audioTimestampOffset():this.sourceUpdater_.videoTimestampOffset(),y={},t.forEach(function(e){y[e.stream]=y[e.stream]||{startTime:1/0,captions:[],endTime:0};var t=y[e.stream];t.startTime=Math.min(t.startTime,e.startTime+g),t.endTime=Math.max(t.endTime,e.endTime+g),t.captions.push(e)}),Object.keys(y).forEach(function(e){var t,i,n,r,a,s,o,u,l,c,d=y[e],h=d.startTime,p=d.endTime,f=d.captions,m=v.inbandTextTracks_;v.logger_("adding cues from "+h+" -> "+p+" for "+e),t=m,i=v.vhs_.tech_,t[n=e]||(i.trigger({type:"usage",name:"vhs-608"}),i.trigger({type:"usage",name:"hls-608"}),/^cc708_/.test(r=n)&&(r="SERVICE"+n.split("_")[1]),(o=i.textTracks().getTrackById(r))?t[n]=o:(s=a=n,d=!1,(o=(i.options_.vhs&&i.options_.vhs.captionServices||{})[r])&&(a=o.label,s=o.language,d=o.default),t[n]=i.addRemoteTextTrack({kind:"captions",id:r,default:d,label:a,language:s},!1).track)),il(h,p,m[e]),l=(f={captionArray:f,inbandTextTracks:m,timestampOffset:g}).inbandTextTracks,m=f.captionArray,c=f.timestampOffset,m&&(u=window.WebKitDataCue||window.VTTCue,m.forEach(function(e){var t=e.stream;l[t].addCue(new u(e.startTime+c,e.endTime+c,e.text))}))}),this.transmuxer_&&this.transmuxer_.postMessage({action:"clearParsedMp4Captions"})):this.metadataQueue_.caption.push(this.handleCaptions_.bind(this,e,t)):this.logger_("SegmentLoader received no captions from a caption event"))},t.handleId3_=function(e,t,i){var n,r,a,s;this.earlyAbortWhenNeeded_(e.stats),this.checkForAbort_(e.requestId)||(this.pendingSegment_.hasAppendedData_?(n=null===this.sourceUpdater_.videoTimestampOffset()?this.sourceUpdater_.audioTimestampOffset():this.sourceUpdater_.videoTimestampOffset(),r=this.inbandTextTracks_,a=i,s=this.vhs_.tech_,r.metadataTrack_||(r.metadataTrack_=s.addRemoteTextTrack({kind:"metadata",label:"Timed Metadata"},!1).track,r.metadataTrack_.inBandMetadataTrackDispatchType=a),tl({inbandTextTracks:this.inbandTextTracks_,metadataArray:t,timestampOffset:n,videoDuration:this.duration_()})):this.metadataQueue_.id3.push(this.handleId3_.bind(this,e,t,i)))},t.processMetadataQueue_=function(){this.metadataQueue_.id3.forEach(function(e){return e()}),this.metadataQueue_.caption.forEach(function(e){return e()}),this.metadataQueue_.id3=[],this.metadataQueue_.caption=[]},t.processCallQueue_=function(){var e=this.callQueue_;this.callQueue_=[],e.forEach(function(e){return e()})},t.processLoadQueue_=function(){var e=this.loadQueue_;this.loadQueue_=[],e.forEach(function(e){return e()})},t.hasEnoughInfoToLoad_=function(){if("audio"!==this.loaderType_)return!0;var e=this.pendingSegment_;return!!e&&(!this.getCurrentMediaInfo_()||!sl({timelineChangeController:this.timelineChangeController_,currentTimeline:this.currentTimeline_,segmentTimeline:e.timeline,loaderType:this.loaderType_,audioDisabled:this.audioDisabled_}))},t.getCurrentMediaInfo_=function(e){return(e=void 0===e?this.pendingSegment_:e)&&e.trackInfo||this.currentMediaInfo_},t.getMediaInfo_=function(e){return void 0===e&&(e=this.pendingSegment_),this.getCurrentMediaInfo_(e)||this.startingMediaInfo_},t.hasEnoughInfoToAppend_=function(){if(!this.sourceUpdater_.ready())return!1;if(this.waitingOnRemove_||this.quotaExceededErrorRetryTimeout_)return!1;var e=this.pendingSegment_,t=this.getCurrentMediaInfo_();if(!e||!t)return!1;var i=t.hasAudio,n=t.hasVideo,t=t.isMuxed;return!(n&&!e.videoTimingInfo)&&(!(i&&!this.audioDisabled_&&!t&&!e.audioTimingInfo)&&!sl({timelineChangeController:this.timelineChangeController_,currentTimeline:this.currentTimeline_,segmentTimeline:e.timeline,loaderType:this.loaderType_,audioDisabled:this.audioDisabled_}))},t.handleData_=function(e,t){if(this.earlyAbortWhenNeeded_(e.stats),!this.checkForAbort_(e.requestId))if(!this.callQueue_.length&&this.hasEnoughInfoToAppend_()){var i,n=this.pendingSegment_;if(this.setTimeMapping_(n.timeline),this.updateMediaSecondsLoaded_(n.part||n.segment),"closed"!==this.mediaSource_.readyState){if(e.map&&(e.map=this.initSegmentForMap(e.map,!0),n.segment.map=e.map),e.key&&this.segmentKey(e.ke
4716y,!0),n.isFmp4=e.isFmp4,n.timingInfo=n.timingInfo||{},n.isFmp4?(this.trigger("fmp4"),n.timingInfo.start=n[al(t.type)].start):(i=this.getCurrentMediaInfo_(),(i="main"===this.loaderType_&&i&&i.hasVideo)&&(r=n.videoTimingInfo.start),n.timingInfo.start=this.trueSegmentStart_({currentStart:n.timingInfo.start,playlist:n.playlist,mediaIndex:n.mediaIndex,currentVideoTimestampOffset:this.sourceUpdater_.videoTimestampOffset(),useVideoTimingInfo:i,firstVideoFrameTimeForData:r,videoTimingInfo:n.videoTimingInfo,audioTimingInfo:n.audioTimingInfo})),this.updateAppendInitSegmentStatus(n,t.type),this.updateSourceBufferTimestampOffset_(n),n.isSyncRequest){this.updateTimingInfoEnd_(n),this.syncController_.saveSegmentTimingInfo({segmentInfo:n,shouldSaveTimelineMapping:"main"===this.loaderType_});var r=this.chooseNextRequest_();if(r.mediaIndex!==n.mediaIndex||r.partIndex!==n.partIndex)return void this.logger_("sync segment was incorrect, not appending");this.logger_("sync segment was correct, appending")}n.hasAppendedData_=!0,this.processMetadataQueue_(),this.appendData_(n,t)}}else this.callQueue_.push(this.handleData_.bind(this,e,t))},t.updateAppendInitSegmentStatus=function(e,t){"main"!==this.loaderType_||"number"!=typeof e.timestampOffset||e.changedTimestampOffset||(this.appendInitSegment_={audio:!0,video:!0}),this.playlistOfLastInitSegment_[t]!==e.playlist&&(this.appendInitSegment_[t]=!0)},t.getInitSegmentAndUpdateState_=function(e){var t=e.type,i=e.initSegment,n=e.map,r=e.playlist;if(n){e=bu(n);if(this.activeInitSegmentId_===e)return null;i=this.initSegmentForMap(n,!0).bytes,this.activeInitSegmentId_=e}return i&&this.appendInitSegment_[t]?(this.playlistOfLastInitSegment_[t]=r,this.appendInitSegment_[t]=!1,this.activeInitSegmentId_=null,i):null},t.handleQuotaExceededError_=function(e,t){var i=this,n=e.segmentInfo,r=e.type,a=e.bytes,s=this.sourceUpdater_.audioBuffered(),o=this.sourceUpdater_.videoBuffered();1<s.length&&this.logger_("On QUOTA_EXCEEDED_ERR, found gaps in the audio buffer: "+Bo(s).join(", ")),1<o.length&&this.logger_("On QUOTA_EXCEEDED_ERR, found gaps in the video buffer: "+Bo(o).join(", "));var u=s.length?s.start(0):0,l=s.length?s.end(s.length-1):0,c=o.length?o.start(0):0,e=o.length?o.end(o.length-1):0;if(l-u<=1&&e-c<=1)return this.logger_("On QUOTA_EXCEEDED_ERR, single segment too large to append to buffer, triggering an error. Appended byte length: "+a.byteLength+", audio buffer: "+Bo(s).join(", ")+", video buffer: "+Bo(o).join(", ")+", "),this.error({message:"Quota exceeded error with append of a single segment of content",excludeUntil:1/0}),void this.trigger("error");this.waitingOnRemove_=!0,this.callQueue_.push(this.appendToSourceBuffer_.bind(this,{segmentInfo:n,type:r,bytes:a}));a=this.currentTime_()-1;this.logger_("On QUOTA_EXCEEDED_ERR, removing audio/video from 0 to "+a),this.remove(0,a,function(){i.logger_("On QUOTA_EXCEEDED_ERR, retrying append in 1s"),i.waitingOnRemove_=!1,i.quotaExceededErrorRetryTimeout_=window.setTimeout(function(){i.logger_("On QUOTA_EXCEEDED_ERR, re-processing call queue"),i.quotaExceededErrorRetryTimeout_=null,i.processCallQueue_()},1e3)},!0)},t.handleAppendError_=function(e,t){var i=e.segmentInfo,n=e.type,e=e.bytes;t&&(22!==t.code?(this.logger_("Received non QUOTA_EXCEEDED_ERR on append",t),this.error(n+" append of "+e.length+"b failed for segment #"+i.mediaIndex+" in playlist "+i.playlist.id),this.trigger("appenderror")):this.handleQuotaExceededError_({segmentInfo:i,type:n,bytes:e}))},t.appendToSourceBuffer_=function(e){var t,i,n=e.segmentInfo,r=e.type,a=e.initSegment,s=e.data,o=e.bytes;o||(e=[s],s=s.byteLength,a&&(e.unshift(a),s+=a.byteLength),i=0,(e={bytes:s,segments:e}).bytes&&(t=new Uint8Array(e.bytes),e.segments.forEach(function(e){t.set(e,i),i+=e.byteLength})),o=t),this.sourceUpdater_.appendBuffer({segmentInfo:n,type:r,bytes:o},this.handleAppendError_.bind(this,{segmentInfo:n,type:r,bytes:o}))},t.handleSegmentTimingInfo_=function(e,t,i){this.pendingSegment_&&t===this.pendingSegment_.requestId&&((t=this.pendingSegment_.segment)[e=e+"TimingInfo"]||(t[e]={}),t[e].transmuxerPrependedSeconds=i.prependedContentDuration||0,t[e].transmuxedPresentationStart=i.start.presentation,t[e].transmuxedDecodeStart=i.start.decode,t[e].transmuxedPresentationEnd=i.end.presentation,t[e].transmuxedDecodeEnd=i.end.decode,t[e].baseMediaDecodeTime=i.baseMediaDecodeTime)},t.appendData_=function(e,t){var i=t.type,n=t.data;n&&n.byteLength&&("audio"===i&&this.audioDisabled_||(t=this.getInitSegmentAndUpdateState_({type:i,initSegment:t.initSegment,playlist:e.playlist,map:e.isFmp4?e.segment.map:null}),this.appendToSourceBuffer_({segmentInfo:e,type:i,initSegment:t,data:n})))},t.loadSegment_=function(t){var i=this;this.state="WAITING",this.pendingSegment_=t,this.trimBackBuffer_(t),"number"==typeof t.timestampOffset&&this.transmuxer_&&this.transmuxer_.postMessage({action:"clearAllMp4Captions"}),this.hasEnoughInfoToLoad_()?this.updateTransmuxerAndRequestSegment_(t):this.loadQueue_.push(function(){var e=g({},t,{forceTimestampOffset:!0});
4716g(t,i.generateSegmentInfo_(e)),i.isPendingTimestampOffset_=!1,i.updateTransmuxerAndRequestSegment_(t)})},t.updateTransmuxerAndRequestSegment_=function(n){var r=this;this.shouldUpdateTransmuxerTimestampOffset_(n.timestampOffset)&&(this.gopBuffer_.length=0,n.gopsToAlignWith=[],this.timeMapping_=0,this.transmuxer_.postMessage({action:"reset"}),this.transmuxer_.postMessage({action:"setTimestampOffset",timestampOffset:n.timestampOffset}));var e=this.createSimplifiedSegmentObj_(n),t=this.isEndOfStream_(n.mediaIndex,n.playlist,n.partIndex),i=null!==this.mediaIndex,a=n.timeline!==this.currentTimeline_&&0<n.timeline,a=t||i&&a;this.logger_("Requesting "+rl(n)),e.map&&!e.map.bytes&&(this.logger_("going to request init segment."),this.appendInitSegment_={video:!0,audio:!0}),n.abortRequests=Gu({xhr:this.vhs_.xhr,xhrOptions:this.xhrOptions_,decryptionWorker:this.decrypter_,segment:e,abortFn:this.handleAbort_.bind(this,n),progressFn:this.handleProgress_.bind(this),trackInfoFn:this.handleTrackInfo_.bind(this),timingInfoFn:this.handleTimingInfo_.bind(this),videoSegmentTimingInfoFn:this.handleSegmentTimingInfo_.bind(this,"video",n.requestId),audioSegmentTimingInfoFn:this.handleSegmentTimingInfo_.bind(this,"audio",n.requestId),captionsFn:this.handleCaptions_.bind(this),isEndOfTimeline:a,endedTimelineFn:function(){r.logger_("received endedtimeline callback")},id3Fn:this.handleId3_.bind(this),dataFn:this.handleData_.bind(this),doneFn:this.segmentRequestFinished_.bind(this),onTransmuxerLog:function(e){var t=e.message,i=e.level,e=e.stream;r.logger_(rl(n)+" logged from transmuxer stream "+e+" as a "+i+": "+t)}})},t.trimBackBuffer_=function(e){var t,i,n,r,r=(t=this.seekable_(),i=this.currentTime_(),n=this.playlist_.targetDuration||10,r=i-Sl.BACK_BUFFER_LENGTH,t.length&&(r=Math.max(r,t.start(0))),Math.min(i-n,r));0<r&&this.remove(0,r)},t.createSimplifiedSegmentObj_=function(e){var t=e.segment,i=e.part,n={resolvedUri:(i||t).resolvedUri,byterange:(i||t).byterange,requestId:e.requestId,transmuxer:e.transmuxer,audioAppendStart:e.audioAppendStart,gopsToAlignWith:e.gopsToAlignWith,part:e.part},i=e.playlist.segments[e.mediaIndex-1];return i&&i.timeline===t.timeline&&(i.videoTimingInfo?n.baseStartTime=i.videoTimingInfo.transmuxedDecodeEnd:i.audioTimingInfo&&(n.baseStartTime=i.audioTimingInfo.transmuxedDecodeEnd)),t.key&&(e=t.key.iv||new Uint32Array([0,0,0,e.mediaIndex+e.playlist.mediaSequence]),n.key=this.segmentKey(t.key),n.key.iv=e),t.map&&(n.map=this.initSegmentForMap(t.map)),n},t.saveTransferStats_=function(e){this.mediaRequests+=1,e&&(this.mediaBytesTransferred+=e.bytesReceived,this.mediaTransferDuration+=e.roundTripTime)},t.saveBandwidthRelatedStats_=function(e,t){this.pendingSegment_.byteLength=t.bytesReceived,e<1/60?this.logger_("Ignoring segment's bandwidth because its duration of "+e+" is less than the min to record "+1/60):(this.bandwidth=t.bandwidth,this.roundTrip=t.roundTripTime)},t.handleTimeout_=function(){this.mediaRequestsTimedout+=1,this.bandwidth=1,this.roundTrip=NaN,this.trigger("bandwidthupdate")},t.segmentRequestFinished_=function(e,t,i){if(this.callQueue_.length)this.callQueue_.push(this.segmentRequestFinished_.bind(this,e,t,i));else if(this.saveTransferStats_(t.stats),this.pendingSegment_&&t.requestId===this.pendingSegment_.requestId){if(e)return this.pendingSegment_=null,this.state="READY",e.code===Al?void 0:(this.pause(),e.code===xl?void this.handleTimeout_():(this.mediaRequestsErrored+=1,this.error(e),void this.trigger("error")));e=this.pendingSegment_;this.saveBandwidthRelatedStats_(e.duration,t.stats),e.endOfAllRequests=t.endOfAllRequests,i.gopInfo&&(this.gopBuffer_=function(e,t,i){if(!t.length)return e;if(i)return t.slice();for(var n=t[0].pts,r=0;r<e.length&&!(e[r].pts>=n);r++);return e.slice(0,r).concat(t)}(this.gopBuffer_,i.gopInfo,this.safeAppend_)),this.state="APPENDING",this.trigger("appending"),this.waitForAppendsToComplete_(e)}},t.setTimeMapping_=function(e){e=this.syncController_.mappingForTimeline(e);null!==e&&(this.timeMapping_=e)},t.updateMediaSecondsLoaded_=function(e){"number"==typeof e.start&&"number"==typeof e.end?this.mediaSecondsLoaded+=e.end-e.start:this.mediaSecondsLoaded+=e.duration},t.shouldUpdateTransmuxerTimestampOffset_=function(e){return null!==e&&("main"===this.loaderType_&&e!==this.sourceUpdater_.videoTimestampOffset()||!this.audioDisabled_&&e!==this.sourceUpdater_.audioTimestampOffset())},t.trueSegmentStart_=function(e){var t=e.currentStart,i=e.playlist,n=e.mediaIndex,r=e.firstVideoFrameTimeForData,a=e.currentVideoTimestampOffset,s=e.useVideoTimingInfo,o=e.videoTimingInfo,e=e.audioTimingInfo;if("undefined"!=typeof t)return t;if(!s)return e.start;i=i.segments[n-1];return 0!==n&&i&&"undefined"!=typeof i.start&&i.end===r+a?o.start:r},t.waitForAppendsToComplete_=function(e){var t=this.getCurrentMediaInfo_(e);if(!t)return this.error({message:"No starting media returned, likely due to an unsupported media format.",blacklistDuration:1/0}),void this.trigger("error");var i=t.hasAudio,n=t.hasVideo,t=t.isMuxed,n="main"===this.loaderType_&&n,t=!this.audioDisabled_&&i&&!t;if(e.waitingOnAppends=0,!e.hasAppendedData_)return e.timingInfo||"number"!=typeof e.timestampOffset||(this.isPendingTimestampOffset_=!0),e.timingInfo={start:0},e.waitingOnAppends++,this.isPendingTimestampOffset_||(this.updateSourceBufferTimestampOffset_(e),this.processMetadataQueue_()),void this.checkAppendsDone_(e);n&&e.waitingOnAppends++,t&&e.waitingOnAppends++,n&&this.sourceUpdater_.videoQueueCallback(this.checkAppendsDone_.bind(this,e)),t&&this.sourceUpdater_.audioQueueCallback(this.checkAppendsDone_.bind(this,e))},t.checkAppendsDone_=function(e){this.checkForAbort_(e.requestId)||
4716(e.waitingOnAppends--,0===e.waitingOnAppends&&this.handleAppendsDone_())},t.checkForIllegalMediaSwitch=function(e){var t,i,e=(t=this.loaderType_,i=this.getCurrentMediaInfo_(),e=e,"main"===t&&i&&e?e.hasAudio||e.hasVideo?i.hasVideo&&!e.hasVideo?"Only audio found in segment when we expected video. We can't switch to audio only from a stream that had video. To get rid of this message, please add codec information to the manifest.":!i.hasVideo&&e.hasVideo?"Video found in segment when we expected only audio. We can't switch to a stream with video from an audio only stream. To get rid of this message, please add codec information to the manifest.":null:"Neither audio nor video found in segment.":null);return!!e&&(this.error({message:e,blacklistDuration:1/0}),this.trigger("error"),!0)},t.updateSourceBufferTimestampOffset_=function(e){var t;null===e.timestampOffset||"number"!=typeof e.timingInfo.start||e.changedTimestampOffset||"main"!==this.loaderType_||(t=!1,e.timestampOffset-=e.timingInfo.start,e.changedTimestampOffset=!0,e.timestampOffset!==this.sourceUpdater_.videoTimestampOffset()&&(this.sourceUpdater_.videoTimestampOffset(e.timestampOffset),t=!0),e.timestampOffset!==this.sourceUpdater_.audioTimestampOffset()&&(this.sourceUpdater_.audioTimestampOffset(e.timestampOffset),t=!0),t&&this.trigger("timestampoffset"))},t.updateTimingInfoEnd_=function(e){e.timingInfo=e.timingInfo||{};var t=this.getMediaInfo_(),t="main"===this.loaderType_&&t&&t.hasVideo&&e.videoTimingInfo?e.videoTimingInfo:e.audioTimingInfo;t&&(e.timingInfo.end="number"==typeof t.end?t.end:t.start+e.duration)},t.handleAppendsDone_=function(){if(this.pendingSegment_&&this.trigger("appendsdone"),!this.pendingSegment_)return this.state="READY",void(this.paused()||this.monitorBuffer_());var e=this.pendingSegment_;this.updateTimingInfoEnd_(e),this.shouldSaveSegmentTimingInfo_&&this.syncController_.saveSegmentTimingInfo({segmentInfo:e,shouldSaveTimelineMapping:"main"===this.loaderType_});var t=ul(e,this.sourceType_);if(t&&("warn"===t.severity?tr.log.warn(t.message):this.logger_(t.message)),this.recordThroughput_(e),this.pendingSegment_=null,this.state="READY",!e.isSyncRequest||(this.trigger("syncinfoupdate"),e.hasAppendedData_)){this.logger_("Appended "+rl(e)),this.addSegmentMetadataCue_(e),this.fetchAtBuffer_=!0,this.currentTimeline_!==e.timeline&&(this.timelineChangeController_.lastTimelineChange({type:this.loaderType_,from:this.currentTimeline_,to:e.timeline}),"main"!==this.loaderType_||this.audioDisabled_||this.timelineChangeController_.lastTimelineChange({type:"audio",from:this.currentTimeline_,to:e.timeline})),this.currentTimeline_=e.timeline,this.trigger("syncinfoupdate");var i=e.segment,t=e.part,i=i.end&&this.currentTime_()-i.end>3*e.playlist.targetDuration,t=t&&t.end&&this.currentTime_()-t.end>3*e.playlist.partTargetDuration;if(i||t)return this.logger_("bad "+(i?"segment":"part")+" "+rl(e)),void this.resetEverything();null!==this.mediaIndex&&this.trigger("bandwidthupdate"),this.trigger("progress"),this.mediaIndex=e.mediaIndex,this.partIndex=e.partIndex,this.isEndOfStream_(e.mediaIndex,e.playlist,e.partIndex)&&this.endOfStream(),this.trigger("appended"),e.hasAppendedData_&&this.mediaAppends++,this.paused()||this.monitorBuffer_()}else this.logger_("Throwing away un-appended sync request "+rl(e))},t.recordThroughput_=function(e){var t,i;e.duration<1/60?this.logger_("Ignoring segment's throughput because its duration of "+e.duration+" is less than the min to record "+1/60):(t=this.throughput.rate,i=Date.now()-e.endOfAllRequests+1,i=Math.floor(e.byteLength/i*8*1e3),this.throughput.rate+=(i-t)/++this.throughput.count)},t.addSegmentMetadataCue_=function(e){var t,i,n,r;this.segmentMetadataTrack_&&(i=(t=e.segment).start,r=t.end,nl(i)&&nl(r)&&(il(i,r,this.segmentMetadataTrack_),n=window.WebKitDataCue||window.VTTCue,e={custom:t.custom,dateTimeObject:t.dateTimeObject,dateTimeString:t.dateTimeString,bandwidth:e.playlist.attributes.BANDWIDTH,resolution:e.playlist.attributes.RESOLUTION,codecs:e.playlist.attributes.CODECS,byteLength:e.byteLength,uri:e.uri,timeline:e.timeline,playlist:e.playlist.id,start:i,end:r},(r=new n(i,r,JSON.stringify(e))).value=e,this.segmentMetadataTrack_.addCue(r)))},e}(tr.EventTarget);function Ol(){}function Rl(e){return"string"!=typeof e?e:e.replace(/./,function(e){return e.toUpperCase()})}function Ml(e,t){var i=t[e+"Buffer"];return i&&i.updating||t.queuePending[e]}function Nl(e,t){if(0!==t.queue.length){var i=0,n=t.queue[i];if("mediaSource"!==n.type){if("mediaSource"!==e&&t.ready()&&"closed"!==t.mediaSource.readyState&&!Ml(e,t)){if(n.type!==e){if(null===(i=function(e,t){for(var i=0;i<t.length;i++){var n=t[i];if("mediaSource"===n.type)return null;if(n.type===e)return i}return null}(e,t.queue)))return;n=t.queue[i]}t.queue.splice(i,1),(t.queuePending[e]=n).action(e,t),n.doneFn||(t.queuePending[e]=null,Nl(e,t))}}else t.updating()||"closed"===t.mediaSource.readyState||(t.queue.shift(),n.action(t),n.doneFn&&n.doneFn(),Nl("audio",t),Nl("video",t))}}function Ul(e,t){var i=t[e+"Buffer"],n=Rl(e);i&&(i.removeEventListener("updateend",t["on"+n+"UpdateEnd_"]),i.removeEventListener("error",t["on"+n+"Error_"]),t.codecs[e]=null,t[e+"Buffer"]=null)}function Bl(e,t){return e&&t&&-1!==Array.prototype.indexOf.call(e.sourceBuffers,t)}function Fl(e){var t=e.type,i=e.sourceUpdater,n=e.action,r=e.doneFn,e=e.name;i.queue.push({type:t,action:n,doneFn:r,name:e}),Nl(t,i)}function jl(i,n){return function(e){var t;n.queuePending[i]&&(t=n.queuePending[i].doneFn,n.queuePending[i]=null,t&&t(n[i+"Error_"])),Nl(i,n)}}function Hl(e){return decodeURIComponent(escape(String.fromCharCode.apply(null,e)))}function ql(e,t){e.abort(),e.pause(),t&&t.activePlaylistLoader&&(t.activePlaylistLoader.pause(),t.activePlaylistLoader=null)}function Vl(e,t){(t.activePlaylistLoader=e).load()}function Wl(e,t){for(var i=0;i<e.length;i++){if(tu(t,e[i]))return!0;
4716if(e[i].playlists&&Wl(e[i].playlists,t))return!0}return!1}function Gl(a){["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(function(e){mc[e](e,a)});var e,s=a.mediaTypes,t=a.masterPlaylistLoader,i=a.tech,n=a.vhs,r=a.segmentLoaders,o=r.AUDIO,u=r.main;function l(){s.AUDIO.onTrackChanged(),i.trigger({type:"usage",name:"vhs-audio-change"}),i.trigger({type:"usage",name:"hls-audio-change"})}for(e in["AUDIO","SUBTITLES"].forEach(function(e){var u,l,o,c,t,i,d,h,n,r;s[e].activeGroup=(u=e,l=a,function(t){var e=l.masterPlaylistLoader,i=l.mediaTypes[u].groups,n=e.media();if(!n)return null;var r=null;n.attributes[u]&&(r=i[n.attributes[u]]);var a=Object.keys(i);if(!r)if("AUDIO"===u&&1<a.length&&nu(l.master))for(var s=0;s<a.length;s++){var o=i[a[s]];if(Wl(o,n)){r=o;break}}else i.main?r=i.main:1===a.length&&(r=i[a[0]]);return"undefined"==typeof t?r:null!==t&&r&&r.filter(function(e){return e.id===t.id})[0]||null}),s[e].activeTrack=gc[e](e,a),s[e].onGroupChanged=(o=e,c=a,function(){var e=c.segmentLoaders,t=e[o],i=e.main,n=c.mediaTypes[o],r
4716=n.activeTrack(),a=n.getActiveGroup(),s=n.activePlaylistLoader,e=n.lastGroup_;a&&e&&a.id===e.id||(n.lastGroup_=a,n.lastTrack_=r,ql(t,n),a&&!a.isMasterPlaylist&&(a.playlistLoader?(t.resyncLoader(),Vl(a.playlistLoader,n)):s&&i.resetEverything()))}),s[e].onGroupChanging=(t=e,i=a,function(){var e=i.segmentLoaders[t];i.mediaTypes[t].lastGroup_=null,e.abort(),e.pause()}),s[e].onTrackChanged=(d=e,h=a,function(){var e=h.masterPlaylistLoader,t=h.segmentLoaders,i=t[d],n=t.main,r=h.mediaTypes[d],a=r.activeTrack(),s=r.getActiveGroup(),o=r.activePlaylistLoader,u=r.lastTrack_;if((!u||!a||u.id!==a.id)&&(r.lastGroup_=s,r.lastTrack_=a,ql(i,r),s)){if(s.isMasterPlaylist){if(!a||!u||a.id===u.id)return;var l=h.vhs.masterPlaylistController_,t=l.selectPlaylist();return l.media()===t?void 0:(r.logger_("track change. Switching master audio from "+u.id+" to "+a.id),e.pause(),n.resetEverything(),void l.fastQualityChange_(t))}if("AUDIO"===d){if(!s.playlistLoader)return n.setAudio(!0),void n.resetEverything();i.setAudio(!0),n.setAudio(!1)}o!==s.playlistLoader&&(i.track&&i.track(a),i.resetEverything()),Vl(s.playlistLoader,r)}}),s[e].getActiveGroup=(n=e,r=a.mediaTypes,function(){var e=r[n].activeTrack();return e?r[n].activeGroup(e):null})}),(r=s.AUDIO.activeGroup())&&(r=(r.filter(function(e){return e.default})[0]||r[0]).id,s.AUDIO.tracks[r].enabled=!0,s.AUDIO.onGroupChanged(),s.AUDIO.onTrackChanged(),s.AUDIO.getActiveGroup().playlistLoader?(u.setAudio(!1),o.setAudio(!0)):u.setAudio(!0)),t.on("mediachange",function(){["AUDIO","SUBTITLES"].forEach(function(e){return s[e].onGroupChanged()})}),t.on("mediachanging",function(){["AUDIO","SUBTITLES"].forEach(function(e){return s[e].onGroupChanging()})}),i.audioTracks().addEventListener("change",l),i.remoteTextTracks().addEventListener("change",s.SUBTITLES.onTrackChanged),n.on("dispose",function(){i.audioTracks().removeEventListener("change",l),i.remoteTextTracks().removeEventListener("change",s.SUBTITLES.onTrackChanged)}),i.clearTracks("audio"),s.AUDIO.tracks)i.audioTracks().addTrack(s.AUDIO.tracks[e])}function zl(e,t,i){var n,r,a,s,o=e.masterPlaylistController_,u=o[(e.options_.smoothQualityChange?"smooth":"fast")+"QualityChange_"].bind(o);t.attributes&&(n=t.attributes.RESOLUTION,this.width=n&&n.width,this.height=n&&n.height,this.bandwidth=t.attributes.BANDWIDTH),this.codecs=Yu(o.master(),t),this.playlist=t,this.id=i,this.enabled=(r=e.playlists,a=t.id,s=u,function(e){var t=r.master.playlists[a],i=$o(t),n=Jo(t);return"undefined"==typeof e?n:(e?delete t.disabled:t.disabled=!0,e===n||i||(s(),e?r.trigger("renditionenabled"):r.trigger("renditiondisabled")),e)})}function Xl(t,e){var i=0,n=0,r=tr.mergeOptions(Tc,e);function a(){n&&t.currentTime(n)}function s(e){null!=e&&(n=t.duration()!==1/0&&t.currentTime()||0,t.one("loadedmetadata",a),t.src(e),t.trigger({type:"usage",name:"vhs-error-reload"}),t.trigger({type:"usage",name:"hls-error-reload"}),t.play())}function o(){return Date.now()-i<1e3*r.errorInterval?(t.trigger({type:"usage",name:"vhs-error-reload-canceled"}),void t.trigger({type:"usage",name:"hls-error-reload-canceled"})):r.getSource&&"function"==typeof r.getSource?(i=Date.now(),r.getSource.call(t,s)):void tr.log.error("ERROR: reloadSourceOnError - The option getSource must be a function!")}function u(){t.off("loadedmetadata",a),t.off("error",o),t.off("dispose",u)}t.ready(function(){t.trigger({type:"usage",name:"vhs-error-reload-initialized"}),t.trigger({type:"usage",name:"hls-error-reload-initialized"})}),t.on("error",o),t.on("dispose",u),t.reloadSourceOnError=function(e){u(),Xl(t,e)}}var Kl,Yl=["video","audio"],Ql=function(n,r,a){return function(t,i){var e=i[t+"Buffer"];if(Bl(i.mediaSource,e)){i.logger_("Appending segment "+r.mediaIndex+"'s "+n.length+" bytes to "+t+"Buffer");try{e.appendBuffer(n)}catch(e){i.logger_("Error with code "+e.code+" "+(22===e.code?"(QUOTA_EXCEEDED_ERR) ":"")+"when appending segment "+r.mediaIndex+" to "+t+"Buffer"),i.queuePending[t]=null,a(e)}}}},$l=function(n,r){return function(t,i){var e=i[t+"Buffer"];if(Bl(i.mediaSource,e)){i.logger_("Removing "+n+" to "+r+" from "+t+"Buffer");try{e.remove(n,r)}catch(e){i.logger_("Remove "+n+" to "+r+" from "+t+"Buffer failed")}}}},Jl=function(n){return function(e,t){var i=t[e+"Buffer"];Bl(t.mediaSource,i)&&(t.logger_("Setting "+e+"timestampOffset to "+n),i.timestampOffset=n)}},Zl=function(i){return function(e,t){i()}},ec=function(t){return function(e){if("open"===e.mediaSource.readyState){e.logger_("Calling mediaSource endOfStream("+(t||"")+")");try{e.mediaSource.endOfStream(t)}catch(e){tr.log.warn("Failed to call media source endOfStream",e)}}}},tc=function(t){return function(e){e.logger_("Setting mediaSource duration to "+t);try{e.mediaSource.duration=t}catch(e){tr.log.warn("Failed to set media source duration",e)}}},ic=function(){return function(t,e){if("open"===e.mediaSource.readyState){var i=e[t+"Buffer"];if(Bl(e.mediaSource,i)){e.logger_("calling abort on "+t+"Buffer");try{i.abort()}catch(e){tr.log.warn("Failed to abort on "+t+"Buffer",e)}}}}},nc=function(n,r){return function(e){var t=Rl(n),i=mr(r);e.logger_("Adding "+n+"Buffer with codec "+r+" to mediaSource");i=e.mediaSource.addSourceBuffer(i);i.addEventListener("updateend",e["on"+t+"UpdateEnd_"]),i.addEventListener("error",e["on"+t+"Error_"]),e.codecs[n]=r,e[n+"Buffer"]=i}},rc=function(i){return function(e){var t=e[i+"Buffer"];if(Ul(i,e),Bl(e.mediaSource,t)){e.logger_("Removing "+i+"Buffer with codec "+e.codecs[i]+" from mediaSource");try{e.mediaSource.removeSourceBuffer(t)}catch(e){tr.log.warn("Failed to removeSourceBuffer "+i+"Buffer",e)}}}},ac=function(r){return function(e,t){var i=t[e+"Buffer"],n=mr(r);Bl(t.mediaSource,i)&&t.codecs[e]!==r&&(t.logger_("changing "+e+"Buffer codec from "+t.codecs[e]+" to "+r),i.changeType(n),t.codecs[e]=r)}},sc=function(i){function e(e){var t=i.call(this)||this;return t.mediaSource=e,t.sourceopenListener_=function(){return Nl("mediaSource",ft(t))},t.mediaSource.addEventListener("sourceopen",t.sourceopenListener_),t.logger_=Oo("SourceUpdater"),t.audioTimestampOffset_=0,t.videoTimestampOffset_=0,t.queue=[],t.queuePending={audio:null,video:null},t.delayedAudioAppendQueue_=[],t.videoAppendQueued_=!1,t.codecs={},t.onVideoUpdateEnd_=jl("video",ft(t)),t.onAudioUpdateEnd_=jl("audio",ft(t)),t.onVideoError_=function(e){t.videoError_=e},t.onAudioError_=function(e){t.audioError_=e},t.createdSourceBuffers_=!1,t.initializedEme_=!1,t.triggeredReady_=!1,t}
vendor: 9,185 bytes, line 4716
4716mt(e,i);var t=e.prototype;return t.initializedEme=function(){this.initializedEme_=!0,this.triggerReady()},t.hasCreatedSourceBuffers=function(){return this.createdSourceBuffers_},t.hasInitializedAnyEme=function(){return this.initializedEme_},t.ready=function(){return this.hasCreatedSourceBuffers()&&this.hasInitializedAnyEme()},t.createSourceBuffers=function(e){this.hasCreatedSourceBuffers()||(this.addOrChangeSourceBuffers(e),this.createdSourceBuffers_=!0,this.trigger("createdsourcebuffers"),this.triggerReady())},t.triggerReady=function(){this.ready()&&!this.triggeredReady_&&(this.triggeredReady_=!0,this.trigger("ready"))},t.addSourceBuffer=function(e,t){Fl({type:"mediaSource",sourceUpdater:this,action:nc(e,t),name:"addSourceBuffer"})},t.abort=function(e){Fl({type:e,sourceUpdater:this,action:ic(e),name:"abort"})},t.removeSourceBuffer=function(e){this.canRemoveSourceBuffer()?Fl({type:"mediaSource",sourceUpdater:this,action:rc(e),name:"removeSourceBuffer"}):tr.log.error("removeSourceBuffer is not supported!")},t.canRemoveSourceBuffer=function(){return!tr.browser.IE_VERSION&&!tr.browser.IS_FIREFOX&&window.MediaSource&&window.MediaSource.prototype&&"function"==typeof window.MediaSource.prototype.removeSourceBuffer},e.canChangeType=function(){return window.SourceBuffer&&window.SourceBuffer.prototype&&"function"==typeof window.SourceBuffer.prototype.changeType},t.canChangeType=function(){return this.constructor.canChangeType()},t.changeType=function(e,t){this.canChangeType()?Fl({type:e,sourceUpdater:this,action:ac(t),name:"changeType"}):tr.log.error("changeType is not supported!")},t.addOrChangeSourceBuffers=function(i){var n=this;if(!i||"object"!=typeof i||0===Object.keys(i).length)throw new Error("Cannot addOrChangeSourceBuffers to undefined codecs");Object.keys(i).forEach(function(e){var t=i[e];if(!n.hasCreatedSourceBuffers())return n.addSourceBuffer(e,t);n.canChangeType()&&n.changeType(e,t)})},t.appendBuffer=function(e,t){var i=this,n=e.segmentInfo,r=e.type,a=e.bytes;if(this.processedAppend_=!0,"audio"===r&&this.videoBuffer&&!this.videoAppendQueued_)return this.delayedAudioAppendQueue_.push([e,t]),void this.logger_("delayed audio append of "+a.length+" until video append");Fl({type:r,sourceUpdater:this,action:Ql(a,n||{mediaIndex:-1},t),doneFn:t,name:"appendBuffer"}),"video"===r&&(this.videoAppendQueued_=!0,this.delayedAudioAppendQueue_.length&&(r=this.delayedAudioAppendQueue_.slice(),this.logger_("queuing delayed audio "+r.length+" appendBuffers"),this.delayedAudioAppendQueue_.length=0,r.forEach(function(e){i.appendBuffer.apply(i,e)})))},t.audioBuffered=function(){return Bl(this.mediaSource,this.audioBuffer)&&this.audioBuffer.buffered||tr.createTimeRange()},t.videoBuffered=function(){return Bl(this.mediaSource,this.videoBuffer)&&this.videoBuffer.buffered||tr.createTimeRange()},t.buffered=function(){var e=Bl(this.mediaSource,this.videoBuffer)?this.videoBuffer:null,t=Bl(this.mediaSource,this.audioBuffer)?this.audioBuffer:null;return t&&!e?this.audioBuffered():e&&!t?this.videoBuffered():function(e,t){var i=null,n=null,r=0,a=[],s=[];if(!(e&&e.length&&t&&t.length))return tr.createTimeRange();for(var o=e.length;o--;)a.push({time:e.start(o),type:"start"}),a.push({time:e.end(o),type:"end"});for(o=t.length;o--;)a.push({time:t.start(o),type:"start"}),a.push({time:t.end(o),type:"end"});for(a.sort(function(e,t){return e.time-t.time}),o=0;o<a.length;o++)"start"===a[o].type?2===++r&&(i=a[o].time):"end"===a[o].type&&1===--r&&(n=a[o].time),null!==i&&null!==n&&(s.push([i,n]),n=i=null);return tr.createTimeRanges(s)}(this.audioBuffered(),this.videoBuffered())},t.setDuration=function(e,t){void 0===t&&(t=Ol),Fl({type:"mediaSource",sourceUpdater:this,action:tc(e),name:"duration",doneFn:t})},t.endOfStream=function(e,t){void 0===t&&(t=Ol),Fl({type:"mediaSource",sourceUpdater:this,action:ec(e="string"!=typeof(e=void 0===e?null:e)?void 0:e),name:"endOfStream",doneFn:t})},t.removeAudio=function(e,t,i){void 0===i&&(i=Ol),this.audioBuffered().length&&0!==this.audioBuffered().end(0)?Fl({type:"audio",sourceUpdater:this,action:$l(e,t),doneFn:i,name:"remove"}):i()},t.removeVideo=function(e,t,i){void 0===i&&(i=Ol),this.videoBuffered().length&&0!==this.videoBuffered().end(0)?Fl({type:"video",sourceUpdater:this,action:$l(e,t),doneFn:i,name:"remove"}):i()},t.updating=function(){return!(!Ml("audio",this)&&!Ml("video",this))},t.audioTimestampOffset=function(e){return"undefined"!=typeof e&&this.audioBuffer&&this.audioTimestampOffset_!==e&&(Fl({type:"audio",sourceUpdater:this,action:Jl(e),name:"timestampOffset"}),this.audioTimestampOffset_=e),this.audioTimestampOffset_},t.videoTimestampOffset=function(e){return"undefined"!=typeof e&&this.videoBuffer&&this.videoTimestampOffset!==e&&(Fl({type:"video",sourceUpdater:this,action:Jl(e),name:"timestampOffset"}),this.videoTimestampOffset_=e),this.videoTimestampOffset_},t.audioQueueCallback=function(e){this.audioBuffer&&Fl({type:"audio",sourceUpdater:this,action:Zl(e),name:"callback"})},t.videoQueueCallback=function(e){this.videoBuffer&&Fl({type:"video",sourceUpdater:this,action:Zl(e),name:"callback"})},t.dispose=function(){var t=this;this.trigger("dispose"),Yl.forEach(function(e){t.abort(e),t.canRemoveSourceBuffer()?t.removeSourceBuffer(e):t[e+"QueueCallback"](function(){return Ul(e,t)})}),this.videoAppendQueued_=!1,this.delayedAudioAppendQueue_.length=0,this.sourceopenListener_&&this.mediaSource.removeEventListener("sourceopen",this.sourceopenListener_),this.off()},e}(tr.EventTarget),oc=new Uint8Array("\n\n".split("").map(function(e){return e.charCodeAt(0)})),uc=function(i){function e(e,t){return(t=i.call(this,e,t=void 0===t?{}:t)||this).mediaSource_=null,t.subtitlesTrack_=null,t.loaderType_="subtitle",t.featuresNativeTextTracks_=e.featuresNativeTextTracks,t.shouldSaveSegmentTimingInfo_=!1,t}mt(e,i);var t=e.prototype;return t.createTransmuxer_=function(){return null},t.buffered_=function(){if(!this.subtitlesTrack_||!this.subtitlesTrack_.cues||!this.subtitlesTrack_.cues.length)return tr.createTimeRanges();var e=this.subtitlesTrack_.cues,t=e[0].startTime,e=e[e.length-1].startTime;return tr.createTimeRanges([[t,e]])},t.initSegmentForMap=function(e,t){if(void 0===t&&(t=!1),!e)return null;var i=bu(e),n=this.initSegments_[i];return t&&!n&&e.bytes&&(t=oc.byteLength+e.bytes.byteLength,(t=new Uint8Array(t)).set(e.bytes),t.set(oc,e.bytes.byteLength),this.initSegments_[i]=n={resolvedUri:e.resolvedUri,byterange:e.byterange,bytes:t}),n||e},t.couldBeginLoading_=function(){return this.playlist_&&this.subtitlesTrack_&&!this.paused()},t.init_=function(){return this.state="READY",this.resetEverything(),this.monitorBuffer_()},t.track=function(e){return"undefined"==typeof e||(this.subtitlesTrack_=e,"INIT"===this.state&&this.couldBeginLoading_()&&this.init_()),this.subtitlesTrack_},t.remove=function(e,t){il(e,t,this.subtitlesTrack_)},t.fillBuffer_=function(){var e=this,t=this.chooseNextRequest_();if(t){if(null===this.syncController_.timestampOffsetForTimeline(t.timeline))return this.syncController_.one("timestampoffset",function(){e.state="READY",e.paused()||e.monitorBuffer_()}),void(this.state="WAITING_ON_TIMELINE");this.loadSegment_(t)}},t.timestampOffsetForSegment_=function(){return null},t.chooseNextRequest_=function(){return this.skipEmptySegments_(i.prototype.chooseNextRequest_.call(this))},t.skipEmptySegments_=function(e){for(;e&&e.segment.empty;){if(e.mediaIndex+1>=e.playlist.segments.length){e=null;break}e=this.generateSegmentInfo_({playlist:e.playlist,mediaIndex:e.mediaIndex+1,startOfSegment:e.startOfSegment+e.duration,isSyncRequest:e.isSyncRequest})}return e},t.stopForError=function(e){this.error(e),this.state="READY",this.pause(),this.trigger("error")},t.segmentRequestFinished_=function(e,t,i){var n=this;if(this.subtitlesTrack_){if(this.saveTransferStats_(t.stats),!this.pendingSegment_)return this.state="READY",void(this.mediaRequestsAborted+=1);if(e)return e.code===xl&&this.handleTimeout_(),e.code===Al?this.mediaRequestsAborted+=1:this.mediaRequestsErrored+=1,void this.stopForError(e);var r=this.pendingSegment_;this.saveBandwidthRelatedStats_(r.duration,t.stats),this.state="APPENDING",this.trigger("appending");var a=r.segment;if(a.map&&(a.map.bytes=t.map.bytes),r.bytes=t.bytes,"function"!=typeof window.WebVTT&&this.subtitlesTrack_&&this.subtitlesTrack_.tech_){var s=function(){n.subtitlesTrack_.tech_.off("vttjsloaded",o),n.stopForError({message:"Error loading vtt.js"})},o=function(){n.subtitlesTrack_.tech_.off("vttjserror",s),n.segmentRequestFinished_(e,t,i)};return this.state="WAITING_ON_VTTJS",this.subtitlesTrack_.tech_.one("vttjsloaded",o),void this.subtitlesTrack_.tech_.one("vttjserror",s)}a.requested=!0;try{this.parseVTTCues_(r)}catch(e){return void this.stopForError({message:e.message})}if(this.updateTimeMapping_(r,this.syncController_.timelines[r.timeline],this.playlist_),r.cues.length?r.timingInfo={start:r.cues[0].startTime,end:r.cues[r.cues.length-1].endTime}:r.timingInfo={start:r.startOfSegment,end:r.startOfSegment+r.duration},r.isSyncRequest)return this.trigger("syncinfoupdate"),this.pendingSegment_=null,void(this.state="READY");r.byteLength=r.bytes.byteLength,this.mediaSecondsLoaded+=a.duration,r.cues.forEac
4716h(function(e){n.subtitlesTrack_.addCue(n.featuresNativeTextTracks_?new window.VTTCue(e.startTime,e.endTime,e.text):e)}),function(t){var e=t.cues;if(e)for(var i=0;i<e.length;i++){for(var n=[],r=0,a=0;a<e.length;a++)e[i].startTime===e[a].startTime&&e[i].endTime===e[a].endTime&&e[i].text===e[a].text&&1<++r&&n.push(e[a]);n.length&&n.forEach(function(e){return t.removeCue(e)})}}(this.subtitlesTrack_),this.handleAppendsDone_()}else this.state="READY"},t.handleData_=function(){},t.updateTimingInfoEnd_=function(){},t.parseVTTCues_=function(t){var e=!1;"function"==typeof window.TextDecoder?i=new window.TextDecoder("utf8"):(i=window.WebVTT.StringDecoder(),e=!0);var i=new window.WebVTT.Parser(window,window.vttjs,i);t.cues=[],t.timestampmap={MPEGTS:0,LOCAL:0},i.oncue=t.cues.push.bind(t.cues),i.ontimestampmap=function(e){t.timestampmap=e},i.onparsingerror=function(e){tr.log.warn("Error encountered when parsing cues: "+e.message)},t.segment.map&&(n=t.segment.map.bytes,e&&(n=Hl(n)),i.parse(n));var n=t.bytes;e&&(n=Hl(n)),i.parse(n),i.flush()},t.updateTimeMapping_=function(e,t,i){var n,r,a=e.segment;t&&(e.cues.length?(r=e.timestampmap,n=r.MPEGTS/cl-r.LOCAL+t.mapping,e.cues.forEach(function(e){e.startTime+=n,e.endTime+=n}),i.syncInfo||(r=e.cues[0].startTime,t=e.cues[e.cues.length-1].startTime,i.syncInfo={mediaSequence:i.mediaSequence+e.mediaIndex,time:Math.min(r,t-a.duration)})):a.empty=!0)},e}(Dl),lc=[{name:"VOD",run:function(e,t,i,n,r){if(i===1/0)return null;return{time:0,segmentIndex:0,partIndex:null}}},{name:"ProgramDateTime",run:function(e,t,i,n,r){if(!Object.keys(e.timelineToDatetimeMappings).length)return null;var a=null,s=null,o=qo(t);r=r||0;for(var u=0;u<o.length;u++){var l=o[t.endList||0===r?u:o.length-(u+1)],c=l.segment,d=e.timelineToDatetimeMappings[c.timeline];if(d&&c.dateTimeObject){var h=c.dateTimeObject.getTime()/1e3+d;if(c.parts&&"number"==typeof l.partIndex)for(var p=0;p<l.partIndex;p++)h+=c.parts[p].duration;d=Math.abs(r-h);if(null!==s&&(0===d||s<d))break;s=d,a={time:h,segmentIndex:l.segmentIndex,partIndex:l.partIndex}}}return a}},{name:"Segment",run:function(e,t,i,n,r){var a=null,s=null;r=r||0;for(var o=qo(t),u=0;u<o.length;u++){var l=o[t.endList||0===r?u:o.length-(u+1)],c=l.segment,d=l.part&&l.part.start||c&&c.start;if(c.timeline===n&&"undefined"!=typeof d){c=Math.abs(r-d);if(null!==s&&s<c)break;(!a||null===s||c<=s)&&(s=c,a={time:d,segmentIndex:l.segmentIndex,partIndex:l.partIndex})}}return a}},{name:"Discontinuity",run:function(e,t,i,n,r){var a=null;if(r=r||0,t.discontinuityStarts&&t.discontinuityStarts.length)for(var s=null,o=0;o<t.discontinuityStarts.length;o++){var u=t.discontinuityStarts[o],l=t.discontinuitySequence+o+1,c=e.discontinuities[l];if(c){l=Math.abs(r-c.time);if(null!==s&&s<l)break;(!a||null===s||l<=s)&&(s=l,a={time:c.time,segmentIndex:u,partIndex:null})}}return a}},{name:"Playlist",run:function(e,t,i,n,r){return t.syncInfo?{time:t.syncInfo.time,segmentIndex:t.syncInfo.mediaSequence-t.mediaSequence,partIndex:null}:null}}],cc=function(i){function e(e){var t=i.call(this)||this;return t.timelines=[],t.discontinuities=[],t.timelineToDatetimeMappings={},t.logger_=Oo("SyncController"),t}mt(e,i);var t=e.prototype;return t.getSyncPoint=function(e,t,i,n){i=this.runStrategies_(e,t,i,n);return i.length?this.selectSyncPoint_(i,{key:"time",value:n}):null},t.getExpiredTime=function(e,t){if(!e||!e.segments)return null;t=this.runStrategies_(e,t,e.discontinuitySequence,0);if(!t.length)return null;t=this.selectSyncPoint_(t,{key:"segmentIndex",value:0});return 0<t.segmentIndex&&(t.time*=-1),Math.abs(t.time+Ko({defaultDuration:e.targetDuration,durationList:e.segments,startIndex:t.segmentIndex,endIndex:0}))},t.runStrategies_=function(e,t,i,n){for(var r=[],a=0;a<lc.length;a++){var s=lc[a],o=s.run(this,e,t,i,n);o&&(o.strategy=s.name,r.push({strategy:s.name,syncPoint:o}))}return r},t.selectSyncPoint_=function(e,t){for(var i=e[0].syncPoint,n=Math.abs(e[0].syncPoint[t.key]-t.value),r=e[0].strategy,a=1;a<e.length;a++){var s=Math.abs(e[a].syncPoint[t.key]-t.value);s<n&&(n=s,i=e[a].syncPoint,r=e[a].strategy)}return this.logger_("syncPoint for ["+t.key+": "+t.value+"] chosen with strategy ["+r+"]: [time:"+i.time+", segmentIndex:"+i.segmentIndex+("number"==typeof i.partIndex?",partIndex:"+i.partIndex:"")+"]"),i},t.saveExpiredSegmentInfo=function(e,t){var i=t.mediaSequence-e.mediaSequence;if(86400<i)tr.log.warn("Not saving expired segment info. Media sequence gap "+i+" is too large.");else for(var n=i-1;0<=n;n--){var r=e.segments[n];if(r&&"undefined"!=typeof r.start){t.syncInfo={mediaSequence:e.mediaSequence+n,time:r.start}
4716,this.logger_("playlist refresh sync: [time:"+t.syncInfo.time+", mediaSequence: "+t.syncInfo.mediaSequence+"]"),this.trigger("syncinfoupdate");break}}},t.setDateTimeMappingForStart=function(e){var t;this.timelineToDatetimeMappings={},e.segments&&e.segments.length&&e.segments[0].dateTimeObject&&(e=(t=e.segments[0]).dateTimeObject.getTime()/1e3,this.timelineToDatetimeMappings[t.timeline]=-e)},t.saveSegmentTimingInfo=function(e){var t=e.segmentInfo,i=e.shouldSaveTimelineMapping,n=this.calculateSegmentTimeMapping_(t,t.timingInfo,i),e=t.segment;n&&(this.saveDiscontinuitySyncInfo_(t),t.playlist.syncInfo||(t.playlist.syncInfo={mediaSequence:t.playlist.mediaSequence+t.mediaIndex,time:e.start}));t=e.dateTimeObject;e.discontinuity&&i&&t&&(this.timelineToDatetimeMappings[e.timeline]=-t.getTime()/1e3)},t.timestampOffsetForTimeline=function(e){return"undefined"==typeof this.timelines[e]?null:this.timelines[e].time},t.mappingForTimeline=function(e){return"undefined"==typeof this.timelines[e]?null:this.timelines[e].mapping},t.calculateSegmentTimeMapping_=function(e,t,i){var n,r,a=e.segment,s=e.part,o=this.timelines[e.timeline];if("number"==typeof e.timestampOffset)o={time:e.startOfSegment,mapping:e.startOfSegment-t.start},i&&(this.timelines[e.timeline]=o,this.trigger("timestampoffset"),this.logger_("time mapping for timeline "+e.timeline+": [time: "+o.time+"] [mapping: "+o.mapping+"]")),n=e.startOfSegment,r=t.end+o.mapping;else{if(!o)return!1;n=t.start+o.mapping,r=t.end+o.mapping}return s&&(s.start=n,s.end=r),(!a.start||n<a.start)&&(a.start=n),a.end=r,!0},t.saveDiscontinuitySyncInfo_=function(e){var t=e.playlist,i=e.segment;if(i.discontinuity)this.discontinuities[i.timeline]={time:i.start,accuracy:0};else if(t.discontinuityStarts&&t.discontinuityStarts.length)for(var n=0;n<t.discontinuityStarts.length;n++){var r,a=t.discontinuityStarts[n],s=t.discontinuitySequence+n+1,o=a-e.mediaIndex,u=Math.abs(o);(!this.discontinuities[s]||this.discontinuities[s].accuracy>u)&&(r=void 0,r=o<0?i.start-Ko({defaultDuration:t.targetDuration,durationList:t.segments,startIndex:e.mediaIndex,endIndex:a}):i.end+Ko({defaultDuration:t.targetDuration,durationList:t.segments,startIndex:e.mediaIndex+1,endIndex:a}),this.discontinuities[s]={time:r,accuracy:u})}},t.dispose=function(){this.trigger("dispose"),this.off()},e}(tr.EventTarget),dc=function(t){function e(){var e=t.call(this)||this;return e.pendingTimelineChanges_={},e.lastTimelineChanges_={},e}mt(e,t);var i=e.prototype;return i.clearPendingTimelineChange=function(e){this.pendingTimelineChanges_[e]=null,this.trigger("pendingtimelinechange")},i.pendingTimelineChange=function(e){var t=e.type,i=e.from,e=e.to;return"number"==typeof i&&"number"==typeof e&&(this.pendingTimelineChanges_[t]={type:t,from:i,to:e},this.trigger("pendingtimelinechange")),this.pendingTimelineChanges_[t]},i.lastTimelineChange=function(e){var t=e.type,i=e.from,e=e.to;return"number"==typeof i&&"number"==typeof e&&(this.lastTimelineChanges_[t]={type:t,from:i,to:e},delete this.pendingTimelineChanges_[t],this.trigger("timelinechange")),this.lastTimelineChanges_[t]},i.dispose=function(){this.trigger("dispose"),this.pendingTimelineChanges_={},this.lastTimelineChanges_={},this.off()},e}(tr.EventTarget),hc=x(U(W(function(){function e(e,t,i){return e(i={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&i.path)}},i.exports),i.exports}var t=e(function(e){function n(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}e.exports=function(e,t,i){return t&&n(e.prototype,t),i&&n(e,i),e},e.exports.default=e.exports,e.exports.__esModule=!0}),i=e(function(i){function n(e,t){return i.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},i.exports.default=i.exports,i.exports.__esModule=!0,n(e,t)}i.exports=n,i.exports.default=i.exports,i.exports.__esModule=!0}),n=e(function(e){e.exports=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,i(e,t)},e.exports.default=e.exports,e.exports.__esModule=!0}),r=function(){function e(){this.listeners={}}var t=e.prototype;return t.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)},t.off=function(e,t){if(!this.listeners[e])return!1;t=this.listeners[e].indexOf(t);return this.listeners[e]=this.listeners[e].slice(0),this.listeners[e].splice(t,1),-1<t},t.trigger=function(e){var t=this.listeners[e];if(t)if(2===arguments.length)for(var i=t.length,n=0;n<i;++n)t[n].call(this,arguments[1]);
vendor: 3,809 bytes, lines 4716-4720
4716else for(var r=Array.prototype.slice.call(arguments,1),a=t.length,s=0;s<a;++s)t[s].apply(this,r)},t.dispose=function(){this.listeners={}},t.pipe=function(t){this.on("data",function(e){t.push(e)})},e}();
4717 /*! @name aes-decrypter @version 3.1.2 @license Apache-2.0 */
4718 var c=null,m=function(){function e(e){var t,i,n;c=c||function(){for(var e,t,i,n,r,a,s,o=[[[],[],[],[],[]],[[],[],[],[],[]]],u=o[0],l=o[1],c=u[4],d=l[4],h=[],p=[],f=0;f<256;f++)p[(h[f]=f<<1^283*(f>>7))^f]=f;for(e=t=0;!c[e];e^=i||1,t=p[t]||1)for(s=16843009*h[n=h[i=h[d[c[e]=r=(r=t^t<<1^t<<2^t<<3^t<<4)>>8^255&r^99]=e]]]^65537*n^257*i^16843008*e,a=257*h[r]^16843008*r,f=0;f<4;f++)u[f][e]=a=a<<24^a>>>8,l[f][r]=s=s<<24^s>>>8;for(f=0;f<5;f++)u[f]=u[f].slice(0),l[f]=l[f].slice(0);return o}(),this._tables=[[c[0][0].slice(),c[0][1].slice(),c[0][2].slice(),c[0][3].slice(),c[0][4].slice()],[c[1][0].slice(),c[1][1].slice(),c[1][2].slice(),c[1][3].slice(),c[1][4].slice()]];var r=this._tables[0][4],a=this._tables[1],s=e.length,o=1;if(4!==s&&6!==s&&8!==s)throw new Error("Invalid aes key size");var u=e.slice(0),l=[];for(this._key=[u,l],t=s;t<4*s+28;t++)n=u[t-1],(t%s==0||8===s&&t%s==4)&&(n=r[n>>>24]<<24^r[n>>16&255]<<16^r[n>>8&255]<<8^r[255&n],t%s==0&&(n=n<<8^n>>>24^o<<24,o=o<<1^283*(o>>7))),u[t]=u[t-s]^n;for(i=0;t;i++,t--)n=u[3&i?t:t-4],l[i]=t<=4||i<4?n:a[0][r[n>>>24]]^a[1][r[n>>16&255]]^a[2][r[n>>8&255]]^a[3][r[255&n]]}return e.prototype.decrypt=function(e,t,i,n,r,a){for(var s,o,u,l=this._key[1],c=e^l[0],d=n^l[1],h=i^l[2],p=t^l[3],f=l.length/4-2,m=4,t=this._tables[1],g=t[0],y=t[1],v=t[2],_=t[3],b=t[4],T=0;T<f;T++)s=g[c>>>24]^y[d>>16&255]^v[h>>8&255]^_[255&p]^l[m],o=g[d>>>24]^y[h>>16&255]^v[p>>8&255]^_[255&c]^l[m+1],u=g[h>>>24]^y[p>>16&255]^v[c>>8&255]^_[255&d]^l[m+2],p=g[p>>>24]^y[c>>16&255]^v[d>>8&255]^_[255&h]^l[m+3],m+=4,c=s,d=o,h=u;for(T=0;T<4;T++)r[(3&-T)+a]=b[c>>>24]<<24^b[d>>16&255]<<16^b[h>>8&255]<<8^b[255&p]^l[m++],s=c,c=d,d=h,h=p,p=s},e}(),l=function(t){function e(){var e=t.call(this,r)||this;return e.jobs=[],e.delay=1,e.timeout_=null,e}n(e,t);var i=e.prototype;return i.processJob_=function(){this.jobs.shift()(),this.jobs.length?this.timeout_=setTimeout(this.processJob_.bind(this),this.delay):this.timeout_=null},i.push=function(e){this.jobs.push(e),this.timeout_||(this.timeout_=setTimeout(this.processJob_.bind(this),this.delay))},e}(r),g=function(e){return e<<24|(65280&e)<<8|(16711680&e)>>8|e>>>24},a=function(){function u(e,t,i,n){var r=u.STEP,a=new Int32Array(e.buffer),s=new Uint8Array(e.byteLength),o=0;for(this.asyncStream_=new l,this.asyncStream_.push(this.decryptChunk_(a.subarray(o,o+r),t,i,s)),o=r;o<a.length;o+=r)i=new Uint32Array([g(a[o-4]),g(a[o-3]),g(a[o-2]),g(a[o-1])]),this.asyncStream_.push(this.decryptChunk_(a.subarray(o,o+r),t,i,s));this.asyncStream_.push(function(){
4719 /*! @name pkcs7 @version 1.0.4 @license Apache-2.0 */
4720 var e;n(null,(e=s).subarray(0,e.byteLength-e[e.byteLength-1]))})}return u.prototype.decryptChunk_=function(t,i,n,r){return function(){var e=function(e,t,i){for(var n,r,a,s,o=new Int32Array(e.buffer,e.byteOffset,e.byteLength>>2),u=new m(Array.prototype.slice.call(t)),e=new Uint8Array(e.byteLength),l=new Int32Array(e.buffer),c=i[0],d=i[1],h=i[2],p=i[3],f=0;f<o.length;f+=4)n=g(o[f]),r=g(o[f+1]),a=g(o[f+2]),s=g(o[f+3]),u.decrypt(n,r,a,s,l,f),l[f]=g(l[f]^c),l[f+1]=g(l[f+1]^d),l[f+2]=g(l[f+2]^h),l[f+3]=g(l[f+3]^p),c=n,d=r,h=a,p=s;return e}(t,i,n);r.set(e,t.byteOffset)}},t(u,null,[{key:"STEP",get:function(){return 32e3}}]),u}();self.onmessage=function(e){var r=e.data,t=new Uint8Array(r.encrypted.bytes,r.encrypted.byteOffset,r.encrypted.byteLength),i=new Uint32Array(r.key.bytes,r.key.byteOffset,r.key.byteLength/4),e=new Uint32Array(r.iv.bytes,r.iv.byteOffset,r.iv.byteLength/4);new a(t,i,e,function(e,t){var i,n;self.postMessage((i={source:r.source,decrypted:t},n={}
4720,Object.keys(i).forEach(function(e){var t=i[e];ArrayBuffer.isView(t)?n[e]={bytes:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength}:n[e]=t}),n),[t.buffer])})}}))),pc={AUDIO:function(s,o){return function(){var e=o.segmentLoaders[s],t=o.mediaTypes[s],i=o.blacklistCurrentPlaylist;ql(e,t);var n=t.activeTrack(),e=t.activeGroup(),e=(e.filter(function(e){return e.default})[0]||e[0]).id,r=t.tracks[e];if(n!==r){for(var a in tr.log.warn("Problem encountered loading the alternate audio track.Switching back to default."),t.tracks)t.tracks[a].enabled=t.tracks[a]===r;t.onTrackChanged()}else i({message:"Problem encountered loading the default audio track."})}},SUBTITLES:function(i,n){return function(){var e=n.segmentLoaders[i],t=n.mediaTypes[i];tr.log.warn("Problem encountered loading the subtitle track.Disabling subtitle track."),ql(e,t);e=t.activeTrack();e&&(e.mode="disabled"),t.onTrackChanged()}}},fc={AUDIO:function(e,t,i){var n,r,a;t&&(n=i.tech,r=i.requestOptions,a=i.segmentLoaders[e],t.on("loadedmetadata",function(){var e=t.media();a.playlist(e,r),(!n.paused()||e.endList&&"none"!==n.preload())&&a.load()}),t.on("loadedplaylist",function(){a.playlist(t.media(),r),n.paused()||a.load()}),t.on("error",pc[e](e,i)))},SUBTITLES:function(e,t,i){var n=i.tech,r=i.requestOptions,a=i.segmentLoaders[e],s=i.mediaTypes[e];t.on("loadedmetadata",function(){var e=t.media();a.playlist(e,r),a.track(s.activeTrack()),(!n.paused()||e.endList&&"none"!==n.preload())&&a.load()}),t.on("loadedplaylist",function(){a.playlist(t.media(),r),n.paused()||a.load()}),t.on("error",pc[e](e,i))}},mc={AUDIO:function(e,t){var i,n,r=t.vhs,a=t.sourceType,s=t.segmentLoaders[e],o=t.requestOptions,u=t.master.mediaGroups,l=t.mediaTypes[e],c=l.groups,d=l.tracks,h=l.logger_,p=t.masterPlaylistLoader,f=nu(p.master);for(i in u[e]&&0!==Object.keys(u[e]).length||(u[e]={main:{default:{default:!0}}},f&&(u[e].main.default.playlists=p.master.playlists)),u[e])for(var m in c[i]||(c[i]=[]),u[e][i]){var g=u[e][i][m],y=void 0,y=f?(h("AUDIO group '"+i+"' label '"+m+"' is a master playlist"),g.isMasterPlaylist=!0,null):"vhs-json"===a&&g.playlists?new yl(g.playlists[0],r,o):g.resolvedUri?new yl(g.resolvedUri,r,o):g.playlists&&"dash"===a?new Tl(g.playlists[0],r,o,p):null,g=tr.mergeOptions({id:m,playlistLoader:y},g);fc[e](e,g.playlistLoader,t),c[i].push(g),"undefined"==typeof d[m]&&(g=new tr.AudioTrack({id:m,kind:(n=void 0,n=(y=g).default?"main":"alternative",n=y.characteristics&&0<=y.characteristics.indexOf("public.accessibility.describes-video")?"main-desc":n),enabled:!1,language:g.language,default:g.default,label:m}),d[m]=g)}s.on("error",pc[e](e,t))},SUBTITLES:function(e,t){var i,n=t.tech,r=t.vhs,a=t.sourceType,s=t.segmentLoaders[e],o=t.requestOptions,u=t.master.mediaGroups,l=t.mediaTypes[e],c=l.groups,d=l.tracks,h=t.masterPlaylistLoader;for(i in u[e])for(var p in c[i]||(c[i]=[]),u[e][i])if(!u[e][i][p].forced){var f=u[e][i][p],m=void 0;if("hls"===a)m=new yl(f.resolvedUri,r,o);else if("dash"===a){if(!f.playlists.filter(function(e){return e.excludeUntil!==1/0}).length)return;m=new Tl(f.playlists[0],r,o,h)}else"vhs-json"===a&&(m=new yl(f.playlists?f.playlists[0]:f.resolvedUri,r,o));f=tr.mergeOptions({id:p,playlistLoader:m},f),fc[e](e,f.playlistLoader,t),c[i].push(f),"undefined"==typeof d[p]&&(f=n.addRemoteTextTrack({id:p,kind:"subtitles",default:f.default&&f.autoselect,language:f.language,label:p},!1).track,d[p]=f)}s.on("error",pc[e](e,t))},"CLOSED-CAPTIONS":function(e,t){var i,n=t.tech,r=t.master.mediaGroups,t=t.mediaTypes[e],a=t.groups,s=t.tracks;for(i in r[e])for(var o in a[i]||(a[i]=[]),r[e][i]){var u,l,c=r[e][i][o];/^(?:CC|SERVICE)/.test(c.instreamId)&&(void 0===(l=(u=n.options_.vhs&&n.options_.vhs.captionServices||{})[(l={label:o,language:c.language,instreamId:c.instreamId,default:c.default&&c.autoselect}).instreamId]?tr.mergeOptions(l,u[l.instreamId]):l).default&&delete l.default,a[i].push(tr.mergeOptions({id:o},c)),"undefined"==typeof s[o]&&(l=n.addRemoteTextTrack({id:l.instreamId,kind:"captions",default:l.default,language:l.language,label:l.label},!1).track,s[o]=l))}}},gc={AUDIO:function(i,n){return function(){var e,t=n.mediaTypes[i].tracks;for(e in t)if(t[e].enabled)return t[e];return null}},SUBTITLES:function(i,n){return function(){var e,t=n.mediaTypes[i].tracks;for(e in t)if("showing"===t[e].mode||"hidden"===t[e].mode)return t[e];return null}}},yc=["mediaRequests","mediaRequestsAborted","mediaRequestsTimedout","mediaRequestsErrored","mediaTransferDuration","mediaBytesTransferred","mediaAppends"],vc=function(v){function e(e){var t=v.call(this)||this,i=e.src,n=e.handleManifestRedirects,r=e.withCredentials,a=e.tech,s=e.bandwidth,o=e.externVhs,u=e.useCueTags,l=e.blacklistDuration,c=e.enableLowInitialPlaylist,d=e.s
4720ourceType,h=e.cacheEncryptionKeys,p=e.experimentalBufferBasedABR,f=e.experimentalLeastPixelDiffSelector,m=e.captionServices;if(!i)throw new Error("A non-empty playlist URL or JSON manifest string is required");var g,y=e.maxPlaylistRetries;null!==y&&"undefined"!=typeof y||(y=1/0),Kl=o,t.experimentalBufferBasedABR=Boolean(p),t.experimentalLeastPixelDiffSelector=Boolean(f),t.withCredentials=r,t.tech_=a,t.vhs_=a.vhs,t.sourceType_=d,t.useCueTags_=u,t.blacklistDuration=l,t.maxPlaylistRetries=y,t.enableLowInitialPlaylist=c,t.useCueTags_&&(t.cueTagsTrack_=t.tech_.addTextTrack("metadata","ad-cues"),t.cueTagsTrack_.inBandMetadataTrackDispatchType=""),t.requestOptions_={withCredentials:r,handleManifestRedirects:n,maxPlaylistRetries:y,timeout:null},t.on("error",t.pauseLoading),t.mediaTypes_=(g={},["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(function(e){g[e]={groups:{},tracks:{},activePlaylistLoader:null,activeGroup:Ol,activeTrack:Ol,getActiveGroup:Ol,onGroupChanged:Ol,onTrackChanged:Ol,lastTrack_:null,logger_:Oo("MediaGroups["+e+"]")}}),g),t.mediaSource=new window.MediaSource,t.handleDurationChange_=t.handleDurationChange_.bind(ft(t)),t.handleSourceOpen_=t.handleSourceOpen_.bind(ft(t)),t.handleSourceEnded_=t.handleSourceEnded_.bind(ft(t)),t.mediaSource.addEventListener("durationchange",t.handleDurationChange_),t.mediaSource.addEventListener("sourceopen",t.handleSourceOpen_),t.mediaSource.addEventListener("sourceended",t.handleSourceEnded_),t.seekable_=tr.createTimeRanges(),t.hasPlayed_=!1,t.syncController_=new cc(e),t.segmentMetadataTrack_=a.addRemoteTextTrack({kind:"metadata",label:"segment-metadata"},!1).track,t.decrypter_=new hc,t.sourceUpdater_=new sc(t.mediaSource),t.inbandTextTracks_={},t.timelineChangeController_=new dc;h={vhs:t.vhs_,parse708captions:e.parse708captions,captionServices:m,mediaSource:t.mediaSource,currentTime:t.tech_.currentTime.bind(t.tech_),seekable:function(){return t.seekable()},seeking:function(){return t.tech_.seeking()},duration:function(){return t.duration()},hasPlayed:function(){return t.hasPlayed_},goalBufferLength:function(){return t.goalBufferLength()},bandwidth:s,syncController:t.syncController_,decrypter:t.decrypter_,sourceType:t.sourceType_,inbandTextTracks:t.inbandTextTracks_,cacheEncryptionKeys:h,sourceUpdater:t.sourceUpdater_,timelineChangeController:t.timelineChangeController_,experimentalExactManifestTimings:e.experimentalExactManifestTimings};t.masterPlaylistLoader_=new("dash"===t.sourceType_?Tl:yl)(i,t.vhs_,t.requestOptions_),t.setupMasterPlaylistLoaderListeners_(),t.mainSegmentLoader_=new Dl(tr.mergeOptions(h,{segmentMetadataTrack:t.segmentMetadataTrack_,loaderType:"main"}),e),t.audioSegmentLoader_=new Dl(tr.mergeOptions(h,{loaderType:"audio"}),e),t.subtitleSegmentLoader_=new uc(tr.mergeOptions(h,{loaderType:"vtt",featuresNativeTextTracks:t.tech_.featuresNativeTextTracks}),e),t.setupSegmentLoaderListeners_(),t.experimentalBufferBasedABR&&(t.masterPlaylistLoader_.one("loadedplaylist",function(){return t.startABRTimer_()}),t.tech_.on("pause",function(){return t.stopABRTimer_()}),t.tech_.on("play",function(){return t.startABRTimer_()})),yc.forEach(function(e){t[e+"_"]=function(e){return this.audioSegmentLoader_[e]+this.mainSegmentLoader_[e]}.bind(ft(t),e)}),t.logger_=Oo("MPC"),t.triggeredFmp4Usage=!1,"none"===t.tech_.preload()?(t.loadOnPlay_=function(){t.loadOnPlay_=null,t.masterPlaylistLoader_.load()},t.tech_.one("play",t.loadOnPlay_)):t.masterPlaylistLoader_.load(),t.timeToLoadedData__=-1,t.mainAppendsToLoadedData__=-1,t.audioAppendsToLoadedData__=-1;e="none"===t.tech_.preload()?"play":"loadstart";return t.tech_.one(e,function(){var e=Date.now();t.tech_.one("loadeddata",function(){t.timeToLoadedData__=Date.now()-e,t.mainAppendsToLoadedData__=t.mainSegmentLoader_.mediaAppends,t.audioAppendsToLoadedData__=t.audioSegmentLoader_.mediaAppends})}),t}mt(e,v);var t=e.prototype;return t.mainAppendsToLoadedData_=function(){return this.mainAppendsToLoadedData__},t.audioAppendsToLoadedData_=function(){return this.audioAppendsToLoadedData__},t.appendsToLoadedData_=function(){var e=this.mainAppendsToLoadedData_(),t=this.audioAppendsToLoadedData_();return-1===e||-1===t?-1:e+t},t.timeToLoadedData_=function(){return this.timeToLoadedData__},t.checkABR_=function(){var e=this.selectPlaylist();e&&this.shouldSwitchToMedia_(e)&&this.switchMedia_(e,"abr")},t.switchMedia_=function(e,t,i){var n=this.media(),r=n&&(n.id||n.uri),n=e.id||e.uri;r&&r!==n&&(this.logger_("switch media "+r+" -> "+n+" from "+t),this.tech_.trigger({type:"usage",name:"vhs-rendition-change-"+t})),this.masterPlaylistLoader_.media(e,i)},t.startABRTimer_=function(){var e=this;this.stopABRTimer_(),this.abrTimer_=window.setInterval(function(){return e.checkABR_()},250)},t.stopABRTimer_=function(){this.tech_.scrubbing&&this.tech_.scrubbing()||(window.clearInterval(this.abrTimer_),this.abrTimer_=null)},t.getAudioTrackPlaylists_=function(){var e=this.master(),t=e&&e.playlists||[];if(!e||!e.mediaGroups||!e.mediaGroups.AUDIO)return t;var i,n=e.mediaGroups.AUDIO,r=Object.keys(n);if(Object.keys(this.mediaTypes_.AUDIO.groups).length)i=this.mediaTypes_.AUDIO.activeTrack();else{var a,s=n.main||r.length&&n[r[0]];for(a in s)if(s[a].default){i={label:a};break}}if(!i)return t;var o,u=[];for(o in n)if(n[o][i.label]){var l=n[o][i.label];if(l.playlists&&l.playlists.length)u.push.apply(u,l.playlists);
4720else if(l.uri)u.push(l);else if(e.playlists.length)for(var c=0;c<e.playlists.length;c++){var d=e.playlists[c];d.attributes&&d.attributes.AUDIO&&d.attributes.AUDIO===o&&u.push(d)}}return u.length?u:t},t.setupMasterPlaylistLoaderListeners_=function(){var i=this;this.masterPlaylistLoader_.on("loadedmetadata",function(){var e=i.masterPlaylistLoader_.media(),t=1.5*e.targetDuration*1e3;eu(i.masterPlaylistLoader_.master,i.masterPlaylistLoader_.media())?i.requestOptions_.timeout=0:i.requestOptions_.timeout=t,e.endList&&"none"!==i.tech_.preload()&&(i.mainSegmentLoader_.playlist(e,i.requestOptions_),i.mainSegmentLoader_.load()),Gl({sourceType:i.sourceType_,segmentLoaders:{AUDIO:i.audioSegmentLoader_,SUBTITLES:i.subtitleSegmentLoader_,main:i.mainSegmentLoader_},tech:i.tech_,requestOptions:i.requestOptions_,masterPlaylistLoader:i.masterPlaylistLoader_,vhs:i.vhs_,master:i.master(),mediaTypes:i.mediaTypes_,blacklistCurrentPlaylist:i.blacklistCurrentPlaylist.bind(i)}),i.triggerPresenceUsage_(i.master(),e),i.setupFirstPlay(),!i.mediaTypes_.AUDIO.activePlaylistLoader||i.mediaTypes_.AUDIO.activePlaylistLoader.media()?i.trigger("selectedinitialmedia"):i.mediaTypes_.AUDIO.activePlaylistLoader.one("loadedmetadata",function(){i.trigger("selectedinitialmedia")})}),this.masterPlaylistLoader_.on("loadedplaylist",function(){i.loadOnPlay_&&i.tech_.off("play",i.loadOnPlay_);var e,t=i.masterPlaylistLoader_.media();if(!t){if(i.excludeUnsupportedVariants_(),!(e=(e=i.enableLowInitialPlaylist?i.selectInitialPlaylist():e)||i.selectPlaylist())||!i.shouldSwitchToMedia_(e))return;if(i.initialMedia_=e,i.switchMedia_(i.initialMedia_,"initial"),!("vhs-json"===i.sourceType_&&i.initialMedia_.segments))return;t=i.initialMedia_}i.handleUpdatedMediaPlaylist(t)}),this.masterPlaylistLoader_.on("error",function(){i.blacklistCurrentPlaylist(i.masterPlaylistLoader_.error)}),this.masterPlaylistLoader_.on("mediachanging",function(){i.mainSegmentLoader_.abort(),i.mainSegmentLoader_.pause()}),this.masterPlaylistLoader_.on("mediachange",function(){var e=i.masterPlaylistLoader_.media(),t=1.5*e.targetDuration*1e3;eu(i.masterPlaylistLoader_.master,i.masterPlaylistLoader_.media())?i.requestOptions_.timeout=0:i.requestOptions_.timeout=t,i.mainSegmentLoader_.playlist(e,i.requestOptions_),i.mainSegmentLoader_.load(),i.tech_.trigger({type:"mediachange",bubbles:!0})}),this.masterPlaylistLoader_.on("playlistunchanged",function(){var e=i.masterPlaylistLoader_.media();"playlist-unchanged"!==e.lastExcludeReason_&&i.stuckAtPlaylistEnd_(e)&&(i.blacklistCurrentPlaylist({message:"Playlist no longer updating.",reason:"playlist-unchanged"}),i.tech_.trigger("playliststuck"))}),this.masterPlaylistLoader_.on("renditiondisabled",function(){i.tech_.trigger({type:"usage",name:"vhs-rendition-disabled"}),i.tech_.trigger({type:"usage",name:"hls-rendition-disabled"})}),this.masterPlaylistLoader_.on("renditionenabled",function(){i.tech_.trigger({type:"usage",name:"vhs-rendition-enabled"}),i.tech_.trigger({type:"usage",name:"hls-rendition-enabled"})})},t.handleUpdatedMediaPlaylist=function(e){this.useCueTags_&&this.updateAdCues_(e),this.mainSegmentLoader_.playlist(e,this.requestOptions_),this.updateDuration(!e.endList),this.tech_.paused()||(this.mainSegmentLoader_.load(),this.audioSegmentLoader_&&this.audioSegmentLoader_.load())},t.triggerPresenceUsage_=function(e,t){var i,n=e.mediaGroups||{},r=!0,e=Object.keys(n.AUDIO);for(i in n.AUDIO)for(var a in n.AUDIO[i])n.AUDIO[i][a].uri||(r=!1);r&&(this.tech_.trigger({type:"usage",name:"vhs-demuxed"}),this.tech_.trigger({type:"usage",name:"hls-demuxed"})),Object.keys(n.SUBTITLES).length&&(this.tech_.trigger({type:"usage",name:"vhs-webvtt"}),this.tech_.trigger({type:"usage",name:"hls-webvtt"})),Kl.Playlist.isAes(t)&&(this.tech_.trigger({type:"usage",name:"vhs-aes"}),this.tech_.trigger({type:"usage",name:"hls-aes"})),e.length&&1<Object.keys(n.AUDIO[e[0]]).length&&(this.tech_.trigger({type:"usage",name:"vhs-alternate-audio"}),this.tech_.trigger({type:"usage",name:"hls-alternate-audio"})),this.useCueTags_&&(this.tech_.trigger({type:"usage",name:"vhs-playlist-cue-tags"}),this.tech_.trigger({type:"usage",name:"hls-playlist-cue-tags"}))},t.shouldSwitchToMedia_=function(e){var t=this.masterPlaylistLoader_.media()||this.masterPlaylistLoader_.pen
4720dingMedia_,i=this.tech_.currentTime(),n=this.bufferLowWaterLine(),r=this.bufferHighWaterLine();return function(e){var t=e.currentPlaylist,i=e.buffered,n=e.currentTime,r=e.nextPlaylist,a=e.bufferLowWaterLine,s=e.bufferHighWaterLine,o=e.duration,u=e.experimentalBufferBasedABR,l=e.log;if(!r)return tr.log.warn("We received no playlist to switch to. Please check your stream."),!1;var c="allowing switch "+(t&&t.id||"null")+" -> "+r.id;if(!t)return l(c+" as current playlist is not set"),!0;if(r.id===t.id)return!1;e=Boolean(Mo(i,n).length);if(!t.endList)return e||"number"!=typeof t.partTargetDuration?(l(c+" as current playlist is live"),!0):(l("not "+c+" as current playlist is live llhls, but currentTime isn't in buffered."),!1);i=jo(i,n),n=u?Sl.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE:Sl.MAX_BUFFER_LOW_WATER_LINE;if(o<n)return l(c+" as duration < max low water line ("+o+" < "+n+")"),!0;n=r.attributes.BANDWIDTH,r=t.attributes.BANDWIDTH;if(n<r&&(!u||i<s)){t=c+" as next bandwidth < current bandwidth ("+n+" < "+r+")";return u&&(t+=" and forwardBuffer < bufferHighWaterLine ("+i+" < "+s+")"),l(t),!0}if((!u||r<n)&&a<=i){a=c+" as forwardBuffer >= bufferLowWaterLine ("+i+" >= "+a+")";return u&&(a+=" and next bandwidth > current bandwidth ("+n+" > "+r+")"),l(a),!0}return l("not "+c+" as no switching criteria met"),!1}({buffered:this.tech_.buffered(),currentTime:i,currentPlaylist:t,nextPlaylist:e,bufferLowWaterLine:n,bufferHighWaterLine:r,duration:this.duration(),experimentalBufferBasedABR:this.experimentalBufferBasedABR,log:this.logger_})},t.setupSegmentLoaderListeners_=function(){var t=this;this.experimentalBufferBasedABR||(this.mainSegmentLoader_.on("bandwidthupdate",function(){var e=t.selectPlaylist();t.shouldSwitchToMedia_(e)&&t.switchMedia_(e,"bandwidthupdate"),t.tech_.trigger("bandwidthupdate")}),this.mainSegmentLoader_.on("progress",function(){t.trigger("progress")})),this.mainSegmentLoader_.on("error",function(){t.blacklistCurrentPlaylist(t.mainSegmentLoader_.error())}),this.mainSegmentLoader_.on("appenderror",function(){t.error=t.mainSegmentLoader_.error_,t.trigger("error")}),this.mainSegmentLoader_.on("syncinfoupdate",function(){t.onSyncInfoUpdate_()}),this.mainSegmentLoader_.on("timestampoffset",function(){t.tech_.trigger({type:"usage",name:"vhs-timestamp-offset"}),t.tech_.trigger({type:"usage",name:"hls-timestamp-offset"})}),this.audioSegmentLoader_.on("syncinfoupdate",function(){t.onSyncInfoUpdate_()}),this.audioSegmentLoader_.on("appenderror",function(){t.error=t.audioSegmentLoader_.error_,t.trigger("error")}),this.mainSegmentLoader_.on("ended",function(){t.logger_("main segment loader ended"),t.onEndOfStream()}),this.mainSegmentLoader_.on("earlyabort",function(e){t.experimentalBufferBasedABR||(t.delegateLoaders_("all",["abort"]),t.blacklistCurrentPlaylist({message:"Aborted early because there isn't enough bandwidth to complete the request without rebuffering."},120))});function e(){if(!t.sourceUpdater_.hasCreatedSourceBuffers())return t.tryToCreateSourceBuffers_();var e=t.getCodecsOrExclude_();e&&t.sourceUpdater_.addOrChangeSourceBuffers(e)}this.mainSegmentLoader_.on("trackinfo",e),this.audioSegmentLoader_.on("trackinfo",e),this.mainSegmentLoader_.on("fmp4",function(){t.triggeredFmp4Usage||(t.tech_.trigger({type:"usage",name:"vhs-fmp4"}),t.tech_.trigger({type:"usage",name:"hls-fmp4"}),t.triggeredFmp4Usage=!0)}),this.audioSegmentLoader_.on("fmp4",function(){t.triggeredFmp4Usage||(t.tech_.trigger({type:"usage",name:"vhs-fmp4"}),t.tech_.trigger({type:"usage",name:"hls-fmp4"}),t.triggeredFmp4Usage=!0)}),this.audioSegmentLoader_.on("ended",function(){t.logger_("audioSegmentLoader ended"),t.onEndOfStream()})},t.mediaSecondsLoaded_=function(){return Math.max(this.audioSegmentLoader_.mediaSecondsLoaded+this.mainSegmentLoader_.mediaSecondsLoaded)},t.load=function(){this.mainSegmentLoader_.load(),this.mediaTypes_.AUDIO.activePlaylistLoader&&this.audioSegmentLoader_.load(),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&this.subtitleSegmentLoader_.load()},t.smoothQualityChange_=function(e){void 0===e&&(e=this.selectPlaylist()),this.fastQualityChange_(e)},t.fastQualityChange_=function(e){var t=this;(e=void 0===e?this.selectPlaylist():e)!==this.masterPlaylistLoader_.media()?(this.switchMedia_(e,"fast-quality"),this.mainSegmentLoader_.resetEverything(function(){tr.browser.IE_VERSION||tr.browser.IS_EDGE?t.tech_.setCurrentTime(t.tech_.currentTime()+.04):t.tech_.setCurrentTime(t.tech_.currentTime())})):this.logger_("skipping fastQualityChange because new media is same as old")},t.play=function(){if(!this.setupFirstPlay()){this.tech_.ended()&&this.tech_.setCurrentTime(0),this.hasPlayed_&&this.load();var e=this.tech_.seekable();return this.tech_.duration()===1/0&&this.tech_.currentTime()<e.start(0)?this.tech_.setCurrentTime(e.end(e.length-1)):void 0}},t.setupFirstPlay=function(){var e=this,t=this.masterPlaylistLoader_.media();if(!t||this.tech_.paused()||this.hasPlayed_)return!1;if(!t.endList){var i=this.seekable();if(!i.length)return!1;if(tr.browser.IE_VERSION&&0===this.tech_.readyState())return this.tech_.one("loadedmetadata",function(){e.trigger("firstplay"),e.tech_.setCurrentTime(i.end(0)),e.hasPlayed_=!0}),!1;this.trigger("firstplay"),this.tech_.setCurrentTime(i.end(0))}return this.hasPlayed_=!0,this.load(),!0},t.handleSourceOpen_=function(){var e;this.tryToCreateSourceBuffers_(),!this.tech_.autoplay()||"undefined"!=typeof(e=this.tech_.play())&&"function"==typeof e.then&&e.then(null,function(e){}),this.trigger("sourceopen")},t.handleSourceEnded_=function(){var e,t;!this.inbandTextTracks_.metadataTrack_||(e=this.inbandTextTracks_.metadataTrack_.cues)&&e.length&&(t=this.duration(),e[e.length-1].endTime=isNaN(t)||Math.abs(t)===1/0?Number.MAX_VALUE:t)},t.handleDurationChange_=function(){this.tech_.trigger("durationchange")},t.onEndOfStream=function(){var e,t=this.mainSegmentLoader_.ended_;(t=this.mediaTypes_.AUDIO.activePlaylistLoader?((e=this.mainSegmentLoader_.getCurrentMediaInfo_())&&!e.hasVideo||t)&&this.audioSegmentLoader_.ended_:t)&&(this.stopABRTimer_(),this.sourceUpdater_.endOfStream())},t.stuckAtPlaylistEnd_=function(e){if(!this.seekable().length)return!1;var t=this.syncController_.getExpiredTime(e,this.duration());if(null===t)return!1;var i=Kl.Playlist.playlistEnd(e,t),e=this.tech_.currentTime(),t=this.tech_.buffered();if(!t.length)return i-e<=.1;t=t.end(t.length-1);return t-e<=.1&&i-t<=.1},t.blacklistCurrentPlaylist=function(e,t){var i=(e=void 0===e?{}:e).playlist||this.masterPlaylistLoader_.media();
4720if(t=t||e.blacklistDuration||this.blacklistDuration,!i)return this.error=e,void("open"!==this.mediaSource.readyState?this.trigger("error"):this.sourceUpdater_.endOfStream("network"));i.playlistErrors_++;var n,r=this.masterPlaylistLoader_.master.playlists,a=r.filter(Jo),s=1===a.length&&a[0]===i;if(1===r.length&&t!==1/0)return tr.log.warn("Problem encountered with playlist "+i.id+". Trying again since it is the only playlist."),this.tech_.trigger("retryplaylist"),this.masterPlaylistLoader_.load(s);s&&(n=!1,r.forEach(function(e){var t;e===i||"undefined"!=typeof(t=e.excludeUntil)&&t!==1/0&&(n=!0,delete e.excludeUntil)}),n&&(tr.log.warn("Removing other playlists from the exclusion list because the last rendition is about to be excluded."),this.tech_.trigger("retryplaylist"))),a=i.playlistErrors_>this.maxPlaylistRetries?1/0:Date.now()+1e3*t,i.excludeUntil=a,e.reason&&(i.lastExcludeReason_=e.reason),this.tech_.trigger("blacklistplaylist"),this.tech_.trigger({type:"usage",name:"vhs-rendition-blacklisted"}),this.tech_.trigger({type:"usage",name:"hls-rendition-blacklisted"});r=this.selectPlaylist();if(!r)return this.error="Playback cannot continue. No available working or supported playlists.",void this.trigger("error");t=e.internal?this.logger_:tr.log.warn,a=e.message?" "+e.message:"";t((e.internal?"Internal problem":"Problem")+" encountered with playlist "+i.id+"."+a+" Switching to playlist "+r.id+"."),r.attributes.AUDIO!==i.attributes.AUDIO&&this.delegateLoaders_("audio",["abort","pause"]),r.attributes.SUBTITLES!==i.attributes.SUBTITLES&&this.delegateLoaders_("subtitle",["abort","pause"]),this.delegateLoaders_("main",["abort","pause"]);a=r.targetDuration/2*1e3||5e3,a="number"==typeof r.lastRequest&&Date.now()-r.lastRequest<=a;return this.switchMedia_(r,"exclude",s||a)},t.pauseLoading=function(){this.delegateLoaders_("all",["abort","pause"]),this.stopABRTimer_()},t.delegateLoaders_=function(i,e){var n=this,r=[],t="all"===i;!t&&"main"!==i||r.push(this.masterPlaylistLoader_);var a=[];!t&&"audio"!==i||a.push("AUDIO"),!t&&"subtitle"!==i||(a.push("CLOSED-CAPTIONS"),a.push("SUBTITLES")),a.forEach(function(e){e=n.mediaTypes_[e]&&n.mediaTypes_[e].activePlaylistLoader;e&&r.push(e)}),["main","audio","subtitle"].forEach(function(e){var t=n[e+"SegmentLoader_"];!t||i!==e&&"all"!==i||r.push(t)}),r.forEach(function(t){return e.forEach(function(e){"function"==typeof t[e]&&t[e]()})})},t.setCurrentTime=function(e){var t=Mo(this.tech_.buffered(),e);return this.masterPlaylistLoader_&&this.masterPlaylistLoader_.media()&&this.masterPlaylistLoader_.media().segments?t&&t.length?e:(this.mainSegmentLoader_.resetEverything(),this.mainSegmentLoader_.abort(),this.mediaTypes_.AUDIO.activePlaylistLoader&&(this.audioSegmentLoader_.resetEverything(),this.audioSegmentLoader_.abort()),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&(this.subtitleSegmentLoader_.resetEverything(),this.subtitleSegmentLoader_.abort()),void this.load()):0},t.duration=function(){if(!this.masterPlaylistLoader_)return 0;var e=this.masterPlaylistLoader_.media();return e?e.endList?this.mediaSource?this.mediaSource.duration:Kl.Playlist.duration(e):1/0:0},t.seekable=function(){return this.seekable_},t.onSyncInfoUpdate_=function(){var e;if(this.masterPlaylistLoader_){var t=this.masterPlaylistLoader_.media();if(t){var i=this.syncController_.getExpiredTime(t,this.duration());if(null!==i){var n,r,a=this.masterPlaylistLoader_.master,s=Kl.Playlist.seekable(t,i,Kl.Playlist.liveEdgeDelay(a,t));if(0!==s.length){if(this.mediaTypes_.AUDIO.activePlaylistLoader){if(t=this.mediaTypes_.AUDIO.activePlaylistLoader.media(),null===(i=this.syncController_.getExpiredTime(t,this.duration())))return;if(0===(e=Kl.Playlist.seekable(t,i,Kl.Playlist.liveEdgeDelay(a,t))).length)return}this.seekable_&&this.seekable_.length&&(n=this.seekable_.end(0),r=this.seekable_.start(0)),!e||e.start(0)>s.end(0)||s.start(0)>e.end(0)?this.seekable_=s:this.seekable_=tr.createTimeRanges([[(e.start(0)>s.start(0)?e:s).start(0),(e.end(0)<s.end(0)?e:s).end(0)]]),this.seekable_&&this.seekable_.length&&this.seekable_.end(0)===n&&this.seekable_.start(0)===r||(this.logger_("seekable updated ["+Uo(this.seekable_)+"]"),this.tech_.trigger("seekablechanged"))}}}}},t.updateDuration=function(e){if(this.updateDuration_&&(this.mediaSource.removeEventListener("sourceopen",this.updateDuration_),this.updateDuration_=null),"open"!==this.mediaSource.readyState)return this.updateDuration_=this.updateDuration.bind(this,e),void this.mediaSource.addEventListener("sourceopen",this.updateDuration_);if(e){var t=this.seekable();return t.length?void((isNaN(this.mediaSource.duration)||this.mediaSource.duration<t.end(t.length-1))&&this.sourceUpdater_.setDuration(t.end(t.length-1))):void 0}e=this.tech_.buffered(),t=Kl.Playlist.duration(this.masterPlaylistLoader_.media());0<e.length&&(t=Math.max(t,e.end(e.length-1))),this.mediaSource.duration!==t&&this.sourceUpdater_.setDuration(t)}
4720,t.dispose=function(){var n=this;this.trigger("dispose"),this.decrypter_.terminate(),this.masterPlaylistLoader_.dispose(),this.mainSegmentLoader_.dispose(),this.loadOnPlay_&&this.tech_.off("play",this.loadOnPlay_),["AUDIO","SUBTITLES"].forEach(function(e){var t,i=n.mediaTypes_[e].groups;for(t in i)i[t].forEach(function(e){e.playlistLoader&&e.playlistLoader.dispose()})}),this.audioSegmentLoader_.dispose(),this.subtitleSegmentLoader_.dispose(),this.sourceUpdater_.dispose(),this.timelineChangeController_.dispose(),this.stopABRTimer_(),this.updateDuration_&&this.mediaSource.removeEventListener("sourceopen",this.updateDuration_),this.mediaSource.removeEventListener("durationchange",this.handleDurationChange_),this.mediaSource.removeEventListener("sourceopen",this.handleSourceOpen_),this.mediaSource.removeEventListener("sourceended",this.handleSourceEnded_),this.off()},t.master=function(){return this.masterPlaylistLoader_.master},t.media=function(){return this.masterPlaylistLoader_.media()||this.initialMedia_},t.areMediaTypesKnown_=function(){var e=!!this.mediaTypes_.AUDIO.activePlaylistLoader,t=!!this.mainSegmentLoader_.getCurrentMediaInfo_(),e=!e||!!this.audioSegmentLoader_.getCurrentMediaInfo_();return t&&e},t.getCodecsOrExclude_=function(){var n=this,r={main:this.mainSegmentLoader_.getCurrentMediaInfo_()||{},audio:this.audioSegmentLoader_.getCurrentMediaInfo_()||{}};r.video=r.main;var e=Yu(this.master(),this.media()),a={},t=!!this.mediaTypes_.AUDIO.activePlaylistLoader;if(r.main.hasVideo&&(a.video=e.video||r.main.videoCodec||"avc1.4d400d"),r.main.isMuxed&&(a.video+=","+(e.audio||r.main.audioCodec||Cr)),(r.main.hasAudio&&!r.main.isMuxed||r.audio.hasAudio||t)&&(a.audio=e.audio||r.main.audioCodec||r.audio.audioCodec||Cr,r.audio.isFmp4=(r.main.hasAudio&&!r.main.isMuxed?r.main:r.audio).isFmp4),a.audio||a.video){var s,i,o={};if(["video","audio"].forEach(function(e){var t,i;a.hasOwnProperty(e)&&(t=r[e].isFmp4,i=a[e],!(t?gr:yr)(i))&&(i=r[e].isFmp4?"browser":"muxer",o[i]=o[i]||[],o[i].push(a[e]),"audio"===e&&(s=i))}),t&&s&&this.media().attributes.AUDIO&&(i=this.media().attributes.AUDIO,this.master().playlists.forEac
4720h(function(e){(e.attributes&&e.attributes.AUDIO)===i&&e!==n.media()&&(e.excludeUntil=1/0)}),this.logger_("excluding audio group "+i+" as "+s+' does not support codec(s): "'+a.audio+'"')),!Object.keys(o).length){if(this.sourceUpdater_.hasCreatedSourceBuffers()&&!this.sourceUpdater_.canChangeType()){var u=[];if(["video","audio"].forEach(function(e){var t=(pr(n.sourceUpdater_.codecs[e]||"")[0]||{}).type,i=(pr(a[e]||"")[0]||{}).type;t&&i&&t.toLowerCase()!==i.toLowerCase()&&u.push('"'+n.sourceUpdater_.codecs[e]+'" -> "'+a[e]+'"')}),u.length)return void this.blacklistCurrentPlaylist({playlist:this.media(),message:"Codec switching not supported: "+u.join(", ")+".",blacklistDuration:1/0,internal:!0})}return a}t=Object.keys(o).reduce(function(e,t){return e&&(e+=", "),e+=t+' does not support codec(s): "'+o[t].join(",")+'"'},"")+".";this.blacklistCurrentPlaylist({playlist:this.media(),internal:!0,message:t,blacklistDuration:1/0})}else this.blacklistCurrentPlaylist({playlist:this.media(),message:"Could not determine codecs for playlist.",blacklistDuration:1/0})},t.tryToCreateSourceBuffers_=function(){var e;"open"!==this.mediaSource.readyState||this.sourceUpdater_.hasCreatedSourceBuffers()||!this.areMediaTypesKnown_()||(e=this.getCodecsOrExclude_())&&(this.sourceUpdater_.createSourceBuffers(e),e=[e.video,e.audio].filter(Boolean).join(","),this.excludeIncompatibleVariants_(e))},t.excludeUnsupportedVariants_=function(){var n=this,r=this.master().playlists,a=[];Object.keys(r).forEach(function(e){var t,i=r[e];-1===a.indexOf(i.id)&&(a.push(i.id),t=[],!(e=Yu(n.master,i)).audio||yr(e.audio)||gr(e.audio)||t.push("audio codec "+e.audio),!e.video||yr(e.video)||gr(e.video)||t.push("video codec "+e.video),e.text&&"stpp.ttml.im1t"===e.text&&t.push("text codec "+e.text),t.length&&(i.excludeUntil=1/0,n.logger_("excluding "+i.id+" for unsupported: "+t.join(", "))))})},t.excludeIncompatibleVariants_=function(e){var r=this,a=[],s=this.master().playlists,e=Xu(pr(e)),o=Ku(e),u=e.video&&pr(e.video)[0]||null,l=e.audio&&pr(e.audio)[0]||null;Object.keys(s).forEach(function(e){var t,i,n=s[e];-1===a.indexOf(n.id)&&n.excludeUntil!==1/0&&(a.push(n.id),t=[],i=Yu(r.masterPlaylistLoader_.master,n),e=Ku(i),(i.audio||i.video)&&(e!==o&&t.push('codec count "'+e+'" !== "'+o+'"'),r.sourceUpdater_.canChangeType()||(e=i.video&&pr(i.video)[0]||null,i=i.audio&&pr(i.audio)[0]||null,e&&u&&e.type.toLowerCase()!==u.type.toLowerCase()&&t.push('video codec "'+e.type+'" !== "'+u.type+'"'),i&&l&&i.type.toLowerCase()!==l.type.toLowerCase()&&t.push('audio codec "'+i.type+'" !== "'+l.type+'"')),t.length&&(n.excludeUntil=1/0,r.logger_("blacklisting "+n.id+": "+t.join(" && ")))))})},t.updateAdCues_=function(e){var t=0,i=this.seekable();i.length&&(t=i.start(0)),function(e,t,i){if(void 0===i&&(i=0),e.segments)for(var n=i,r=0;r<e.segments.length;r++){var a,s,o,u=e.segments[r];if(o=o||function(e,t){for(var i=e.cues,n=0;n<i.length;n++){var r=i[n];if(t>=r.adStartTime&&t<=r.adEndTime)return r}return null}(t,n+u.duration/2)){if("cueIn"in u){o.endTime=n,o.adEndTime=n,n+=u.duration,o=null;continue}if(n<o.endTime){n+=u.duration;continue}o.endTime+=u.duration}else"cueOut"in u&&((o=new window.VTTCue(n,n+u.duration,u.cueOut)).adStartTime=n,o.adEndTime=n+parseFloat(u.cueOut),t.addCue(o)),"cueOutCont"in u&&(a=(s=u.cueOutCont.split("/").map(parseFloat))[0],s=s[1],(o=new window.VTTCue(n,n+u.duration,"")).adStartTime=n-a,o.adEndTime=o.adStartTime+s,t.addCue(o));n+=u.duration}}(e,this.cueTagsTrack_,t)},t.goalBufferLength=function(){var e=this.tech_.currentTime(),t=Sl.GOAL_BUFFER_LENGTH,i=Sl.GOAL_BUFFER_LENGTH_RATE,n=Math.max(t,Sl.MAX_GOAL_BUFFER_LENGTH);return Math.min(t+e*i,n)},t.bufferLowWaterLine=function(){var e=this.tech_.currentTime(),t=Sl.BUFFER_LOW_WATER_LINE,i=Sl.BUFFER_LOW_WATER_LINE_RATE,n=Math.max(t,Sl.MAX_BUFFER_LOW_WATER_LINE),r=Math.max(t,Sl.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE);return Math.min(t+e*i,this.experimentalBufferBasedABR?r:n)},t.bufferHighWaterLine=function(){return Sl.BUFFER_HIGH_WATER_LINE},e}(tr.EventTarget),_c=["seeking","seeked","pause","playing","error"],bc=function(){function e(e){var i=this;this.masterPlaylistController_=e.masterPlaylistController,this.tech_=e.tech,this.seekable=e.seekable,this.allowSeeksWithinUnsafeLiveWindow=e.allowSeeksWithinUnsafeLiveWindow,this.liveRangeSafeTimeDelta=e.liveRangeSafeTimeDelta,this.media=e.media,this.consecutiveUpdates=0,this.lastRecordedTime=null,this.timer_=null,this.checkCurrentTimeTimeout_=null,this.logger_=Oo("PlaybackWatcher"),this.logger_("initialize");function t(){return i.monitorCurrentTime_()}function n(){return i.monitorCurrentTime_()}function r(){return i.techWaiting_()}function a(){return i.cancelTimer_()}var s=this.masterPlaylistController_,o=["main","subtitle","audio"],u={};o.forEach(function(e){u[e]={reset:function(){return i.resetSegmentDownloads_(e)},updateend:function(){return i.checkSegmentDownloads_(e)}},s[e+"SegmentLoader_"].on("appendsdone",u[e].updateend),s[e+"SegmentLoader_"].on("playlistupdate",u[e].reset),i.tech_.on(["seeked","seeking"],u[e].reset)});function l(t){["main","audio"].forEach(function(e){s[e+"SegmentLoader_"][t]("appended",i.seekingAppendCheck_)})}this.seekingAppendCheck_=function(){i.fixesBadSeeks_()&&(i.consecutiveUpdates=0,i.lastRecordedTime=i.tech_.currentTime(),l("off"))},this.clearSeekingAppendCheck_=function(){return l("off")},this.watchForBadSeeking_=function(){i.clearSeekingAppendCheck_(),l("on")},this.tech_.on("seeked",this.clearSeekingAppendCheck_),this.tech_.on("seeking",this.watchForBadSeeking_),this.tech_.on("waiting",r),this.tech_.on(_c,a),this.tech_.on("canplay",n),this.tech_.one("play",t),this.dispose=function(){i.clearSeekingAppendCheck_(),i.logger_("dispose"),i.tech_.off("waiting",r),i.tech_.off(_c,a),i.tech_.off("canplay",n),i.tech_.off("play",t),i.tech_.off("seeking",i.watchForBadSeeking_),i.tech_.off("seeked",i.clearSeekingAppendCheck_),o.forEach(function(e){s[e+"SegmentLoader_"].off("appendsdone",u[e].updateend),s[e+"SegmentLoader_"].off("playlistupdate",u[e].reset),i.tech_.off(["seeked","seeking"],u[e].reset)}),i.checkCurrentTimeTimeout_&&window.clearTimeout(i.checkCurrentTimeTimeout_),i.cancelTimer_()}}var t=e.prototype;return t.monitorCurrentTime_=function(){this.checkCurrentTime_(),this.checkCurrentTimeTimeout_&&window.clearTimeout(this.checkCurrentTimeTimeout_),this.checkCurrentTimeTimeout_=window.setTimeout(this.monitorCurrentTime_.bind(this),250)},t.resetSegmentDownloads_=function(e){var t=this.masterPlaylistController_[e+"SegmentLoader_"];0<this[e+"StalledDownloads_"]&&this.logger_("resetting possible stalled download count for "+e+" loader"),this[e+"StalledDownloads_"]=0,this[e+"Buffered_"]=t.buffered_()},t.checkSegmentDownloads_=function(e){var t=this.masterPlaylistController_,i=t[e+"SegmentLoader_"],n=i.buffered_(),r=function(e,t){if(e===t)return!1;if(!e&&t||!t&&e)return!0;
4720if(e.length!==t.length)return!0;for(var i=0;i<e.length;i++)if(e.start(i)!==t.start(i)||e.end(i)!==t.end(i))return!0;return!1}(this[e+"Buffered_"],n);this[e+"Buffered_"]=n,r?this.resetSegmentDownloads_(e):(this[e+"StalledDownloads_"]++,this.logger_("found #"+this[e+"StalledDownloads_"]+" "+e+" appends that did not increase buffer (possible stalled download)",{playlistId:i.playlist_&&i.playlist_.id,buffered:Bo(n)}),this[e+"StalledDownloads_"]<10||(this.logger_(e+" loader stalled download exclusion"),this.resetSegmentDownloads_(e),this.tech_.trigger({type:"usage",name:"vhs-"+e+"-download-exclusion"}),"subtitle"!==e&&t.blacklistCurrentPlaylist({message:"Excessive "+e+" segment downloading detected."},1/0)))},t.checkCurrentTime_=function(){if(!this.tech_.paused()&&!this.tech_.seeking()){var e=this.tech_.currentTime(),t=this.tech_.buffered();if(this.lastRecordedTime===e&&(!t.length||e+.1>=t.end(t.length-1)))return this.techWaiting_();5<=this.consecutiveUpdates&&e===this.lastRecordedTime?(this.consecutiveUpdates++,this.waiting_()):e===this.lastRecordedTime?this.consecutiveUpdates++:(this.consecutiveUpdates=0,this.lastRecordedTime=e)}},t.cancelTimer_=function(){this.consecutiveUpdates=0,this.timer_&&(this.logger_("cancelTimer_"),clearTimeout(this.timer_)),this.timer_=null},t.fixesBadSeeks_=function(){if(!this.tech_.seeking())return!1;var e,t=this.seekable(),i=this.tech_.currentTime();if(this.afterSeekableWindow_(t,i,this.media(),this.allowSeeksWithinUnsafeLiveWindow)&&(e=t.end(t.length-1)),"undefined"!=typeof(e=this.beforeSeekableWindow_(t,i)?(a=t.start(0))+(a===t.end(0)?0:.1):e))return this.logger_("Trying to seek outside of seekable at time "+i+" with seekable range "+Uo(t)+". Seeking to "+e+"."),this.tech_.setCurrentTime(e),!0;for(var n=this.masterPlaylistController_.sourceUpdater_,r=this.tech_.buffered(),a=n.audioBuffer?n.audioBuffered():null,t=n.videoBuffer?n.videoBuffered():null,n=this.media(),s=n.partTargetDuration||2*(n.targetDuration-hl),o=[a,t],u=0;u<o.length;u++)if(o[u])if(jo(o[u],i)<s)return!1;r=No(r,i);return 0!==r.length&&(e=r.start(0)+.1,this.logger_("Buffered region starts ("+r.start(0)+")  just beyond seek point ("+i+"). Seeking to "+e+"."),this.tech_.setCurrentTime(e),!0)},t.waiting_=function(){var e,t;this.techWaiting_()||(e=this.tech_.currentTime(),t=this.tech_.buffered(),(t=Mo(t,e)).length&&e+3<=t.end(0)&&(this.cancelTimer_(),this.tech_.setCurrentTime(e),this.logger_("Stopped at "+e+" while inside a buffered region ["+t.start(0)+" -> "+t.end(0)+"]. Attempting to resume playback by seeking to the current time."),this.tech_.trigger({type:"usage",name:"vhs-unknown-waiting"}),this.tech_.trigger({type:"usage",name:"hls-unknown-waiting"})))},t.techWaiting_=function(){var e=this.seekable(),t=this.tech_.currentTime();if(this.tech_.seeking()||null!==this.timer_)return!0;if(this.beforeSeekableWindow_(e,t)){var i=e.end(e.length-1);return this.logger_("Fell out of live window at time "+t+". Seeking to live point (seekable end) "+i),this.cancelTimer_(),this.tech_.setCurrentTime(i),this.tech_.trigger({type:"usage",name:"vhs-live-resync"}),this.tech_.trigger({type:"usage",name:"hls-live-resync"}),!0}e=this.tech_.vhs.masterPlaylistController_.sourceUpdater_,i=this.tech_.buffered();if(this.videoUnderflow_({audioBuffered:e.audioBuffered(),videoBuffered:e.videoBuffered(),currentTime:t}))return this.cancelTimer_(),this.tech_.setCurrentTime(t),this.tech_.trigger({type:"usage",name:"vhs-video-underflow"}),this.tech_.trigger({type:"usage",name:"hls-video-underflow"}),!0;e=No(i,t);if(0<e.length){i=e.start(0)-t;return this.logger_("Stopped at "+t+", setting timer for "+i+", seeking to "+e.start(0)),this.cancelTimer_(),this.timer_=setTimeout(this.skipTheGap_.bind(this),1e3*i,t),!0}return!1},t.afterSeekableWindow_=function(e,t,i,n){if(void 0===n&&(n=!1),!e.length)return!1;var r=e.end(e.length-1)+.1;return(r=!i.endList&&n?e.end(e.length-1)+3*i.targetDuration:r)<t},t.beforeSeekableWindow_=function(e,t){return!!(e.length&&0<e.start(0)&&t<e.start(0)-this.liveRangeSafeTimeDelta)},t.videoUnderflow_=function(e){var t,i,n=e.videoBuffered,r=e.audioBuffered,a=e.currentTime;
4720if(n)return n.length&&r.length?(i=Mo(n,a-3),e=Mo(n,a),(r=Mo(r,a)).length&&!e.length&&i.length&&(t={start:i.end(0),end:r.end(0)})):No(n,a).length||(t=this.gapFromVideoUnderflow_(n,a)),!!t&&(this.logger_("Encountered a gap in video from "+t.start+" to "+t.end+". Seeking to current time "+a),!0)},t.skipTheGap_=function(e){var t=this.tech_.buffered(),i=this.tech_.currentTime(),t=No(t,i);this.cancelTimer_(),0!==t.length&&i===e&&(this.logger_("skipTheGap_:","currentTime:",i,"scheduled currentTime:",e,"nextRange start:",t.start(0)),this.tech_.setCurrentTime(t.start(0)+hl),this.tech_.trigger({type:"usage",name:"vhs-gap-skip"}),this.tech_.trigger({type:"usage",name:"hls-gap-skip"}))},t.gapFromVideoUnderflow_=function(e,t){for(var i=function(e){if(e.length<2)return tr.createTimeRanges();for(var t=[],i=1;i<e.length;i++){var n=e.end(i-1),r=e.start(i);t.push([n,r])}return tr.createTimeRanges(t)}(e),n=0;n<i.length;n++){var r=i.start(n),a=i.end(n);if(t-r<4&&2<t-r)return{start:r,end:a}}return null},e}(),Tc={errorInterval:30,getSource:function(e){return e(this.tech({IWillNotUseThisInPlugins:!0}).currentSource_||this.currentSource())}},Sc={PlaylistLoader:yl,Playlist:fl,utils:zt,STANDARD_PLAYLIST_SELECTOR:ar,INITIAL_PLAYLIST_SELECTOR:function(){var t=this,e=this.playlists.master.playlists.filter(fl.isEnabled);return Ju(e,Zu),e.filter(function(e){return!!Yu(t.playlists.master,e).video})[0]||null},lastBandwidthSelector:ar,movingAverageBandwidthSelector:function(t){var i=-1,n=-1;if(t<0||1<t)throw new Error("Moving average bandwidth decay must be between 0 and 1.");return function(){var e=this.useDevicePixelRatio&&window.devicePixelRatio||1;return i<0&&(i=this.systemBandwidth,n=this.systemBandwidth),0<this.systemBandwidth&&this.systemBandwidth!==n&&(i=t*this.systemBandwidth+(1-t)*i,n=this.systemBandwidth),el(this.playlists.master,i,parseInt($u(this.tech_.el(),"width"),10)*e,parseInt($u(this.tech_.el(),"height"),10)*e,this.limitRenditionByPlayerDimensions,this.masterPlaylistController_)}},comparePlaylistBandwidth:Zu,comparePlaylistResolution:function(e,t){var i,n;return(i=(i=e.attributes.RESOLUTION&&e.attributes.RESOLUTION.width?e.attributes.RESOLUTION.width:i)||window.Number.MAX_VALUE)===(n=(n=t.attributes.RESOLUTION&&t.attributes.RESOLUTION.width?t.attributes.RESOLUTION.width:n)||window.Number.MAX_VALUE)&&e.attributes.BANDWIDTH&&t.attributes.BANDWIDTH?e.attributes.BANDWIDTH-t.attributes.BANDWIDTH:i-n},xhr:mu()};Object.keys(Sl).forEach(function(t){Object.defineProperty(Sc,t,{get:function(){return tr.log.warn("using Vhs."+t+" is UNSAFE be sure you know what you are doing"),Sl[t]},set:function(e){tr.log.warn("using Vhs."+t+" is UNSAFE be sure you know what you are doing"),"number"!=typeof e||e<0?tr.log.warn("value of Vhs."+t+" must be greater than or equal to 0"):Sl[t]=e}})});function wc(e,t){for(var i=t.media(),n=-1,r=0;r<e.length;r++)if(e[r].id===i.id){n=r;break}e.selectedIndex_=n,e.trigger({selectedIndex:n,type:"change"})}var Ec="videojs-vhs";Sc.canPlaySource=function(){return tr.log.warn("HLS is no longer a tech. Please remove it from your player's techOrder.")};function kc(e){var n=e.player,t=e.sourceKeySystems,i=e.audioMedia,e=e.mainPlaylists;if(!n.eme.initializeMediaKeys)return Promise.resolve();var r,e=(e=e=i?e.concat([i]):e,r=Object.keys(t),e.reduce(function(e,n){if(!n.contentProtection)return e;var t=r.reduce(function(e,t){var i=n.contentProtection[t];return i&&i.pssh&&(e[t]={pssh:i.pssh}),e},{});return Object.keys(t).length&&e.push(t),e},[])),a=[],s=[];return e.forEach(function(e){s.push(new Promise(function(e,t){n.tech_.one("keysessioncreated",e)})),a.push(new Promise(function(t,i){n.eme.initializeMediaKeys({keySystems:e},function(e){e?i(e):t()})}))}),Promise.race([Promise.all(a),Promise.race(s)])}function Cc(e){var t=e.player;return!!(e=function(e,t,i){if(!e)return e;var n={};t&&t.attributes&&t.attributes.CODECS&&(n=Xu(pr(t.attributes.CODECS))),i&&i.attributes&&i.attributes.CODECS&&(n.audio=i.attributes.CODECS);var r,a=mr(n.video),s=mr(n.audio),o={};for(r in e)o[r]={},s&&(o[r].audioContentType=s),a&&(o[r].videoContentType=a),t.contentProtection&&t.contentProtection[r]&&t.contentProtection[r].pssh&&(o[r].pssh=t.contentProtection[r].pssh),"string"==typeof e[r]&&(o[r].url=e[r]);return tr.mergeOptions(e,o)}(e.sourceKeySystems,e.media,e.audioMedia))&&(!((t.currentSource().keySystems=e)&&!t.eme)||(tr.log.warn("DRM encrypted source cannot be decrypted without a DRM plugin"),!1))}function Ic(){if(!window.localStorage)return null;var e=window.localStorage.getItem(Ec);if(!e)return null;try{return JSON.parse(e)}catch(e){return null}}Sc.supportsNativeHls=function(){if(!document||!document.createElement)return!1;var t=document.createElement("video");if(!tr.getTech("Html5").isSupported())return!1;return["application/vnd.apple.mpegurl","audio/mpegurl","audio/x-mpegurl","application/x-mpegurl","video/x-mpegurl","video/mpegurl","application/mpegurl"].some(function(e){return/maybe|probably/i.test(t.canPlayType(e))})}(),Sc.supportsNativeDash=!!(document&&document.createElement&&tr.getTech("Html5").isSupported())&&/maybe|probably/i.test(document.createElement("video").canPlayType("application/d
4720ash+xml")),Sc.supportsTypeNatively=function(e){return"hls"===e?Sc.supportsNativeHls:"dash"===e&&Sc.supportsNativeDash},Sc.isSupported=function(){return tr.log.warn("HLS is no longer a tech. Please remove it from your player's techOrder.")};var xc=function(r){function e(e,t,i){var n=r.call(this,t,tr.mergeOptions(i.hls,i.vhs))||this;if(i.hls&&Object.keys(i.hls).length&&tr.log.warn("Using hls options is deprecated. Use vhs instead."),"number"==typeof i.initialBandwidth&&(n.options_.bandwidth=i.initialBandwidth),n.logger_=Oo("VhsHandler"),t.options_&&t.options_.playerId&&((i=tr(t.options_.playerId)).hasOwnProperty("hls")||Object.defineProperty(i,"hls",{get:function(){return tr.log.warn("player.hls is deprecated. Use player.tech().vhs instead."),t.trigger({type:"usage",name:"hls-player-access"}),ft(n)},configurable:!0}),i.hasOwnProperty("vhs")||Object.defineProperty(i,"vhs",{get:function(){return tr.log.warn("player.vhs is deprecated. Use player.tech().vhs instead."),t.trigger({type:"usage",name:"vhs-player-access"}),ft(n)},configurable:!0}),i.hasOwnProperty("dash")||Object.defineProperty(i,"dash",{get:function(){return tr.log.warn("player.dash is deprecated. Use player.tech().vhs instead."),ft(n)},configurable:!0}),n.player_=i),n.tech_=t,n.source_=e,n.stats={},n.ignoreNextSeekingEvent_=!1,n.setOptions_(),n.options_.overrideNative&&t.overrideNativeAudioTracks&&t.overrideNativeVideoTracks)t.overrideNativeAudioTracks(!0),t.overrideNativeVideoTracks(!0);else if(n.options_.overrideNative&&(t.featuresNativeVideoTracks||t.featuresNativeAudioTracks))throw new Error("Overriding native HLS requires emulated tracks. See https://git.io/vMpjB");return n.on(document,["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"],function(e){var t=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;t&&t.contains(n.tech_.el())?n.masterPlaylistController_.fastQualityChange_():n.masterPlaylistController_.checkABR_()}),n.on(n.tech_,"seeking",function(){this.ignoreNextSeekingEvent_?this.ignoreNextSeekingEvent_=!1:this.setCurrentTime(this.tech_.currentTime())}),n.on(n.tech_,"error",function(){this.tech_.error()&&this.masterPlaylistController_&&this.masterPlaylistController_.pauseLoading()}),n.on(n.tech_,"play",n.play),n}mt(e,r);var t=e.prototype;return t.setOptions_=function(){var e,t=this;this.options_.withCredentials=this.options_.withCredentials||!1,this.options_.handleManifestRedirects=!1!==this.options_.handleManifestRedirects,this.options_.limitRenditionByPlayerDimensions=!1!==this.options_.limitRenditionByPlayerDimensions,this.options_.useDevicePixelRatio=this.options_.useDevicePixelRatio||!1,this.options_.smoothQualityChange=this.options_.smoothQualityChange||!1,this.options_.useBandwidthFromLocalStorage="undefined"!=typeof this.source_.useBandwidthFromLocalStorage?this.source_.useBandwidthFromLocalStorage:this.options_.useBandwidthFromLocalStorage||!1,this.options_.useNetworkInformationApi=this.options_.useNetworkInformationApi||!1,this.options_.customTagParsers=this.options_.customTagParsers||[],this.options_.customTagMappers=this.options_.customTagMappers||[],this.options_.cacheEncryptionKeys=this.options_.cacheEncryptionKeys||!1,"number"!=typeof this.options_.blacklistDuration&&(this.options_.blacklistDuration=300),"number"!=typeof this.options_.bandwidth&&this.options_.useBandwidthFromLocalStorage&&((e=Ic())&&e.bandwidth&&(this.options_.bandwidth=e.bandwidth,this.tech_.trigger({type:"usage",name:"vhs-bandwidth-from-local-storage"}),this.tech_.trigger({type:"usage",name:"hls-bandwidth-from-local-storage"})),e&&e.throughput&&(this.options_.throughput=e.throughput,this.tech_.trigger({type:"usage",name:"vhs-throughput-from-local-storage"}),this.tech_.trigger({type:"usage",name:"hls-throughput-from-local-storage"}))),"number"!=typeof this.options_.bandwidth&&(this.options_.bandwidth=Sl.INITIAL_BANDWIDTH),this.options_.enableLowInitialPlaylist=this.options_.enableLowInitialPlaylist&&this.options_.bandwidth===Sl.INITIAL_BANDWIDTH,["withCredentials","useDevicePixelRatio","limitRenditionByPlayerDimensions","bandwidth","smoothQualityChange","customTagParsers","customTagMappers","handleManifestRedirects","cacheEncryptionKeys","playlistSelector","initialPlaylistSelector","experimentalBufferBasedABR","liveRangeSafeTimeDelta","experimentalLLHLS","useNetworkInformationApi","experimentalExactManifestTimings","experimentalLeastPixelDiffSelector"].forEach(function(e){"undefined"!=typeof t.source_[e]&&(t.options_[e]=t.source_[e])}),this.limitRenditionByPlayerDimensions=this.options_.limitRenditionByPlayerDimensions,this.useDevicePixelRatio=this.options_.useDevicePixelRatio},t.src=function(e,t){var n=this;e&&(this.setOptions_(),this.options_.src=0===(e=this.source_.src).toLowerCase().indexOf("data:application/vnd.videojs.vhs+json,")?JSON.parse(e.substring(e.indexOf(",")+1)):e,this.options_.tech=this.tech_,this.options_.externVhs=Sc,this.options_.sourceType=vr(t),this.options_.seekTo=function(e){n.tech_.setCurrentTime(e)},this.options_.smoothQualityChange&&tr.log.warn("smoothQualityChange is deprecated and will be removed in the next major version"),this.masterPlaylistController_=new vc(this.options_),t=tr.mergeOptions({liveRangeSafeTimeDelta:.1},this.options_,{seekable:function(){return n.seekable()},media:function(){return n.masterPlaylistController_.media()},masterPlaylistController:this.masterPlaylistController_}),this.playbackWatcher_=new bc(t),this.masterPlaylistController_.on("error",function(){var e=tr.players[n.tech_.options_.playerId],t=n.masterPlaylistController_.error;"object"!=typeof t||t.code?"string"==typeof t&&(t={message:t,code:3}):t.code=3,e.error(t)}
4720),t=this.options_.experimentalBufferBasedABR?Sc.movingAverageBandwidthSelector(.55):Sc.STANDARD_PLAYLIST_SELECTOR,this.masterPlaylistController_.selectPlaylist=(this.selectPlaylist||t).bind(this),this.masterPlaylistController_.selectInitialPlaylist=Sc.INITIAL_PLAYLIST_SELECTOR.bind(this),this.playlists=this.masterPlaylistController_.masterPlaylistLoader_,this.mediaSource=this.masterPlaylistController_.mediaSource,Object.defineProperties(this,{selectPlaylist:{get:function(){return this.masterPlaylistController_.selectPlaylist},set:function(e){this.masterPlaylistController_.selectPlaylist=e.bind(this)}},throughput:{get:function(){return this.masterPlaylistController_.mainSegmentLoader_.throughput.rate},set:function(e){this.masterPlaylistController_.mainSegmentLoader_.throughput.rate=e,this.masterPlaylistController_.mainSegmentLoader_.throughput.count=1}},bandwidth:{get:function(){var e=this.masterPlaylistController_.mainSegmentLoader_.bandwidth,t=window.navigator.connection||window.navigator.mozConnection||window.navigator.webkitConnection;return e=this.options_.useNetworkInformationApi&&t?1e7<=(t=1e3*t.downlink*1e3)&&1e7<=e?Math.max(e,t):t:e},set:function(e){this.masterPlaylistController_.mainSegmentLoader_.bandwidth=e,this.masterPlaylistController_.mainSegmentLoader_.throughput={rate:0,count:0}}},systemBandwidth:{get:function(){var e=1/(this.bandwidth||1),t=0<this.throughput?1/this.throughput:0;return Math.floor(1/(e+t))},set:function(){tr.log.error('The "systemBandwidth" property is read-only')}}}),this.options_.bandwidth&&(this.bandwidth=this.options_.bandwidth),this.options_.throughput&&(this.throughput=this.options_.throughput),Object.defineProperties(this.stats,{bandwidth:{get:function(){return n.bandwidth||0},enumerable:!0},mediaRequests:{get:function(){return n.masterPlaylistController_.mediaRequests_()||0},enumerable:!0},mediaRequestsAborted:{get:function(){return n.masterPlaylistController_.mediaRequestsAborted_()||0},enumerable:!0},mediaRequestsTimedout:{get:function(){return n.masterPlaylistController_.mediaRequestsTimedout_()||0},enumerable:!0},mediaRequestsErrored:{get:function(){return n.masterPlaylistController_.mediaRequestsErrored_()||0},enumerable:!0},mediaTransferDuration:{get:function(){return n.masterPlaylistController_.mediaTransferDuration_()||0},enumerable:!0},mediaBytesTransferred:{get:function(){return n.masterPlaylistController_.mediaBytesTransferred_()||0},enumerable:!0},mediaSecondsLoaded:{get:function(){return n.masterPlaylistController_.mediaSecondsLoaded_()||0},enumerable:!0},mediaAppends:{get:function(){return n.masterPlaylistController_.mediaAppends_()||0},enumerable:!0},mainAppendsToLoadedData:{get:function(){return n.masterPlaylistController_.mainAppendsToLoadedData_()||0},enumerable:!0},audioAppendsToLoadedData:{get:function(){return n.masterPlaylistController_.audioAppendsToLoadedData_()||0},enumerable:!0},appendsToLoadedData:{get:function(){return n.masterPlaylistController_.appendsToLoadedData_()||0},enumerable:!0},timeToLoadedData:{get:function(){return n.masterPlaylistController_.timeToLoadedData_()||0},enumerable:!0},buffered:{get:function(){return Bo(n.tech_.buffered())},enumerable:!0},currentTime:{get:function(){return n.tech_.currentTime()},enumerable:!0},currentSource:{get:function(){return n.tech_.currentSource_},enumerable:!0},currentTech:{get:function(){return n.tech_.name_},enumerable:!0},duration:{get:function(){return n.tech_.duration()},enumerable:!0},master:{get:function(){return n.playlists.master},enumerable:!0},playerDimensions:{get:function(){return n.tech_.currentDimensions()},enumerable:!0},seekable:{get:function(){return Bo(n.tech_.seekable())},enumerable:!0},timestamp:{get:function(){return Date.now()},enumerable:!0},videoPlaybackQuality:{get:function(){return n.tech_.getVideoPlaybackQuality()},enumerable:!0}}),this.tech_.one("canplay",this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_)),this.tech_.on("bandwidthupdate",function(){n.options_.useBandwidthFromLocalStorage&&function(e){if(!window.localStorage)return;var t=(t=Ic())?tr.mergeOptions(t,e):e;try{window.localStorage.setItem(Ec,JSON.stringify(t))}catch(e){return}}({bandwidth:n.bandwidth,throughput:Math.round(n.throughput)})}),this.masterPlaylistController_.on("selectedinitialmedia",function(){var i;(i=n).representations=function(){var e=i.masterPlaylistController_.master(),e=nu(e)?i.masterPlaylistController_.getAudioTrackPlaylists_():e.playlists;return e?e.filter(function(e){return!$o(e)}
4720).map(function(e,t){return new zl(i,e,e.id)}):[]}}),this.masterPlaylistController_.sourceUpdater_.on("createdsourcebuffers",function(){n.setupEme_()}),this.on(this.masterPlaylistController_,"progress",function(){this.tech_.trigger("progress")}),this.on(this.masterPlaylistController_,"firstplay",function(){this.ignoreNextSeekingEvent_=!0}),this.setupQualityLevels_(),this.tech_.el()&&(this.mediaSourceUrl_=window.URL.createObjectURL(this.masterPlaylistController_.mediaSource),this.tech_.src(this.mediaSourceUrl_)))},t.createKeySessions_=function(){var t=this,e=this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader;this.logger_("waiting for EME key session creation"),kc({player:this.player_,sourceKeySystems:this.source_.keySystems,audioMedia:e&&e.media(),mainPlaylists:this.playlists.master.playlists}).then(function(){t.logger_("created EME key session"),t.masterPlaylistController_.sourceUpdater_.initializedEme()}).catch(function(e){t.logger_("error while creating EME key session",e),t.player_.error({message:"Failed to initialize media keys for EME",code:3})})},t.handleWaitingForKey_=function(){this.logger_("waitingforkey fired, attempting to create any new key sessions"),this.createKeySessions_()},t.setupEme_=function(){var t=this,e=this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader,e=Cc({player:this.player_,sourceKeySystems:this.source_.keySystems,media:this.playlists.media(),audioMedia:e&&e.media()});this.player_.tech_.on("keystatuschange",function(e){"output-restricted"===e.status&&t.masterPlaylistController_.blacklistCurrentPlaylist({playlist:t.masterPlaylistController_.media(),message:"DRM keystatus changed to "+e.status+". Playlist will fail to play. Check for HDCP content.",blacklistDuration:1/0})}),this.handleWaitingForKey_=this.handleWaitingForKey_.bind(this),this.player_.tech_.on("waitingforkey",this.handleWaitingForKey_),11!==tr.browser.IE_VERSION&&e?this.createKeySessions_():this.masterPlaylistController_.sourceUpdater_.initializedEme()},t.setupQualityLevels_=function(){var i=this,e=tr.players[this.tech_.options_.playerId];
4720e&&e.qualityLevels&&!this.qualityLevels_&&(this.qualityLevels_=e.qualityLevels(),this.masterPlaylistController_.on("selectedinitialmedia",function(){var t,e;t=i.qualityLevels_,(e=i).representations().forEach(function(e){t.addQualityLevel(e)}),wc(t,e.playlists)}),this.playlists.on("mediachange",function(){wc(i.qualityLevels_,i.playlists)}))},e.version=function(){return{"@videojs/http-streaming":"2.13.1","mux.js":"6.0.1","mpd-parser":"0.21.0","m3u8-parser":"4.7.0","aes-decrypter":"3.1.2"}},t.version=function(){return this.constructor.version()},t.canChangeType=function(){return sc.canChangeType()},t.play=function(){this.masterPlaylistController_.play()},t.setCurrentTime=function(e){this.masterPlaylistController_.setCurrentTime(e)},t.duration=function(){return this.masterPlaylistController_.duration()},t.seekable=function(){return this.masterPlaylistController_.seekable()},t.dispose=function(){this.playbackWatcher_&&this.playbackWatcher_.dispose(),this.masterPlaylistController_&&this.masterPlaylistController_.dispose(),this.qualityLevels_&&this.qualityLevels_.dispose(),this.player_&&(delete this.player_.vhs,delete this.player_.dash,delete this.player_.hls),this.tech_&&this.tech_.vhs&&delete this.tech_.vhs,this.tech_&&delete this.tech_.hls,this.mediaSourceUrl_&&window.URL.revokeObjectURL&&(window.URL.revokeObjectURL(this.mediaSourceUrl_),this.mediaSourceUrl_=null),this.tech_&&this.tech_.off("waitingforkey",this.handleWaitingForKey_),r.prototype.dispose.call(this)},t.convertToProgramTime=function(e,t){return wu({playlist:this.masterPlaylistController_.media(),time:e,callback:t})},t.seekToProgramTime=function(e,t,i,n){return void 0===i&&(i=!0),void 0===n&&(n=2),Eu({programTime:e,playlist:this.masterPlaylistController_.media(),retryCount:n,pauseAfterSeek:i,seekTo:this.options_.seekTo,tech:this.options_.tech,callback:t})},e}(tr.getComponent("Component")),Ac={name:"videojs-http-streaming",VERSION:"2.13.1",canHandleSource:function(e,t){t=tr.mergeOptions(tr.options,t=void 0===t?{}:t);return Ac.canPlayType(e.type,t)},handleSource:function(e,t,i){i=tr.mergeOptions(tr.options,i=void 0===i?{}:i);return t.vhs=new xc(e,t,i),tr.hasOwnProperty("hls")||Object.defineProperty(t,"hls",{get:function(){return tr.log.warn("player.tech().hls is deprecated. Use player.tech().vhs instead."),t.vhs},configurable:!0}),t.vhs.xhr=mu(),t.vhs.src(e.src,e.type),t.vhs},canPlayType:function(e,t){var i=tr.mergeOptions(tr.options,t=void 0===t?{}:t),t=i.vhs,t=(t=void 0===t?{}:t).overrideNative,t=void 0===t?!tr.browser.IS_ANY_SAFARI:t,i=i.hls,i=(i=void 0===i?{}:i).overrideNative,i=void 0!==i&&i,e=vr(e);return e&&(!Sc.supportsTypeNatively(e)||i||t)?"maybe":""}};return gr("avc1.4d400d,mp4a.40.2")&&tr.getTech("Html5").registerSourceHandler(Ac,0),tr.VhsHandler=xc,Object.defineProperty(tr,"HlsHandler",{get:function(){return tr.log.warn("videojs.HlsHandler is deprecated. Use videojs.VhsHandler instead."),xc},configurable:!0}),tr.VhsSourceHandler=Ac,Object.defineProperty(tr,"HlsSourceHandler",{get:function(){return tr.log.warn("videojs.HlsSourceHandler is deprecated. Use videojs.VhsSourceHandler instead."),Ac},configurable:!0}),tr.Vhs=Sc,Object.defineProperty(tr,"Hls",{get:function(){return tr.log.warn("videojs.Hls is deprecated. Use videojs.Vhs instead."),Sc},configurable:!0}),tr.use||(tr.registerComponent("Hls",Sc),tr.registerComponent("Vhs",Sc)),tr.options.vhs=tr.options.vhs||{},tr.options.hls=tr.options.hls||{},tr.getPlugin&&tr.getPlugin("reloadSourceOnError")||(tr.registerPlugin||tr.plugin)("reloadSourceOnError",function(e){Xl(this,e)}),tr});
4721 !function(){!function(a){var b=a&&a.videojs;b&&(b.CDN_VERSION="7.18.1")}(window)}();
4722// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/admin/lib/videojs-vr/videojs-vr.js?ver=1 
4723/*! @name videojs-vr @version 1.7.2 @license Apache-2.0 */
4724(function (global, factory) {
4725	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window'), require('global/document'), require('video.js')) :
4726	typeof define === 'function' && define.amd ? define(['global/window', 'global/document', 'video.js'], factory) :
4727	(global = global || self, global.videojsVr = factory(global.window, global.document, global.videojs));
4728  }(this, (function (window$1, document$1, videojs) { 'use strict';
4729  
4730	window$1 = window$1 && window$1.hasOwnProperty('default') ? window$1['default'] : window$1;
4731	document$1 = document$1 && document$1.hasOwnProperty('default') ? document$1['default'] : document$1;
4732	videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
4733  
4734	function _assertThisInitialized(self) {
4735	  if (self === void 0) {
4736		throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
4737	  }
4738  
4739	  return self;
4740	}
4741  
4742	var assertThisInitialized = _assertThisInitialized;
4743  
4744	function _inheritsLoose(subClass, superClass) {
4745	  subClass.prototype = Object.create(superClass.prototype);
4746	  subClass.prototype.constructor = subClass;
4747	  subClass.__proto__ = superClass;
4748	}
4749  
4750	var inheritsLoose = _inheritsLoose;
4751  
4752	var version = "1.7.2";
4753  
4754	var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
4755  
4756	function unwrapExports (x) {
4757		return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
4758	}
4759  
4760	function createCommonjsModule(fn, module) {
4761		return module = { exports: {} }, fn(module, module.exports), module.exports;
4762	}
4763  
4764	var webvrPolyfill = createCommonjsModule(function (module, exports) {
4765	/**
4766	 * @license
4767	 * webvr-polyfill
4768	 * Copyright (c) 2015-2017 Google
4769	 * Licensed under the Apache License, Version 2.0 (the "License");
4770	 * you may not use this file except in compliance with the License.
4771	 * You may obtain a copy of the License at
4772	 *
4773	 * http://www.apache.org/licenses/LICENSE-2.0
4774	 *
4775	 * Unless required by applicable law or agreed to in writing, software
4776	 * distributed under the License is distributed on an "AS IS" BASIS,
4777	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4778	 * See the License for the specific language governing permissions and
4779	 * limitations under the License.
4780	 */
4781  
4782	/**
4783	 * @license
4784	 * cardboard-vr-display
4785	 * Copyright (c) 2015-2017 Google
4786	 * Licensed under the Apache License, Version 2.0 (the "License");
4787	 * you may not use this file except in compliance with the License.
4788	 * You may obtain a copy of the License at
4789	 *
4790	 * http://www.apache.org/licenses/LICENSE-2.0
4791	 *
4792	 * Unless required by applicable law or agreed to in writing, software
4793	 * distributed under the License is distributed on an "AS IS" BASIS,
4794	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4795	 * See the License for the specific language governing permissions and
4796	 * limitations under the License.
4797	 */
4798  
4799	/**
4800	 * @license
4801	 * webvr-polyfill-dpdb 
4802	 * Copyright (c) 2017 Google
4803	 * Licensed under the Apache License, Version 2.0 (the "License");
4804	 * you may not use this file except in compliance with the License.
4805	 * You may obtain a copy of the License at
4806	 *
4807	 * http://www.apache.org/licenses/LICENSE-2.0
4808	 *
4809	 * Unless required by applicable law or agreed to in writing, software
4810	 * distributed under the License is distributed on an "AS IS" BASIS,
4811	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4812	 * See the License for the specific language governing permissions and
4813	 * limitations under the License.
4814	 */
4815  
4816	/**
4817	 * @license
4818	 * wglu-preserve-state
4819	 * Copyright (c) 2016, Brandon Jones.
4820	 *
4821	 * Permission is hereby granted, free of charge, to any person obtaining a copy
4822	 * of this software and associated documentation files (the "Software"), to deal
4823	 * in the Software without restriction, including without limitation the rights
4824	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4825	 * copies of the Software, and to permit persons to whom the Software is
4826	 * furnished to do so, subject to the following conditions:
4827	 *
4828	 * The above copyright notice and this permission notice shall be included in
4829	 * all copies or substantial portions of the Software.
4830	 *
4831	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4832	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4833	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4834	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4835	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4836	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4837	 * THE SOFTWARE.
4838	 */
4839  
4840	/**
4841	 * @license
4842	 * nosleep.js
4843	 * Copyright (c) 2017, Rich Tibbett
4844	 *
4845	 * Permission is hereby granted, free of charge, to any person obtaining a copy
4846	 * of this software and associated documentation files (the "Software"), to deal
4847	 * in the Software without restriction, including without limitation the rights
4848	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4849	 * copies of the Software, and to permit persons to whom the Software is
4850	 * furnished to do so, subject to the following conditions:
4851	 *
4852	 * The above copyright notice and this permission notice shall be included in
4853	 * all copies or substantial portions of the Software.
4854	 *
4855	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4856	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4857	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4858	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4859	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4860	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4861	 * THE SOFTWARE.
4862	 */
4863  
4864	(function (global, factory) {
4865		 module.exports = factory() ;
4866	}(commonjsGlobal, (function () {
4867	var commonjsGlobal$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {};
4868  
4869  
4870  
4871	function unwrapExports (x) {
4872		return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
4873	}
4874  
4875	function createCommonjsModule(fn, module) {
4876		return module = { exports: {} }, fn(module, module.exports), module.exports;
4877	}
4878  
4879	var race = function race(promises) {
4880	  if (Promise.race) {
4881		return Promise.race(promises);
4882	  }
4883	  return new Promise(function (resolve, reject) {
4884		for (var i = 0; i < promises.length; i++) {
4885		  promises[i].then(resolve, reject);
4886		}
4887	  });
4888	};
4889  
4890	var isMobile = function isMobile() {
4891	  return (/Android/i.test(navigator.userAgent) || /iPhone|iPad|iPod/i.test(navigator.userAgent)
4892	  );
4893	};
4894	var copyArray = function copyArray(source, dest) {
4895	  for (var i = 0, n = source.length; i < n; i++) {
4896		dest[i] = source[i];
4897	  }
4898	};
4899	var extend = function extend(dest, src) {
4900	  for (var key in src) {
4901		if (src.hasOwnProperty(key)) {
4902		  dest[key] = src[key];
4903		}
4904	  }
4905	  return dest;
4906	};
4907  
4908	var cardboardVrDisplay = createCommonjsModule(function (module, exports
4908) {
4909	/**
4910	 * @license
4911	 * cardboard-vr-display
4912	 * Copyright (c) 2015-2017 Google
4913	 * Licensed under the Apache License, Version 2.0 (the "License");
4914	 * you may not use this file except in compliance with the License.
4915	 * You may obtain a copy of the License at
4916	 *
4917	 * http://www.apache.org/licenses/LICENSE-2.0
4918	 *
4919	 * Unless required by applicable law or agreed to in writing, software
4920	 * distributed under the License is distributed on an "AS IS" BASIS,
4921	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4922	 * See the License for the specific language governing permissions and
4923	 * limitations under the License.
4924	 */
4925	/**
4926	 * @license
4927	 * gl-preserve-state
4928	 * Copyright (c) 2016, Brandon Jones.
4929	 *
4930	 * Permission is hereby granted, free of charge, to any person obtaining a copy
4931	 * of this software and associated documentation files (the "Software"), to deal
4932	 * in the Software without restriction, including without limitation the rights
4933	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4934	 * copies of the Software, and to permit persons to whom the Software is
4935	 * furnished to do so, subject to the following conditions:
4936	 *
4937	 * The above copyright notice and this permission notice shall be included in
4938	 * all copies or substantial portions of the Software.
4939	 *
4940	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4941	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4942	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4943	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4944	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4945	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4946	 * THE SOFTWARE.
4947	 */
4948	/**
4949	 * @license
4950	 * webvr-polyfill-dpdb
4951	 * Copyright (c) 2015-2017 Google
4952	 * Licensed under the Apache License, Version 2.0 (the "License");
4953	 * you may not use this file except in compliance with the License.
4954	 * You may obtain a copy of the License at
4955	 *
4956	 * http://www.apache.org/licenses/LICENSE-2.0
4957	 *
4958	 * Unless required by applicable law or agreed to in writing, software
4959	 * distributed under the License is distributed on an "AS IS" BASIS,
4960	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4961	 * See the License for the specific language governing permissions and
4962	 * limitations under the License.
4963	 */
4964	/**
4965	 * @license
4966	 * nosleep.js
4967	 * Copyright (c) 2017, Rich Tibbett
4968	 *
4969	 * Permission is hereby granted, free of charge, to any person obtaining a copy
4970	 * of this software and associated documentation files (the "Software"), to deal
4971	 * in the Software without restriction, including without limitation the rights
4972	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4973	 * copies of the Software, and to permit persons to whom the Software is
4974	 * furnished to do so, subject to the following conditions:
4975	 *
4976	 * The above copyright notice and this permission notice shall be included in
4977	 * all copies or substantial portions of the Software.
4978	 *
4979	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4980	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4981	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4982	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4983	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4984	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4985	 * THE SOFTWARE.
4986	 */
4987	(function (global, factory) {
4988		module.exports = factory();
4989	}(commonjsGlobal$1, (function () { var classCallCheck = function (instance, Constructor) {
4990	  if (!(instance instanceof Constructor)) {
4991		throw new TypeError("Cannot call a class as a function");
4992	  }
4993	};
4994	var createClass = function () {
4995	  function defineProperties(target, props) {
4996		for (var i = 0; i < props.length; i++) {
4997		  var descriptor = props[i];
4998		  descriptor.enumerable = descriptor.enumerable || false;
4999		  descriptor.configurable = true;
5000		  if ("value" in descriptor) descriptor.writable = true;
vendor: 26,977 bytes, lines 5001-5755
5001		  Object.defineProperty(target, descriptor.key, descriptor);
5002		}
5003	  }
5004	  return function (Constructor, protoProps, staticProps) {
5005		if (protoProps) defineProperties(Constructor.prototype, protoProps);
5006		if (staticProps) defineProperties(Constructor, staticProps);
5007		return Constructor;
5008	  };
5009	}();
5010	var slicedToArray = function () {
5011	  function sliceIterator(arr, i) {
5012		var _arr = [];
5013		var _n = true;
5014		var _d = false;
5015		var _e = undefined;
5016		try {
5017		  for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
5018			_arr.push(_s.value);
5019			if (i && _arr.length === i) break;
5020		  }
5021		} catch (err) {
5022		  _d = true;
5023		  _e = err;
5024		} finally {
5025		  try {
5026			if (!_n && _i["return"]) _i["return"]();
5027		  } finally {
5028			if (_d) throw _e;
5029		  }
5030		}
5031		return _arr;
5032	  }
5033	  return function (arr, i) {
5034		if (Array.isArray(arr)) {
5035		  return arr;
5036		} else if (Symbol.iterator in Object(arr)) {
5037		  return sliceIterator(arr, i);
5038		} else {
5039		  throw new TypeError("Invalid attempt to destructure non-iterable instance");
5040		}
5041	  };
5042	}();
5043	var MIN_TIMESTEP = 0.001;
5044	var MAX_TIMESTEP = 1;
5045	var base64 = function base64(mimeType, _base) {
5046	  return 'data:' + mimeType + ';base64,' + _base;
5047	};
5048	var lerp = function lerp(a, b, t) {
5049	  return a + (b - a) * t;
5050	};
5051	var isIOS = function () {
5052	  var isIOS = /iPad|iPhone|iPod/.test(navigator.platform);
5053	  return function () {
5054		return isIOS;
5055	  };
5056	}();
5057	var isWebViewAndroid = function () {
5058	  var isWebViewAndroid = navigator.userAgent.indexOf('Version') !== -1 && navigator.userAgent.indexOf('Android') !== -1 && navigator.userAgent.indexOf('Chrome') !== -1;
5059	  return function () {
5060		return isWebViewAndroid;
5061	  };
5062	}();
5063	var isSafari = function () {
5064	  var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
5065	  return function () {
5066		return isSafari;
5067	  };
5068	}();
5069	var isFirefoxAndroid = function () {
5070	  var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 && navigator.userAgent.indexOf('Android') !== -1;
5071	  return function () {
5072		return isFirefoxAndroid;
5073	  };
5074	}();
5075	var getChromeVersion = function () {
5076	  var match = navigator.userAgent.match(/.*Chrome\/([0-9]+)/);
5077	  var value = match ? parseInt(match[1], 10) : null;
5078	  return function () {
5079		return value;
5080	  };
5081	}();
5082	var isChromeWithoutDeviceMotion = function () {
5083	  var value = false;
5084	  if (getChromeVersion() === 65) {
5085		var match = navigator.userAgent.match(/.*Chrome\/([0-9\.]*)/);
5086		if (match) {
5087		  var _match$1$split = match[1].split('.'),
5088			  _match$1$split2 = slicedToArray(_match$1$split, 4),
5089			  major = _match$1$split2[0],
5090			  minor = _match$1$split2[1],
5091			  branch = _match$1$split2[2],
5092			  build = _match$1$split2[3];
5093		  value = parseInt(branch, 10) === 3325 && parseInt(build, 10) < 148;
5094		}
5095	  }
5096	  return function () {
5097		return value;
5098	  };
5099	}();
5100	var isR7 = function () {
5101	  var isR7 = navigator.userAgent.indexOf('R7 Build') !== -1;
5102	  return function () {
5103		return isR7;
5104	  };
5105	}();
5106	var isLandscapeMode = function isLandscapeMode() {
5107	  var rtn = window.orientation == 90 || window.orientation == -90;
5108	  return isR7() ? !rtn : rtn;
5109	};
5110	var isTimestampDeltaValid = function isTimestampDeltaValid(timestampDeltaS) {
5111	  if (isNaN(timestampDeltaS)) {
5112		return false;
5113	  }
5114	  if (timestampDeltaS <= MIN_TIMESTEP) {
5115		return false;
5116	  }
5117	  if (timestampDeltaS > MAX_TIMESTEP) {
5118		return false;
5119	  }
5120	  return true;
5121	};
5122	var getScreenWidth = function getScreenWidth() {
5123	  return Math.max(window.screen.width, window.screen.height) * window.devicePixelRatio;
5124	};
5125	var getScreenHeight = function getScreenHeight() {
5126	  return Math.min(window.screen.width, window.screen.height) * window.devicePixelRatio;
5127	};
5128	var requestFullscreen = function requestFullscreen(element) {
5129	  if (isWebViewAndroid()) {
5130		return false;
5131	  }
5132	  if (element.requestFullscreen) {
5133		element.requestFullscreen();
5134	  } else if (element.webkitRequestFullscreen) {
5135		element.webkitRequestFullscreen();
5136	  } else if (element.mozRequestFullScreen) {
5137		element.mozRequestFullScreen();
5138	  } else if (element.msRequestFullscreen) {
5139		element.msRequestFullscreen();
5140	  } else {
5141		return false;
5142	  }
5143	  return true;
5144	};
5145	var exitFullscreen = function exitFullscreen() {
5146	  if (document.exitFullscreen) {
5147		document.exitFullscreen();
5148	  } else if (document.webkitExitFullscreen) {
5149		document.webkitExitFullscreen();
5150	  } else if (document.mozCancelFullScreen) {
5151		document.mozCancelFullScreen();
5152	  } else if (document.msExitFullscreen) {
5153		document.msExitFullscreen();
5154	  } else {
5155		return false;
5156	  }
5157	  return true;
5158	};
5159	var getFullscreenElement = function getFullscreenElement() {
5160	  return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
5161	};
5162	var linkProgram = function linkProgram(gl, vertexSource, fragmentSource, attribLocationMap) {
5163	  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
5164	  gl.shaderSource(vertexShader, vertexSource);
5165	  gl.compileShader(vertexShader);
5166	  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
5167	  gl.shaderSource(fragmentShader, fragmentSource);
5168	  gl.compileShader(fragmentShader);
5169	  var program = gl.createProgram();
5170	  gl.attachShader(program, vertexShader);
5171	  gl.attachShader(program, fragmentShader);
5172	  for (var attribName in attribLocationMap) {
5173		gl.bindAttribLocation(program, attribLocationMap[attribName], attribName);
5174	  }gl.linkProgram(program);
5175	  gl.deleteShader(vertexShader);
5176	  gl.deleteShader(fragmentShader);
5177	  return program;
5178	};
5179	var getProgramUniforms = function getProgramUniforms(gl, program) {
5180	  var uniforms = {};
5181	  var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
5182	  var uniformName = '';
5183	  for (var i = 0; i < uniformCount; i++) {
5184		var uniformInfo = gl.getActiveUniform(program, i);
5185		uniformName = uniformInfo.name.replace('[0]', '');
5186		uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
5187	  }
5188	  return uniforms;
5189	};
5190	var orthoMatrix = function orthoMatrix(out, left, right, bottom, top, near, far) {
5191	  var lr = 1 / (left - right),
5192		  bt = 1 / (bottom - top),
5193		  nf = 1 / (near - far);
5194	  out[0] = -2 * lr;
5195	  out[1] = 0;
5196	  out[2] = 0;
5197	  out[3] = 0;
5198	  out[4] = 0;
5199	  out[5] = -2 * bt;
5200	  out[6] = 0;
5201	  out[7] = 0;
5202	  out[8] = 0;
5203	  out[9] = 0;
5204	  out[10] = 2 * nf;
5205	  out[11] = 0;
5206	  out[12] = (left + right) * lr;
5207	  out[13] = (top + bottom) * bt;
5208	  out[14] = (far + near) * nf;
5209	  out[15] = 1;
5210	  return out;
5211	};
5212	var isMobile = function isMobile() {
5213	  var check = false;
5214	  (function (a) {
5215		if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
5216	  })(navigator.userAgent || navigator.vendor || window.opera);
5217	  return check;
5218	};
5219	var extend = function extend(dest, src) {
5220	  for (var key in src) {
5221		if (src.hasOwnProperty(key)) {
5222		  dest[key] = src[key];
5223		}
5224	  }
5225	  return dest;
5226	};
5227	var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) {
5228	  if (isIOS()) {
5229		var width = canvas.style.width;
5230		var height = canvas.style.height;
5231		canvas.style.width = parseInt(width) + 1 + 'px';
5232		canvas.style.height = parseInt(height) + 'px';
5233		setTimeout(function () {
5234		  canvas.style.width = width;
5235		  canvas.style.height = height;
5236		}, 100);
5237	  }
5238	  window.canvas = canvas;
5239	};
5240	var frameDataFromPose = function () {
5241	  var piOver180 = Math.PI / 180.0;
5242	  var rad45 = Math.PI * 0.25;
5243	  function mat4_perspectiveFromFieldOfView(out, fov, near, far) {
5244		var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45),
5245			downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45),
5246			leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45),
5247			rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45),
5248			xScale = 2.0 / (leftTan + rightTan),
5249			yScale = 2.0 / (upTan + downTan);
5250		out[0] = xScale;
5251		out[1] = 0.0;
5252		out[2] = 0.0;
5253		out[3] = 0.0;
5254		out[4] = 0.0;
5255		out[5] = yScale;
5256		out[6] = 0.0;
5257		out[7] = 0.0;
5258		out[8] = -((leftTan - rightTan) * xScale * 0.5);
5259		out[9] = (upTan - downTan) * yScale * 0.5;
5260		out[10] = far / (near - far);
5261		out[11] = -1.0;
5262		out[12] = 0.0;
5263		out[13] = 0.0;
5264		out[14] = far * near / (near - far);
5265		out[15] = 0.0;
5266		return out;
5267	  }
5268	  function mat4_fromRotationTranslation(out, q, v) {
5269		var x = q[0],
5270			y = q[1],
5271			z = q[2],
5272			w = q[3],
5273			x2 = x + x,
5274			y2 = y + y,
5275			z2 = z + z,
5276			xx = x * x2,
5277			xy = x * y2,
5278			xz = x * z2,
5279			yy = y * y2,
5280			yz = y * z2,
5281			zz = z * z2,
5282			wx = w * x2,
5283			wy = w * y2,
5284			wz = w * z2;
5285		out[0] = 1 - (yy + zz);
5286		out[1] = xy + wz;
5287		out[2] = xz - wy;
5288		out[3] = 0;
5289		out[4] = xy - wz;
5290		out[5] = 1 - (xx + zz);
5291		out[6] = yz + wx;
5292		out[7] = 0;
5293		out[8] = xz + wy;
5294		out[9] = yz - wx;
5295		out[10] = 1 - (xx + yy);
5296		out[11] = 0;
5297		out[12] = v[0];
5298		out[13] = v[1];
5299		out[14] = v[2];
5300		out[15] = 1;
5301		return out;
5302	  }
5303	  function mat4_translate(out, a, v) {
5304		var x = v[0],
5305			y = v[1],
5306			z = v[2],
5307			a00,
5308			a01,
5309			a02,
5310			a03,
5311			a10,
5312			a11,
5313			a12,
5314			a13,
5315			a20,
5316			a21,
5317			a22,
5318			a23;
5319		if (a === out) {
5320		  out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
5321		  out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
5322		  out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
5323		  out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
5324		} else {
5325		  a00 = a[0];a01 = a[1];a02 = a[2];a03 = a[3];
5326		  a10 = a[4];a11 = a[5];a12 = a[6];a13 = a[7];
5327		  a20 = a[8];a21 = a[9];a22 = a[10];a23 = a[11];
5328		  out[0] = a00;out[1] = a01;out[2] = a02;out[3] = a03;
5329		  out[4] = a10;out[5] = a11;out[6] = a12;out[7] = a13;
5330		  out[8] = a20;out[9] = a21;out[10] = a22;out[11] = a23;
5331		  out[12] = a00 * x + a10 * y + a20 * z + a[12];
5332		  out[13] = a01 * x + a11 * y + a21 * z + a[13];
5333		  out[14] = a02 * x + a12 * y + a22 * z + a[14];
5334		  out[15] = a03 * x + a13 * y + a23 * z + a[15];
5335		}
5336		return out;
5337	  }
5338	  function mat4_invert(out, a) {
5339		var a00 = a[0],
5340			a01 = a[1],
5341			a02 = a[2],
5342			a03 = a[3],
5343			a10 = a[4],
5344			a11 = a[5],
5345			a12 = a[6],
5346			a13 = a[7],
5347			a20 = a[8],
5348			a21 = a[9],
5349			a22 = a[10],
5350			a23 = a[11],
5351			a30 = a[12],
5352			a31 = a[13],
5353			a32 = a[14],
5354			a33 = a[15],
5355			b00 = a00 * a11 - a01 * a10,
5356			b01 = a00 * a12 - a02 * a10,
5357			b02 = a00 * a13 - a03 * a10,
5358			b03 = a01 * a12 - a02 * a11,
5359			b04 = a01 * a13 - a03 * a11,
5360			b05 = a02 * a13 - a03 * a12,
5361			b06 = a20 * a31 - a21 * a30,
5362			b07 = a20 * a32 - a22 * a30,
5363			b08 = a20 * a33 - a23 * a30,
5364			b09 = a21 * a32 - a22 * a31,
5365			b10 = a21 * a33 - a23 * a31,
5366			b11 = a22 * a33 - a23 * a32,
5367		det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
5368		if (!det) {
5369		  return null;
5370		}
5371		det = 1.0 / det;
5372		out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
5373		out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
5374		out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
5375		out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
5376		out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
5377		out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
5378		out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
5379		out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
5380		out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
5381		out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
5382		out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
5383		out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
5384		out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
5385		out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
5386		out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
5387		out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
5388		return out;
5389	  }
5390	  var defaultOrientation = new Float32Array([0, 0, 0, 1]);
5391	  var defaultPosition = new Float32Array([0, 0, 0]);
5392	  function updateEyeMatrices(projection, view, pose, fov, offset, vrDisplay) {
5393		mat4_perspectiveFromFieldOfView(projection, fov || null, vrDisplay.depthNear, vrDisplay.depthFar);
5394		var orientation = pose.orientation || defaultOrientation;
5395		var position = pose.position || defaultPosition;
5396		mat4_fromRotationTranslation(view, orientation, position);
5397		if (offset) mat4_translate(view, view, offset);
5398		mat4_invert(view, view);
5399	  }
5400	  return function (frameData, pose, vrDisplay) {
5401		if (!frameData || !pose) return false;
5402		frameData.pose = pose;
5403		frameData.timestamp = pose.timestamp;
5404		updateEyeMatrices(frameData.leftProjectionMatrix, frameData.leftViewMatrix, pose, vrDisplay._getFieldOfView("left"), vrDisplay._getEyeOffset("left"), vrDisplay);
5405		updateEyeMatrices(frameData.rightProjectionMatrix, frameData.rightViewMatrix, pose, vrDisplay._getFieldOfView("right"), vrDisplay._getEyeOffset("right"), vrDisplay);
5406		return true;
5407	  };
5408	}();
5409	var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() {
5410	  var isFramed = window.self !== window.top;
5411	  var refOrigin = getOriginFromUrl(document.referrer);
5412	  var thisOrigin = getOriginFromUrl(window.location.href);
5413	  return isFramed && refOrigin !== thisOrigin;
5414	};
5415	var getOriginFromUrl = function getOriginFromUrl(url) {
5416	  var domainIdx;
5417	  var protoSepIdx = url.indexOf("://");
5418	  if (protoSepIdx !== -1) {
5419		domainIdx = protoSepIdx + 3;
5420	  } else {
5421		domainIdx = 0;
5422	  }
5423	  var domainEndIdx = url.indexOf('/', domainIdx);
5424	  if (domainEndIdx === -1) {
5425		domainEndIdx = url.length;
5426	  }
5427	  return url.substring(0, domainEndIdx);
5428	};
5429	var getQuaternionAngle = function getQuaternionAngle(quat) {
5430	  if (quat.w > 1) {
5431		console.warn('getQuaternionAngle: w > 1');
5432		return 0;
5433	  }
5434	  var angle = 2 * Math.acos(quat.w);
5435	  return angle;
5436	};
5437	var warnOnce = function () {
5438	  var observedWarnings = {};
5439	  return function (key, message) {
5440		if (observedWarnings[key] === undefined) {
5441		  console.warn('webvr-polyfill: ' + message);
5442		  observedWarnings[key] = true;
5443		}
5444	  };
5445	}();
5446	var deprecateWarning = function deprecateWarning(deprecated, suggested) {
5447	  var alternative = suggested ? 'Please use ' + suggested + ' instead.' : '';
5448	  warnOnce(deprecated, deprecated + ' has been deprecated. ' + 'This may not work on native WebVR displays. ' + alternative);
5449	};
5450	function WGLUPreserveGLState(gl, bindings, callback) {
5451	  if (!bindings) {
5452		callback(gl);
5453		return;
5454	  }
5455	  var boundValues = [];
5456	  var activeTexture = null;
5457	  for (var i = 0; i < bindings.length; ++i) {
5458		var binding = bindings[i];
5459		switch (binding) {
5460		  case gl.TEXTURE_BINDING_2D:
5461		  case gl.TEXTURE_BINDING_CUBE_MAP:
5462			var textureUnit = bindings[++i];
5463			if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) {
5464			  console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit");
5465			  boundValues.push(null, null);
5466			  break;
5467			}
5468			if (!activeTexture) {
5469			  activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
5470			}
5471			gl.activeTexture(textureUnit);
5472			boundValues.push(gl.getParameter(binding), null);
5473			break;
5474		  case gl.ACTIVE_TEXTURE:
5475			activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
5476			boundValues.push(null);
5477			break;
5478		  default:
5479			boundValues.push(gl.getParameter(binding));
5480			break;
5481		}
5482	  }
5483	  callback(gl);
5484	  for (var i = 0; i < bindings.length; ++i) {
5485		var binding = bindings[i];
5486		var boundValue = boundValues[i];
5487		switch (binding) {
5488		  case gl.ACTIVE_TEXTURE:
5489			break;
5490		  case gl.ARRAY_BUFFER_BINDING:
5491			gl.bindBuffer(gl.ARRAY_BUFFER, boundValue);
5492			break;
5493		  case gl.COLOR_CLEAR_VALUE:
5494			gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
5495			break;
5496		  case gl.COLOR_WRITEMASK:
5497			gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
5498			break;
5499		  case gl.CURRENT_PROGRAM:
5500			gl.useProgram(boundValue);
5501			break;
5502		  case gl.ELEMENT_ARRAY_BUFFER_BINDING:
5503			gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue);
5504			break;
5505		  case gl.FRAMEBUFFER_BINDING:
5506			gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue);
5507			break;
5508		  case gl.RENDERBUFFER_BINDING:
5509			gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue);
5510			break;
5511		  case gl.TEXTURE_BINDING_2D:
5512			var textureUnit = bindings[++i];
5513			if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
5514			  break;
5515			gl.activeTexture(textureUnit);
5516			gl.bindTexture(gl.TEXTURE_2D, boundValue);
5517			break;
5518		  case gl.TEXTURE_BINDING_CUBE_MAP:
5519			var textureUnit = bindings[++i];
5520			if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
5521			  break;
5522			gl.activeTexture(textureUnit);
5523			gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue);
5524			break;
5525		  case gl.VIEWPORT:
5526			gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
5527			break;
5528		  case gl.BLEND:
5529		  case gl.CULL_FACE:
5530		  case gl.DEPTH_TEST:
5531		  case gl.SCISSOR_TEST:
5532		  case gl.STENCIL_TEST:
5533			if (boundValue) {
5534			  gl.enable(binding);
5535			} else {
5536			  gl.disable(binding);
5537			}
5538			break;
5539		  default:
5540			console.log("No GL restore behavior for 0x" + binding.toString(16));
5541			break;
5542		}
5543		if (activeTexture) {
5544		  gl.activeTexture(activeTexture);
5545		}
5546	  }
5547	}
5548	var glPreserveState = WGLUPreserveGLState;
5549	var distortionVS = ['attribute vec2 position;', 'attribute vec3 texCoord;', 'varying vec2 vTexCoord;', 'uniform vec4 viewportOffsetScale[2];', 'void main() {', '  vec4 viewport = viewportOffsetScale[int(texCoord.z)];', '  vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;', '  gl_Position = vec4( position, 1.0, 1.0 );', '}'].join('\n');
5550	var distortionFS = ['precision mediump float;', 'uniform sampler2D diffuse;', 'varying vec2 vTexCoord;', 'void main() {', '  gl_FragColor = texture2D(diffuse, vTexCoord);', '}'].join('\n');
5551	function CardboardDistorter(gl, cardboardUI, bufferScale, dirtySubmitFrameBindings) {
5552	  this.gl = gl;
5553	  this.cardboardUI = cardboardUI;
5554	  this.bufferScale = bufferScale;
5555	  this.dirtySubmitFrameBindings = dirtySubmitFrameBindings;
5556	  this.ctxAttribs = gl.getContextAttributes();
5557	  this.meshWidth = 20;
5558	  this.meshHeight = 20;
5559	  this.bufferWidth = gl.drawingBufferWidth;
5560	  this.bufferHeight = gl.drawingBufferHeight;
5561	  this.realBindFramebuffer = gl.bindFramebuffer;
5562	  this.realEnable = gl.enable;
5563	  this.realDisable = gl.disable;
5564	  this.realColorMask = gl.colorMask;
5565	  this.realClearColor = gl.clearColor;
5566	  this.realViewport = gl.viewport;
5567	  if (!isIOS()) {
5568		this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width');
5569		this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height');
5570	  }
5571	  this.isPatched = false;
5572	  this.lastBoundFramebuffer = null;
5573	  this.cullFace = false;
5574	  this.depthTest = false;
5575	  this.blend = false;
5576	  this.scissorTest = false;
5577	  this.stencilTest = false;
5578	  this.viewport = [0, 0, 0, 0];
5579	  this.colorMask = [true, true, true, true];
5580	  this.clearColor = [0, 0, 0, 0];
5581	  this.attribs = {
5582		position: 0,
5583		texCoord: 1
5584	  };
5585	  this.program = linkProgram(gl, distortionVS, distortionFS, this.attribs);
5586	  this.uniforms = getProgramUniforms(gl, this.program);
5587	  this.viewportOffsetScale = new Float32Array(8);
5588	  this.setTextureBounds();
5589	  this.vertexBuffer = gl.createBuffer();
5590	  this.indexBuffer = gl.createBuffer();
5591	  this.indexCount = 0;
5592	  this.renderTarget = gl.createTexture();
5593	  this.framebuffer = gl.createFramebuffer();
5594	  this.depthStencilBuffer = null;
5595	  this.depthBuffer = null;
5596	  this.stencilBuffer = null;
5597	  if (this.ctxAttribs.depth && this.ctxAttribs.stencil) {
5598		this.depthStencilBuffer = gl.createRenderbuffer();
5599	  } else if (this.ctxAttribs.depth) {
5600		this.depthBuffer = gl.createRenderbuffer();
5601	  } else if (this.ctxAttribs.stencil) {
5602		this.stencilBuffer = gl.createRenderbuffer();
5603	  }
5604	  this.patch();
5605	  this.onResize();
5606	}
5607	CardboardDistorter.prototype.destroy = function () {
5608	  var gl = this.gl;
5609	  this.unpatch();
5610	  gl.deleteProgram(this.program);
5611	  gl.deleteBuffer(this.vertexBuffer);
5612	  gl.deleteBuffer(this.indexBuffer);
5613	  gl.deleteTexture(this.renderTarget);
5614	  gl.deleteFramebuffer(this.framebuffer);
5615	  if (this.depthStencilBuffer) {
5616		gl.deleteRenderbuffer(this.depthStencilBuffer);
5617	  }
5618	  if (this.depthBuffer) {
5619		gl.deleteRenderbuffer(this.depthBuffer);
5620	  }
5621	  if (this.stencilBuffer) {
5622		gl.deleteRenderbuffer(this.stencilBuffer);
5623	  }
5624	  if (this.cardboardUI) {
5625		this.cardboardUI.destroy();
5626	  }
5627	};
5628	CardboardDistorter.prototype.onResize = function () {
5629	  var gl = this.gl;
5630	  var self = this;
5631	  var glState = [gl.RENDERBUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0];
5632	  glPreserveState(gl, glState, function (gl) {
5633		self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
5634		if (self.scissorTest) {
5635		  self.realDisable.call(gl, gl.SCISSOR_TEST);
5636		}
5637		self.realColorMask.call(gl, true, true, true, true);
5638		self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
5639		self.realClearColor.call(gl, 0, 0, 0, 1);
5640		gl.clear(gl.COLOR_BUFFER_BIT);
5641		self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer);
5642		gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
5643		gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, self.bufferWidth, self.bufferHeight, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null);
5644		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
5645		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
5646		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
5647		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
5648		gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0);
5649		if (self.ctxAttribs.depth && self.ctxAttribs.stencil) {
5650		  gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer);
5651		  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, self.bufferWidth, self.bufferHeight);
5652		  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.depthStencilBuffer);
5653		} else if (self.ctxAttribs.depth) {
5654		  gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer);
5655		  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, self.bufferWidth, self.bufferHeight);
5656		  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, self.depthBuffer);
5657		} else if (self.ctxAttribs.stencil) {
5658		  gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer);
5659		  gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, self.bufferWidth, self.bufferHeight);
5660		  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.stencilBuffer);
5661		}
5662		if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
5663		  console.error('Framebuffer incomplete!');
5664		}
5665		self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
5666		if (self.scissorTest) {
5667		  self.realEnable.call(gl, gl.SCISSOR_TEST);
5668		}
5669		self.realColorMask.apply(gl, self.colorMask);
5670		self.realViewport.apply(gl, self.viewport);
5671		self.realClearColor.apply(gl, self.clearColor);
5672	  });
5673	  if (this.cardboardUI) {
5674		this.cardboardUI.onResize();
5675	  }
5676	};
5677	CardboardDistorter.prototype.patch = function () {
5678	  if (this.isPatched) {
5679		return;
5680	  }
5681	  var self = this;
5682	  var canvas = this.gl.canvas;
5683	  var gl = this.gl;
5684	  if (!isIOS()) {
5685		canvas.width = getScreenWidth() * this.bufferScale;
5686		canvas.height = getScreenHeight() * this.bufferScale;
5687		Object.defineProperty(canvas, 'width', {
5688		  configurable: true,
5689		  enumerable: true,
5690		  get: function get() {
5691			return self.bufferWidth;
5692		  },
5693		  set: function set(value) {
5694			self.bufferWidth = value;
5695			self.realCanvasWidth.set.call(canvas, value);
5696			self.onResize();
5697		  }
5698		});
5699		Object.defineProperty(canvas, 'height', {
5700		  configurable: true,
5701		  enumerable: true,
5702		  get: function get() {
5703			return self.bufferHeight;
5704		  },
5705		  set: function set(value) {
5706			self.bufferHeight = value;
5707			self.realCanvasHeight.set.call(canvas, value);
5708			self.onResize();
5709		  }
5710		});
5711	  }
5712	  this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
5713	  if (this.lastBoundFramebuffer == null) {
5714		this.lastBoundFramebuffer = this.framebuffer;
5715		this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
5716	  }
5717	  this.gl.bindFramebuffer = function (target, framebuffer) {
5718		self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer;
5719		self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer);
5720	  };
5721	  this.cullFace = gl.getParameter(gl.CULL_FACE);
5722	  this.depthTest = gl.getParameter(gl.DEPTH_TEST);
5723	  this.blend = gl.getParameter(gl.BLEND);
5724	  this.scissorTest = gl.getParameter(gl.SCISSOR_TEST);
5725	  this.stencilTest = gl.getParameter(gl.STENCIL_TEST);
5726	  gl.enable = function (pname) {
5727		switch (pname) {
5728		  case gl.CULL_FACE:
5729			self.cullFace = true;break;
5730		  case gl.DEPTH_TEST:
5731			self.depthTest = true;break;
5732		  case gl.BLEND:
5733			self.blend = true;break;
5734		  case gl.SCISSOR_TEST:
5735			self.scissorTest = true;break;
5736		  case gl.STENCIL_TEST:
5737			self.stencilTest = true;break;
5738		}
5739		self.realEnable.call(gl, pname);
5740	  };
5741	  gl.disable = function (pname) {
5742		switch (pname) {
5743		  case gl.CULL_FACE:
5744			self.cullFace = false;break;
5745		  case gl.DEPTH_TEST:
5746			self.depthTest = false;break;
5747		  case gl.BLEND:
5748			self.blend = false;break;
5749		  case gl.SCISSOR_TEST:
5750			self.scissorTest = false;break;
5751		  case gl.STENCIL_TEST:
5752			self.stencilTest = false;break;
5753		}
5754		self.realDisable.call(gl, pname);
5755	  };
vendor: 13,898 bytes, lines 5756-6120
5756	  this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK);
5757	  gl.colorMask = function (r, g, b, a) {
5758		self.colorMask[0] = r;
5759		self.colorMask[1] = g;
5760		self.colorMask[2] = b;
5761		self.colorMask[3] = a;
5762		self.realColorMask.call(gl, r, g, b, a);
5763	  };
5764	  this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
5765	  gl.clearColor = function (r, g, b, a) {
5766		self.clearColor[0] = r;
5767		self.clearColor[1] = g;
5768		self.clearColor[2] = b;
5769		self.clearColor[3] = a;
5770		self.realClearColor.call(gl, r, g, b, a);
5771	  };
5772	  this.viewport = gl.getParameter(gl.VIEWPORT);
5773	  gl.viewport = function (x, y, w, h) {
5774		self.viewport[0] = x;
5775		self.viewport[1] = y;
5776		self.viewport[2] = w;
5777		self.viewport[3] = h;
5778		self.realViewport.call(gl, x, y, w, h);
5779	  };
5780	  this.isPatched = true;
5781	  safariCssSizeWorkaround(canvas);
5782	};
5783	CardboardDistorter.prototype.unpatch = function () {
5784	  if (!this.isPatched) {
5785		return;
5786	  }
5787	  var gl = this.gl;
5788	  var canvas = this.gl.canvas;
5789	  if (!isIOS()) {
5790		Object.defineProperty(canvas, 'width', this.realCanvasWidth);
5791		Object.defineProperty(canvas, 'height', this.realCanvasHeight);
5792	  }
5793	  canvas.width = this.bufferWidth;
5794	  canvas.height = this.bufferHeight;
5795	  gl.bindFramebuffer = this.realBindFramebuffer;
5796	  gl.enable = this.realEnable;
5797	  gl.disable = this.realDisable;
5798	  gl.colorMask = this.realColorMask;
5799	  gl.clearColor = this.realClearColor;
5800	  gl.viewport = this.realViewport;
5801	  if (this.lastBoundFramebuffer == this.framebuffer) {
5802		gl.bindFramebuffer(gl.FRAMEBUFFER, null);
5803	  }
5804	  this.isPatched = false;
5805	  setTimeout(function () {
5806		safariCssSizeWorkaround(canvas);
5807	  }, 1);
5808	};
5809	CardboardDistorter.prototype.setTextureBounds = function (leftBounds, rightBounds) {
5810	  if (!leftBounds) {
5811		leftBounds = [0, 0, 0.5, 1];
5812	  }
5813	  if (!rightBounds) {
5814		rightBounds = [0.5, 0, 0.5, 1];
5815	  }
5816	  this.viewportOffsetScale[0] = leftBounds[0];
5817	  this.viewportOffsetScale[1] = leftBounds[1];
5818	  this.viewportOffsetScale[2] = leftBounds[2];
5819	  this.viewportOffsetScale[3] = leftBounds[3];
5820	  this.viewportOffsetScale[4] = rightBounds[0];
5821	  this.viewportOffsetScale[5] = rightBounds[1];
5822	  this.viewportOffsetScale[6] = rightBounds[2];
5823	  this.viewportOffsetScale[7] = rightBounds[3];
5824	};
5825	CardboardDistorter.prototype.submitFrame = function () {
5826	  var gl = this.gl;
5827	  var self = this;
5828	  var glState = [];
5829	  if (!this.dirtySubmitFrameBindings) {
5830		glState.push(gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0);
5831	  }
5832	  glPreserveState(gl, glState, function (gl) {
5833		self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
5834		if (self.cullFace) {
5835		  self.realDisable.call(gl, gl.CULL_FACE);
5836		}
5837		if (self.depthTest) {
5838		  self.realDisable.call(gl, gl.DEPTH_TEST);
5839		}
5840		if (self.blend) {
5841		  self.realDisable.call(gl, gl.BLEND);
5842		}
5843		if (self.scissorTest) {
5844		  self.realDisable.call(gl, gl.SCISSOR_TEST);
5845		}
5846		if (self.stencilTest) {
5847		  self.realDisable.call(gl, gl.STENCIL_TEST);
5848		}
5849		self.realColorMask.call(gl, true, true, true, true);
5850		self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
5851		if (self.ctxAttribs.alpha || isIOS()) {
5852		  self.realClearColor.call(gl, 0, 0, 0, 1);
5853		  gl.clear(gl.COLOR_BUFFER_BIT);
5854		}
5855		gl.useProgram(self.program);
5856		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
5857		gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
5858		gl.enableVertexAttribArray(self.attribs.position);
5859		gl.enableVertexAttribArray(self.attribs.texCoord);
5860		gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0);
5861		gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8);
5862		gl.activeTexture(gl.TEXTURE0);
5863		gl.uniform1i(self.uniforms.diffuse, 0);
5864		gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
5865		gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale);
5866		gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0);
5867		if (self.cardboardUI) {
5868		  self.cardboardUI.renderNoState();
5869		}
5870		self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer);
5871		if (!self.ctxAttribs.preserveDrawingBuffer) {
5872		  self.realClearColor.call(gl, 0, 0, 0, 0);
5873		  gl.clear(gl.COLOR_BUFFER_BIT);
5874		}
5875		if (!self.dirtySubmitFrameBindings) {
5876		  self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
5877		}
5878		if (self.cullFace) {
5879		  self.realEnable.call(gl, gl.CULL_FACE);
5880		}
5881		if (self.depthTest) {
5882		  self.realEnable.call(gl, gl.DEPTH_TEST);
5883		}
5884		if (self.blend) {
5885		  self.realEnable.call(gl, gl.BLEND);
5886		}
5887		if (self.scissorTest) {
5888		  self.realEnable.call(gl, gl.SCISSOR_TEST);
5889		}
5890		if (self.stencilTest) {
5891		  self.realEnable.call(gl, gl.STENCIL_TEST);
5892		}
5893		self.realColorMask.apply(gl, self.colorMask);
5894		self.realViewport.apply(gl, self.viewport);
5895		if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) {
5896		  self.realClearColor.apply(gl, self.clearColor);
5897		}
5898	  });
5899	  if (isIOS()) {
5900		var canvas = gl.canvas;
5901		if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) {
5902		  self.bufferWidth = canvas.width;
5903		  self.bufferHeight = canvas.height;
5904		  self.onResize();
5905		}
5906	  }
5907	};
5908	CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) {
5909	  var gl = this.gl;
5910	  var self = this;
5911	  var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING];
5912	  glPreserveState(gl, glState, function (gl) {
5913		var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo);
5914		gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
5915		gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
5916		if (!self.indexCount) {
5917		  var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight);
5918		  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
5919		  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
5920		  self.indexCount = indices.length;
5921		}
5922	  });
5923	};
5924	CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) {
5925	  var vertices = new Float32Array(2 * width * height * 5);
5926	  var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles();
5927	  var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles();
5928	  var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum);
5929	  var vidx = 0;
5930	  for (var e = 0; e < 2; e++) {
5931		for (var j = 0; j < height; j++) {
5932		  for (var i = 0; i < width; i++, vidx++) {
5933			var u = i / (width - 1);
5934			var v = j / (height - 1);
5935			var s = u;
5936			var t = v;
5937			var x = lerp(lensFrustum[0], lensFrustum[2], u);
5938			var y = lerp(lensFrustum[3], lensFrustum[1], v);
5939			var d = Math.sqrt(x * x + y * y);
5940			var r = deviceInfo.distortion.distortInverse(d);
5941			var p = x * r / d;
5942			var q = y * r / d;
5943			u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]);
5944			v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]);
5945			u = (viewport.x + u * viewport.width - 0.5) * 2.0;
5946			v = (viewport.y + v * viewport.height - 0.5) * 2.0;
5947			vertices[vidx * 5 + 0] = u;
5948			vertices[vidx * 5 + 1] = v;
5949			vertices[vidx * 5 + 2] = s;
5950			vertices[vidx * 5 + 3] = t;
5951			vertices[vidx * 5 + 4] = e;
5952		  }
5953		}
5954		var w = lensFrustum[2] - lensFrustum[0];
5955		lensFrustum[0] = -(w + lensFrustum[0]);
5956		lensFrustum[2] = w - lensFrustum[2];
5957		w = noLensFrustum[2] - noLensFrustum[0];
5958		noLensFrustum[0] = -(w + noLensFrustum[0]);
5959		noLensFrustum[2] = w - noLensFrustum[2];
5960		viewport.x = 1 - (viewport.x + viewport.width);
5961	  }
5962	  return vertices;
5963	};
5964	CardboardDistorter.prototype.computeMeshIndices_ = function (width, height) {
5965	  var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6);
5966	  var halfwidth = width / 2;
5967	  var halfheight = height / 2;
5968	  var vidx = 0;
5969	  var iidx = 0;
5970	  for (var e = 0; e < 2; e++) {
5971		for (var j = 0; j < height; j++) {
5972		  for (var i = 0; i < width; i++, vidx++) {
5973			if (i == 0 || j == 0) continue;
5974			if (i <= halfwidth == j <= halfheight) {
5975			  indices[iidx++] = vidx;
5976			  indices[iidx++] = vidx - width - 1;
5977			  indices[iidx++] = vidx - width;
5978			  indices[iidx++] = vidx - width - 1;
5979			  indices[iidx++] = vidx;
5980			  indices[iidx++] = vidx - 1;
5981			} else {
5982			  indices[iidx++] = vidx - 1;
5983			  indices[iidx++] = vidx - width;
5984			  indices[iidx++] = vidx;
5985			  indices[iidx++] = vidx - width;
5986			  indices[iidx++] = vidx - 1;
5987			  indices[iidx++] = vidx - width - 1;
5988			}
5989		  }
5990		}
5991	  }
5992	  return indices;
5993	};
5994	CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function (proto, attrName) {
5995	  var descriptor = Object.getOwnPropertyDescriptor(proto, attrName);
5996	  if (descriptor.get === undefined || descriptor.set === undefined) {
5997		descriptor.configurable = true;
5998		descriptor.enumerable = true;
5999		descriptor.get = function () {
6000		  return this.getAttribute(attrName);
6001		};
6002		descriptor.set = function (val) {
6003		  this.setAttribute(attrName, val);
6004		};
6005	  }
6006	  return descriptor;
6007	};
6008	var uiVS = ['attribute vec2 position;', 'uniform mat4 projectionMat;', 'void main() {', '  gl_Position = projectionMat * vec4( position, -1.0, 1.0 );', '}'].join('\n');
6009	var uiFS = ['precision mediump float;', 'uniform vec4 color;', 'void main() {', '  gl_FragColor = color;', '}'].join('\n');
6010	var DEG2RAD = Math.PI / 180.0;
6011	var kAnglePerGearSection = 60;
6012	var kOuterRimEndAngle = 12;
6013	var kInnerRimBeginAngle = 20;
6014	var kOuterRadius = 1;
6015	var kMiddleRadius = 0.75;
6016	var kInnerRadius = 0.3125;
6017	var kCenterLineThicknessDp = 4;
6018	var kButtonWidthDp = 28;
6019	var kTouchSlopFactor = 1.5;
6020	function CardboardUI(gl) {
6021	  this.gl = gl;
6022	  this.attribs = {
6023		position: 0
6024	  };
6025	  this.program = linkProgram(gl, uiVS, uiFS, this.attribs);
6026	  this.uniforms = getProgramUniforms(gl, this.program);
6027	  this.vertexBuffer = gl.createBuffer();
6028	  this.gearOffset = 0;
6029	  this.gearVertexCount = 0;
6030	  this.arrowOffset = 0;
6031	  this.arrowVertexCount = 0;
6032	  this.projMat = new Float32Array(16);
6033	  this.listener = null;
6034	  this.onResize();
6035	}
6036	CardboardUI.prototype.destroy = function () {
6037	  var gl = this.gl;
6038	  if (this.listener) {
6039		gl.canvas.removeEventListener('click', this.listener, false);
6040	  }
6041	  gl.deleteProgram(this.program);
6042	  gl.deleteBuffer(this.vertexBuffer);
6043	};
6044	CardboardUI.prototype.listen = function (optionsCallback, backCallback) {
6045	  var canvas = this.gl.canvas;
6046	  this.listener = function (event) {
6047		var midline = canvas.clientWidth / 2;
6048		var buttonSize = kButtonWidthDp * kTouchSlopFactor;
6049		if (event.clientX > midline - buttonSize && event.clientX < midline + buttonSize && event.clientY > canvas.clientHeight - buttonSize) {
6050		  optionsCallback(event);
6051		}
6052		else if (event.clientX < buttonSize && event.clientY < buttonSize) {
6053			backCallback(event);
6054		  }
6055	  };
6056	  canvas.addEventListener('click', this.listener, false);
6057	};
6058	CardboardUI.prototype.onResize = function () {
6059	  var gl = this.gl;
6060	  var self = this;
6061	  var glState = [gl.ARRAY_BUFFER_BINDING];
6062	  glPreserveState(gl, glState, function (gl) {
6063		var vertices = [];
6064		var midline = gl.drawingBufferWidth / 2;
6065		var physicalPixels = Math.max(screen.width, screen.height) * window.devicePixelRatio;
6066		var scalingRatio = gl.drawingBufferWidth / physicalPixels;
6067		var dps = scalingRatio * window.devicePixelRatio;
6068		var lineWidth = kCenterLineThicknessDp * dps / 2;
6069		var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps;
6070		var buttonScale = kButtonWidthDp * dps / 2;
6071		var buttonBorder = (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps;
6072		vertices.push(midline - lineWidth, buttonSize);
6073		vertices.push(midline - lineWidth, gl.drawingBufferHeight);
6074		vertices.push(midline + lineWidth, buttonSize);
6075		vertices.push(midline + lineWidth, gl.drawingBufferHeight);
6076		self.gearOffset = vertices.length / 2;
6077		function addGearSegment(theta, r) {
6078		  var angle = (90 - theta) * DEG2RAD;
6079		  var x = Math.cos(angle);
6080		  var y = Math.sin(angle);
6081		  vertices.push(kInnerRadius * x * buttonScale + midline, kInnerRadius * y * buttonScale + buttonScale);
6082		  vertices.push(r * x * buttonScale + midline, r * y * buttonScale + buttonScale);
6083		}
6084		for (var i = 0; i <= 6; i++) {
6085		  var segmentTheta = i * kAnglePerGearSection;
6086		  addGearSegment(segmentTheta, kOuterRadius);
6087		  addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius);
6088		  addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius);
6089		  addGearSegment(segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), kMiddleRadius);
6090		  addGearSegment(segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), kOuterRadius);
6091		}
6092		self.gearVertexCount = vertices.length / 2 - self.gearOffset;
6093		self.arrowOffset = vertices.length / 2;
6094		function addArrowVertex(x, y) {
6095		  vertices.push(buttonBorder + x, gl.drawingBufferHeight - buttonBorder - y);
6096		}
6097		var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD);
6098		addArrowVertex(0, buttonScale);
6099		addArrowVertex(buttonScale, 0);
6100		addArrowVertex(buttonScale + angledLineWidth, angledLineWidth);
6101		addArrowVertex(angledLineWidth, buttonScale + angledLineWidth);
6102		addArrowVertex(angledLineWidth, buttonScale - angledLineWidth);
6103		addArrowVertex(0, buttonScale);
6104		addArrowVertex(buttonScale, buttonScale * 2);
6105		addArrowVertex(buttonScale + angledLineWidth, buttonScale * 2 - angledLineWidth);
6106		addArrowVertex(angledLineWidth, buttonScale - angledLineWidth);
6107		addArrowVertex(0, buttonScale);
6108		addArrowVertex(angledLineWidth, buttonScale - lineWidth);
6109		addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth);
6110		addArrowVertex(angledLineWidth, buttonScale + lineWidth);
6111		addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth);
6112		self.arrowVertexCount = vertices.length / 2 - self.arrowOffset;
6113		gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
6114		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
6115	  });
6116	};
6117	CardboardUI.prototype.render = function () {
6118	  var gl = this.gl;
6119	  var self = this;
6120	  var glState = [gl.CULL_FACE, gl.DEPTH_TEST, gl.BLEND, gl.SCISSOR_TEST, gl.STENCIL_TEST, gl.COLOR_WRITEMA
vendor: 18,151 bytes, lines 6120-6650
6120SK, gl.VIEWPORT, gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING];
6121	  glPreserveState(gl, glState, function (gl) {
6122		gl.disable(gl.CULL_FACE);
6123		gl.disable(gl.DEPTH_TEST);
6124		gl.disable(gl.BLEND);
6125		gl.disable(gl.SCISSOR_TEST);
6126		gl.disable(gl.STENCIL_TEST);
6127		gl.colorMask(true, true, true, true);
6128		gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
6129		self.renderNoState();
6130	  });
6131	};
6132	CardboardUI.prototype.renderNoState = function () {
6133	  var gl = this.gl;
6134	  gl.useProgram(this.program);
6135	  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
6136	  gl.enableVertexAttribArray(this.attribs.position);
6137	  gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0);
6138	  gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0);
6139	  orthoMatrix(this.projMat, 0, gl.drawingBufferWidth, 0, gl.drawingBufferHeight, 0.1, 1024.0);
6140	  gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat);
6141	  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
6142	  gl.drawArrays(gl.TRIANGLE_STRIP, this.gearOffset, this.gearVertexCount);
6143	  gl.drawArrays(gl.TRIANGLE_STRIP, this.arrowOffset, this.arrowVertexCount);
6144	};
6145	function Distortion(coefficients) {
6146	  this.coefficients = coefficients;
6147	}
6148	Distortion.prototype.distortInverse = function (radius) {
6149	  var r0 = 0;
6150	  var r1 = 1;
6151	  var dr0 = radius - this.distort(r0);
6152	  while (Math.abs(r1 - r0) > 0.0001             ) {
6153		var dr1 = radius - this.distort(r1);
6154		var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0));
6155		r0 = r1;
6156		r1 = r2;
6157		dr0 = dr1;
6158	  }
6159	  return r1;
6160	};
6161	Distortion.prototype.distort = function (radius) {
6162	  var r2 = radius * radius;
6163	  var ret = 0;
6164	  for (var i = 0; i < this.coefficients.length; i++) {
6165		ret = r2 * (ret + this.coefficients[i]);
6166	  }
6167	  return (ret + 1) * radius;
6168	};
6169	var degToRad = Math.PI / 180;
6170	var radToDeg = 180 / Math.PI;
6171	var Vector3 = function Vector3(x, y, z) {
6172	  this.x = x || 0;
6173	  this.y = y || 0;
6174	  this.z = z || 0;
6175	};
6176	Vector3.prototype = {
6177	  constructor: Vector3,
6178	  set: function set(x, y, z) {
6179		this.x = x;
6180		this.y = y;
6181		this.z = z;
6182		return this;
6183	  },
6184	  copy: function copy(v) {
6185		this.x = v.x;
6186		this.y = v.y;
6187		this.z = v.z;
6188		return this;
6189	  },
6190	  length: function length() {
6191		return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
6192	  },
6193	  normalize: function normalize() {
6194		var scalar = this.length();
6195		if (scalar !== 0) {
6196		  var invScalar = 1 / scalar;
6197		  this.multiplyScalar(invScalar);
6198		} else {
6199		  this.x = 0;
6200		  this.y = 0;
6201		  this.z = 0;
6202		}
6203		return this;
6204	  },
6205	  multiplyScalar: function multiplyScalar(scalar) {
6206		this.x *= scalar;
6207		this.y *= scalar;
6208		this.z *= scalar;
6209	  },
6210	  applyQuaternion: function applyQuaternion(q) {
6211		var x = this.x;
6212		var y = this.y;
6213		var z = this.z;
6214		var qx = q.x;
6215		var qy = q.y;
6216		var qz = q.z;
6217		var qw = q.w;
6218		var ix = qw * x + qy * z - qz * y;
6219		var iy = qw * y + qz * x - qx * z;
6220		var iz = qw * z + qx * y - qy * x;
6221		var iw = -qx * x - qy * y - qz * z;
6222		this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
6223		this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
6224		this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
6225		return this;
6226	  },
6227	  dot: function dot(v) {
6228		return this.x * v.x + this.y * v.y + this.z * v.z;
6229	  },
6230	  crossVectors: function crossVectors(a, b) {
6231		var ax = a.x,
6232			ay = a.y,
6233			az = a.z;
6234		var bx = b.x,
6235			by = b.y,
6236			bz = b.z;
6237		this.x = ay * bz - az * by;
6238		this.y = az * bx - ax * bz;
6239		this.z = ax * by - ay * bx;
6240		return this;
6241	  }
6242	};
6243	var Quaternion = function Quaternion(x, y, z, w) {
6244	  this.x = x || 0;
6245	  this.y = y || 0;
6246	  this.z = z || 0;
6247	  this.w = w !== undefined ? w : 1;
6248	};
6249	Quaternion.prototype = {
6250	  constructor: Quaternion,
6251	  set: function set(x, y, z, w) {
6252		this.x = x;
6253		this.y = y;
6254		this.z = z;
6255		this.w = w;
6256		return this;
6257	  },
6258	  copy: function copy(quaternion) {
6259		this.x = quaternion.x;
6260		this.y = quaternion.y;
6261		this.z = quaternion.z;
6262		this.w = quaternion.w;
6263		return this;
6264	  },
6265	  setFromEulerXYZ: function setFromEulerXYZ(x, y, z) {
6266		var c1 = Math.cos(x / 2);
6267		var c2 = Math.cos(y / 2);
6268		var c3 = Math.cos(z / 2);
6269		var s1 = Math.sin(x / 2);
6270		var s2 = Math.sin(y / 2);
6271		var s3 = Math.sin(z / 2);
6272		this.x = s1 * c2 * c3 + c1 * s2 * s3;
6273		this.y = c1 * s2 * c3 - s1 * c2 * s3;
6274		this.z = c1 * c2 * s3 + s1 * s2 * c3;
6275		this.w = c1 * c2 * c3 - s1 * s2 * s3;
6276		return this;
6277	  },
6278	  setFromEulerYXZ: function setFromEulerYXZ(x, y, z) {
6279		var c1 = Math.cos(x / 2);
6280		var c2 = Math.cos(y / 2);
6281		var c3 = Math.cos(z / 2);
6282		var s1 = Math.sin(x / 2);
6283		var s2 = Math.sin(y / 2);
6284		var s3 = Math.sin(z / 2);
6285		this.x = s1 * c2 * c3 + c1 * s2 * s3;
6286		this.y = c1 * s2 * c3 - s1 * c2 * s3;
6287		this.z = c1 * c2 * s3 - s1 * s2 * c3;
6288		this.w = c1 * c2 * c3 + s1 * s2 * s3;
6289		return this;
6290	  },
6291	  setFromAxisAngle: function setFromAxisAngle(axis, angle) {
6292		var halfAngle = angle / 2,
6293			s = Math.sin(halfAngle);
6294		this.x = axis.x * s;
6295		this.y = axis.y * s;
6296		this.z = axis.z * s;
6297		this.w = Math.cos(halfAngle);
6298		return this;
6299	  },
6300	  multiply: function multiply(q) {
6301		return this.multiplyQuaternions(this, q);
6302	  },
6303	  multiplyQuaternions: function multiplyQuaternions(a, b) {
6304		var qax = a.x,
6305			qay = a.y,
6306			qaz = a.z,
6307			qaw = a.w;
6308		var qbx = b.x,
6309			qby = b.y,
6310			qbz = b.z,
6311			qbw = b.w;
6312		this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
6313		this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
6314		this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
6315		this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
6316		return this;
6317	  },
6318	  inverse: function inverse() {
6319		this.x *= -1;
6320		this.y *= -1;
6321		this.z *= -1;
6322		this.normalize();
6323		return this;
6324	  },
6325	  normalize: function normalize() {
6326		var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
6327		if (l === 0) {
6328		  this.x = 0;
6329		  this.y = 0;
6330		  this.z = 0;
6331		  this.w = 1;
6332		} else {
6333		  l = 1 / l;
6334		  this.x = this.x * l;
6335		  this.y = this.y * l;
6336		  this.z = this.z * l;
6337		  this.w = this.w * l;
6338		}
6339		return this;
6340	  },
6341	  slerp: function slerp(qb, t) {
6342		if (t === 0) return this;
6343		if (t === 1) return this.copy(qb);
6344		var x = this.x,
6345			y = this.y,
6346			z = this.z,
6347			w = this.w;
6348		var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
6349		if (cosHalfTheta < 0) {
6350		  this.w = -qb.w;
6351		  this.x = -qb.x;
6352		  this.y = -qb.y;
6353		  this.z = -qb.z;
6354		  cosHalfTheta = -cosHalfTheta;
6355		} else {
6356		  this.copy(qb);
6357		}
6358		if (cosHalfTheta >= 1.0) {
6359		  this.w = w;
6360		  this.x = x;
6361		  this.y = y;
6362		  this.z = z;
6363		  return this;
6364		}
6365		var halfTheta = Math.acos(cosHalfTheta);
6366		var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
6367		if (Math.abs(sinHalfTheta) < 0.001) {
6368		  this.w = 0.5 * (w + this.w);
6369		  this.x = 0.5 * (x + this.x);
6370		  this.y = 0.5 * (y + this.y);
6371		  this.z = 0.5 * (z + this.z);
6372		  return this;
6373		}
6374		var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
6375			ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
6376		this.w = w * ratioA + this.w * ratioB;
6377		this.x = x * ratioA + this.x * ratioB;
6378		this.y = y * ratioA + this.y * ratioB;
6379		this.z = z * ratioA + this.z * ratioB;
6380		return this;
6381	  },
6382	  setFromUnitVectors: function () {
6383		var v1, r;
6384		var EPS = 0.000001;
6385		return function (vFrom, vTo) {
6386		  if (v1 === undefined) v1 = new Vector3();
6387		  r = vFrom.dot(vTo) + 1;
6388		  if (r < EPS) {
6389			r = 0;
6390			if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
6391			  v1.set(-vFrom.y, vFrom.x, 0);
6392			} else {
6393			  v1.set(0, -vFrom.z, vFrom.y);
6394			}
6395		  } else {
6396			v1.crossVectors(vFrom, vTo);
6397		  }
6398		  this.x = v1.x;
6399		  this.y = v1.y;
6400		  this.z = v1.z;
6401		  this.w = r;
6402		  this.normalize();
6403		  return this;
6404		};
6405	  }()
6406	};
6407	function Device(params) {
6408	  this.width = params.width || getScreenWidth();
6409	  this.height = params.height || getScreenHeight();
6410	  this.widthMeters = params.widthMeters;
6411	  this.heightMeters = params.heightMeters;
6412	  this.bevelMeters = params.bevelMeters;
6413	}
6414	var DEFAULT_ANDROID = new Device({
6415	  widthMeters: 0.110,
6416	  heightMeters: 0.062,
6417	  bevelMeters: 0.004
6418	});
6419	var DEFAULT_IOS = new Device({
6420	  widthMeters: 0.1038,
6421	  heightMeters: 0.0584,
6422	  bevelMeters: 0.004
6423	});
6424	var Viewers = {
6425	  CardboardV1: new CardboardViewer({
6426		id: 'CardboardV1',
6427		label: 'Cardboard I/O 2014',
6428		fov: 40,
6429		interLensDistance: 0.060,
6430		baselineLensDistance: 0.035,
6431		screenLensDistance: 0.042,
6432		distortionCoefficients: [0.441, 0.156],
6433		inverseCoefficients: [-0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, -0.01488963, 0.001559834]
6434	  }),
6435	  CardboardV2: new CardboardViewer({
6436		id: 'CardboardV2',
6437		label: 'Cardboard I/O 2015',
6438		fov: 60,
6439		interLensDistance: 0.064,
6440		baselineLensDistance: 0.035,
6441		screenLensDistance: 0.039,
6442		distortionCoefficients: [0.34, 0.55],
6443		inverseCoefficients: [-0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169E-4, 6.183535E-5, -1.6981803E-6]
6444	  })
6445	};
6446	function DeviceInfo(deviceParams, additionalViewers) {
6447	  this.viewer = Viewers.CardboardV2;
6448	  this.updateDeviceParams(deviceParams);
6449	  this.distortion = new Distortion(this.viewer.distortionCoefficients);
6450	  for (var i = 0; i < additionalViewers.length; i++) {
6451		var viewer = additionalViewers[i];
6452		Viewers[viewer.id] = new CardboardViewer(viewer);
6453	  }
6454	}
6455	DeviceInfo.prototype.updateDeviceParams = function (deviceParams) {
6456	  this.device = this.determineDevice_(deviceParams) || this.device;
6457	};
6458	DeviceInfo.prototype.getDevice = function () {
6459	  return this.device;
6460	};
6461	DeviceInfo.prototype.setViewer = function (viewer) {
6462	  this.viewer = viewer;
6463	  this.distortion = new Distortion(this.viewer.distortionCoefficients);
6464	};
6465	DeviceInfo.prototype.determineDevice_ = function (deviceParams) {
6466	  if (!deviceParams) {
6467		if (isIOS()) {
6468		  console.warn('Using fallback iOS device measurements.');
6469		  return DEFAULT_IOS;
6470		} else {
6471		  console.warn('Using fallback Android device measurements.');
6472		  return DEFAULT_ANDROID;
6473		}
6474	  }
6475	  var METERS_PER_INCH = 0.0254;
6476	  var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi;
6477	  var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi;
6478	  var width = getScreenWidth();
6479	  var height = getScreenHeight();
6480	  return new Device({
6481		widthMeters: metersPerPixelX * width,
6482		heightMeters: metersPerPixelY * height,
6483		bevelMeters: deviceParams.bevelMm * 0.001
6484	  });
6485	};
6486	DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () {
6487	  var viewer = this.viewer;
6488	  var device = this.device;
6489	  var distortion = this.distortion;
6490	  var eyeToScreenDistance = viewer.screenLensDistance;
6491	  var outerDist = (device.widthMeters - viewer.interLensDistance) / 2;
6492	  var innerDist = viewer.interLensDistance / 2;
6493	  var bottomDist = viewer.baselineLensDistance - device.bevelMeters;
6494	  var topDist = device.heightMeters - bottomDist;
6495	  var outerAngle = radToDeg * Math.atan(distortion.distort(outerDist / eyeToScreenDistance));
6496	  var innerAngle = radToDeg * Math.atan(distortion.distort(innerDist / eyeToScreenDistance));
6497	  var bottomAngle = radToDeg * Math.atan(distortion.distort(bottomDist / eyeToScreenDistance));
6498	  var topAngle = radToDeg * Math.atan(distortion.distort(topDist / eyeToScreenDistance));
6499	  return {
6500		leftDegrees: Math.min(outerAngle, viewer.fov),
6501		rightDegrees: Math.min(innerAngle, viewer.fov),
6502		downDegrees: Math.min(bottomAngle, viewer.fov),
6503		upDegrees: Math.min(topAngle, viewer.fov)
6504	  };
6505	};
6506	DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () {
6507	  var viewer = this.viewer;
6508	  var device = this.device;
6509	  var distortion = this.distortion;
6510	  var fovLeft = Math.tan(-degToRad * viewer.fov);
6511	  var fovTop = Math.tan(degToRad * viewer.fov);
6512	  var fovRight = Math.tan(degToRad * viewer.fov);
6513	  var fovBottom = Math.tan(-degToRad * viewer.fov);
6514	  var halfWidth = device.widthMeters / 4;
6515	  var halfHeight = device.heightMeters / 2;
6516	  var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight;
6517	  var centerX = viewer.interLensDistance / 2 - halfWidth;
6518	  var centerY = -verticalLensOffset;
6519	  var centerZ = viewer.screenLensDistance;
6520	  var screenLeft = distortion.distort((centerX - halfWidth) / centerZ);
6521	  var screenTop = distortion.distort((centerY + halfHeight) / centerZ);
6522	  var screenRight = distortion.distort((centerX + halfWidth) / centerZ);
6523	  var screenBottom = distortion.distort((centerY - halfHeight) / centerZ);
6524	  var result = new Float32Array(4);
6525	  result[0] = Math.max(fovLeft, screenLeft);
6526	  result[1] = Math.min(fovTop, screenTop);
6527	  result[2] = Math.min(fovRight, screenRight);
6528	  result[3] = Math.max(fovBottom, screenBottom);
6529	  return result;
6530	};
6531	DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () {
6532	  var viewer = this.viewer;
6533	  var device = this.device;
6534	  var distortion = this.distortion;
6535	  var result = new Float32Array(4);
6536	  var fovLeft = distortion.distortInverse(Math.tan(-degToRad * viewer.fov));
6537	  var fovTop = distortion.distortInverse(Math.tan(degToRad * viewer.fov));
6538	  var fovRight = distortion.distortInverse(Math.tan(degToRad * viewer.fov));
6539	  var fovBottom = distortion.distortInverse(Math.tan(-degToRad * viewer.fov));
6540	  var halfWidth = device.widthMeters / 4;
6541	  var halfHeight = device.heightMeters / 2;
6542	  var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight;
6543	  var centerX = viewer.interLensDistance / 2 - halfWidth;
6544	  var centerY = -verticalLensOffset;
6545	  var centerZ = viewer.screenLensDistance;
6546	  var screenLeft = (centerX - halfWidth) / centerZ;
6547	  var screenTop = (centerY + halfHeight) / centerZ;
6548	  var screenRight = (centerX + halfWidth) / centerZ;
6549	  var screenBottom = (centerY - halfHeight) / centerZ;
6550	  result[0] = Math.max(fovLeft, screenLeft);
6551	  result[1] = Math.min(fovTop, screenTop);
6552	  result[2] = Math.min(fovRight, screenRight);
6553	  result[3] = Math.max(fovBottom, screenBottom);
6554	  return result;
6555	};
6556	DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function (undistortedFrustum) {
6557	  var viewer = this.viewer;
6558	  var device = this.device;
6559	  var dist = viewer.screenLensDistance;
6560	  var eyeX = (device.widthMeters - viewer.interLensDistance) / 2;
6561	  var eyeY = viewer.baselineLensDistance - device.bevelMeters;
6562	  var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters;
6563	  var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters;
6564	  var right = (undistortedFrustum[2] * dist + eyeX) / device.widthMeters;
6565	  var bottom = (undistortedFrustum[3] * dist + eyeY) / device.heightMeters;
6566	  return {
6567		x: left,
6568		y: bottom,
6569		width: right - left,
6570		height: top - bottom
6571	  };
6572	};
6573	DeviceInfo.prototype.getFieldOfViewLeftEye = function (opt_isUndistorted) {
6574	  return opt_isUndistorted ? this.getUndistortedFieldOfViewLeftEye() : this.getDistortedFieldOfViewLeftEye();
6575	};
6576	DeviceInfo.prototype.getFieldOfViewRightEye = function (opt_isUndistorted) {
6577	  var fov = this.getFieldOfViewLeftEye(opt_isUndistorted);
6578	  return {
6579		leftDegrees: fov.rightDegrees,
6580		rightDegrees: fov.leftDegrees,
6581		upDegrees: fov.upDegrees,
6582		downDegrees: fov.downDegrees
6583	  };
6584	};
6585	DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () {
6586	  var p = this.getUndistortedParams_();
6587	  return {
6588		leftDegrees: radToDeg * Math.atan(p.outerDist),
6589		rightDegrees: radToDeg * Math.atan(p.innerDist),
6590		downDegrees: radToDeg * Math.atan(p.bottomDist),
6591		upDegrees: radToDeg * Math.atan(p.topDist)
6592	  };
6593	};
6594	DeviceInfo.prototype.getUndistortedViewportLeftEye = function () {
6595	  var p = this.getUndistortedParams_();
6596	  var viewer = this.viewer;
6597	  var device = this.device;
6598	  var eyeToScreenDistance = viewer.screenLensDistance;
6599	  var screenWidth = device.widthMeters / eyeToScreenDistance;
6600	  var screenHeight = device.heightMeters / eyeToScreenDistance;
6601	  var xPxPerTanAngle = device.width / screenWidth;
6602	  var yPxPerTanAngle = device.height / screenHeight;
6603	  var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle);
6604	  var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle);
6605	  return {
6606		x: x,
6607		y: y,
6608		width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x,
6609		height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y
6610	  };
6611	};
6612	DeviceInfo.prototype.getUndistortedParams_ = function () {
6613	  var viewer = this.viewer;
6614	  var device = this.device;
6615	  var distortion = this.distortion;
6616	  var eyeToScreenDistance = viewer.screenLensDistance;
6617	  var halfLensDistance = viewer.interLensDistance / 2 / eyeToScreenDistance;
6618	  var screenWidth = device.widthMeters / eyeToScreenDistance;
6619	  var screenHeight = device.heightMeters / eyeToScreenDistance;
6620	  var eyePosX = screenWidth / 2 - halfLensDistance;
6621	  var eyePosY = (viewer.baselineLensDistance - device.bevelMeters) / eyeToScreenDistance;
6622	  var maxFov = viewer.fov;
6623	  var viewerMax = distortion.distortInverse(Math.tan(degToRad * maxFov));
6624	  var outerDist = Math.min(eyePosX, viewerMax);
6625	  var innerDist = Math.min(halfLensDistance, viewerMax);
6626	  var bottomDist = Math.min(eyePosY, viewerMax);
6627	  var topDist = Math.min(screenHeight - eyePosY, viewerMax);
6628	  return {
6629		outerDist: outerDist,
6630		innerDist: innerDist,
6631		topDist: topDist,
6632		bottomDist: bottomDist,
6633		eyePosX: eyePosX,
6634		eyePosY: eyePosY
6635	  };
6636	};
6637	function CardboardViewer(params) {
6638	  this.id = params.id;
6639	  this.label = params.label;
6640	  this.fov = params.fov;
6641	  this.interLensDistance = params.interLensDistance;
6642	  this.baselineLensDistance = params.baselineLensDistance;
6643	  this.screenLensDistance = params.screenLensDistance;
6644	  this.distortionCoefficients = params.distortionCoefficients;
6645	  this.inverseCoefficients = params.inverseCoefficients;
6646	}
6647	DeviceInfo.Viewers = Viewers;
6648	var format = 1;
6649	var last_updated = "2018-02-20T22:55:10Z";
6650	var devices = [{"type":"android","rules":[{"mdmh":"asus/*/Nexus 7/*"},{"ua":"Nexus 7"}],"dpi":[320.8,323],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"asus/*/ASUS_Z00AD/*"},{"ua":"ASUS_Z00AD"}],"dpi":[403,404.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel XL/*"},{"ua":"Pixel XL"}],"dpi":[537.9,533],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel/*"},{"ua":"Pixel"}
6650],"dpi":[432.6,436.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC6435LVW/*"},{"ua":"HTC6435LVW"}],"dpi":[449.7,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One XL/*"},{"ua":"HTC One XL"}],"dpi":[315.3,314.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"htc/*/Nexus 9/*"},{"ua":"Nexus 9"}],"dpi":289,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One M9/*"},{"ua":"HTC One M9"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One_M8/*"},{"ua":"HTC One_M8"}],"dpi":[449.7,447.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One/*"},{"ua":"HTC One"}],"dpi":472.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/Nexus 6P/*"},{"ua":"Nexus 6P"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LENOVO/*/Lenovo PB2-690Y/*"},{"ua":"Lenovo PB2-690Y"}],"dpi":[457.2,454.713],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5X/*"},{"ua":"Nexus 5X"}],"dpi":[422,419.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS345/*"},{"ua":"LGMS345"}],"dpi":[221.7,219.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D800/*"},{"ua":"LG-D800"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D850/*"},{"ua":"LG-D850"}],"dpi":[537.9,541.9],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/VS985 4G/*"},{"ua":"VS985 4G"}],"dpi":[537.9,535.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5/*"},{"ua":"Nexus 5 B"}],"dpi":[442.4,444.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 4/*"},{"ua":"Nexus 4"}],"dpi":[319.8,318.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LG-P769/*"},{"ua":"LG-P769"}],"dpi":[240.6,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS323/*"},{"ua":"LGMS323"}],"dpi":[206.6,204.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGLS996/*"},{"ua":"LGLS996"}],"dpi":[403.4,401.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/4560MMX/*"},{"ua":"4560MMX"}],"dpi":[240,219.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/A250/*"},{"ua":"Micromax A250"}],"dpi":[480,446.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/Micromax AQ4501/*"},{"ua":"Micromax AQ4501"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/G5/*"},{"ua":"Moto G (5) Plus"}],"dpi":[403.4,403],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/DROID RAZR/*"},{"ua":"DROID RAZR"}],"dpi":[368.1,256.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT830C/*"},{"ua":"XT830C"}],"dpi":[254,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1021/*"},{"ua":"XT1021"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1023/*"},{"ua":"XT1023"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1028/*"},{"ua":"XT1028"}],"dpi":[326.6,327.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1034/*"},{"ua":"XT1034"}],"dpi":[326.6,328.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1053/*"},{"ua":"XT1053"}],"dpi":[315.3,316.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1562/*"},{"ua":"XT1562"}],"dpi":[403.4,402.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/Nexus 6/*"},{"ua":"Nexus 6 B"}],"dpi":[494.3,489.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1063/*"},{"ua":"XT1063"}
6650],"dpi":[295,296.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1064/*"},{"ua":"XT1064"}],"dpi":[295,295.6],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1092/*"},{"ua":"XT1092"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1095/*"},{"ua":"XT1095"}],"dpi":[422,423.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/G4/*"},{"ua":"Moto G (4)"}],"dpi":401,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/A0001/*"},{"ua":"A0001"}],"dpi":[403.4,401],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE E1005/*"},{"ua":"ONE E1005"}],"dpi":[442.4,441.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A2005/*"},{"ua":"ONE A2005"}],"dpi":[391.9,405.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONEPLUS A5000/*"},{"ua":"ONEPLUS A5000 "}],"dpi":[403.411,399.737],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A5010/*"},{"ua":"ONEPLUS A5010"}],"dpi":[403,400],"bw":2,"ac":1000},{"type":"android","rules":[{"mdmh":"OPPO/*/X909/*"},{"ua":"X909"}],"dpi":[442.4,444.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9082/*"},{"ua":"GT-I9082"}],"dpi":[184.7,185.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G360P/*"},{"ua":"SM-G360P"}],"dpi":[196.7,205.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Nexus S/*"},{"ua":"Nexus S"}],"dpi":[234.5,229.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[304.8,303.9],"bw":5,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T230NU/*"},{"ua":"SM-T230NU"}],"dpi":216,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-T399/*"},{"ua":"SGH-T399"}],"dpi":[217.7,231.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-M919/*"},{"ua":"SGH-M919"}],"dpi":[440.8,437.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N9005/*"},{"ua":"SM-N9005"}],"dpi":[386.4,387],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SM-N900A/*"},{"ua":"SAMSUNG-SM-N900A"}],"dpi":[386.4,387.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9500/*"},{"ua":"GT-I9500"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9505/*"},{"ua":"GT-I9505"}],"dpi":439.4,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900F/*"},{"ua":"SM-G900F"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900M/*"},{"ua":"SM-G900M"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G800F/*"},{"ua":"SM-G800F"}],"dpi":326.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G906S/*"},{"ua":"SM-G906S"}],"dpi":[562.7,572.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[306.7,304.8],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T535/*"},{"ua":"SM-T535"}],"dpi":[142.6,136.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920C/*"},{"ua":"SM-N920C"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920P/*"},{"ua":"SM-N920P"}],"dpi":[386.3655,390.144],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920W8/*"},{"ua":"SM-N920W8"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300I/*"},{"ua":"GT-I9300I"}],"dpi":[304.8,305.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9195/*"},{"ua":"GT-I9195"}],"dpi":[249.4,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-L520/*"},{"ua":"SPH-L520"}],"dpi":[249.4,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SGH-I717/*"},{"ua":"SAMSUNG-SGH-I717"}],"dpi":285.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-D710/*"},{"ua":"SPH-D710"}],"dpi":[217.7,204.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-N7100/*"},{"ua":"GT-N7100"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SCH-I605/*"},{"ua":"SCH-I605"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Galaxy Nexus/*"},{"ua":"Galaxy Nexus"}],"dpi":[315.3,314.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910H/*"},{"ua":"SM-N910H"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910C/*"},{"ua":"SM-N910C"}],"dpi":[515.2,520.2],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G130M/*"},{"ua":"SM-G130M"}],"dpi":[165.9,164.8],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G928I/*"},{"ua":"SM-G928I"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920F/*"},{"ua":"SM-G920F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920P/*"},{"ua":"SM-G920P"}],"dpi":[522.5,577],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925F/*"},{"ua":"SM-G925F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925V/*"},{"ua":"SM-G925V"}],"dpi":[522.5,576.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G930F/*"},{"ua":"SM-G930F"}],"dpi":576.6,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G935F/*"},{"ua":"SM-G935F"}],"dpi":533,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G950F/*"},{"ua":"SM-G950F"}],"dpi":[562.707,565.293],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955U/*"},{"ua":"SM-G955U"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/C6903/*"},{"ua":"C6903"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/D6653/*"},{"ua":"D6653"}],"dpi":[428.6,427.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6653/*"},{"ua":"E6653"}],"dpi":[428.6,425.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6853/*"},{"ua":"E6853"}],"dpi":[403.4,401.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/SGP321/*"},{"ua":"SGP321"}],"dpi":[224.7,224.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{"ua":"ALCATEL ONE TOUCH Fierce"}],"dpi":[240,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"THL/*/thl 5000/*"},{"ua":"thl 5000"}],"dpi":[480,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Fly/*/IQ4412/*"},{"ua":"IQ4412"}],"dpi":307.9,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"ZTE/*/ZTE Blade L2/*"},{"ua":"ZTE Blade L2"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"BENEVE/*/VR518/*"},{"ua":"VR518"}],"dpi":480,"bw":3,"ac":500}
vendor: 9,300 bytes, lines 6650-6900
6650,{"type":"ios","rules":[{"res":[640,960]}],"dpi":[325.1,328.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[640,1136]}],"dpi":[317.1,320.2],"bw":3,"ac":1000},{"type":"ios","rules":[{"res":[750,1334]}],"dpi":326.4,"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1242,2208]}],"dpi":[453.6,458.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2001]}],"dpi":[410.9,415.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2436]}],"dpi":458,"bw":4,"ac":1000}];
6651	var DPDB_CACHE = {
6652		format: format,
6653		last_updated: last_updated,
6654		devices: devices
6655	};
6656	function Dpdb(url, onDeviceParamsUpdated) {
6657	  this.dpdb = DPDB_CACHE;
6658	  this.recalculateDeviceParams_();
6659	  if (url) {
6660		this.onDeviceParamsUpdated = onDeviceParamsUpdated;
6661		var xhr = new XMLHttpRequest();
6662		var obj = this;
6663		xhr.open('GET', url, true);
6664		xhr.addEventListener('load', function () {
6665		  obj.loading = false;
6666		  if (xhr.status >= 200 && xhr.status <= 299) {
6667			obj.dpdb = JSON.parse(xhr.response);
6668			obj.recalculateDeviceParams_();
6669		  } else {
6670			console.error('Error loading online DPDB!');
6671		  }
6672		});
6673		xhr.send();
6674	  }
6675	}
6676	Dpdb.prototype.getDeviceParams = function () {
6677	  return this.deviceParams;
6678	};
6679	Dpdb.prototype.recalculateDeviceParams_ = function () {
6680	  var newDeviceParams = this.calcDeviceParams_();
6681	  if (newDeviceParams) {
6682		this.deviceParams = newDeviceParams;
6683		if (this.onDeviceParamsUpdated) {
6684		  this.onDeviceParamsUpdated(this.deviceParams);
6685		}
6686	  } else {
6687		console.error('Failed to recalculate device parameters.');
6688	  }
6689	};
6690	Dpdb.prototype.calcDeviceParams_ = function () {
6691	  var db = this.dpdb;
6692	  if (!db) {
6693		console.error('DPDB not available.');
6694		return null;
6695	  }
6696	  if (db.format != 1) {
6697		console.error('DPDB has unexpected format version.');
6698		return null;
6699	  }
6700	  if (!db.devices || !db.devices.length) {
6701		console.error('DPDB does not have a devices section.');
6702		return null;
6703	  }
6704	  var userAgent = navigator.userAgent || navigator.vendor || window.opera;
6705	  var width = getScreenWidth();
6706	  var height = getScreenHeight();
6707	  if (!db.devices) {
6708		console.error('DPDB has no devices section.');
6709		return null;
6710	  }
6711	  for (var i = 0; i < db.devices.length; i++) {
6712		var device = db.devices[i];
6713		if (!device.rules) {
6714		  console.warn('Device[' + i + '] has no rules section.');
6715		  continue;
6716		}
6717		if (device.type != 'ios' && device.type != 'android') {
6718		  console.warn('Device[' + i + '] has invalid type.');
6719		  continue;
6720		}
6721		if (isIOS() != (device.type == 'ios')) continue;
6722		var matched = false;
6723		for (var j = 0; j < device.rules.length; j++) {
6724		  var rule = device.rules[j];
6725		  if (this.matchRule_(rule, userAgent, width, height)) {
6726			matched = true;
6727			break;
6728		  }
6729		}
6730		if (!matched) continue;
6731		var xdpi = device.dpi[0] || device.dpi;
6732		var ydpi = device.dpi[1] || device.dpi;
6733		return new DeviceParams({ xdpi: xdpi, ydpi: ydpi, bevelMm: device.bw });
6734	  }
6735	  console.warn('No DPDB device match.');
6736	  return null;
6737	};
6738	Dpdb.prototype.matchRule_ = function (rule, ua, screenWidth, screenHeight) {
6739	  if (!rule.ua && !rule.res) return false;
6740	  if (rule.ua && ua.indexOf(rule.ua) < 0) return false;
6741	  if (rule.res) {
6742		if (!rule.res[0] || !rule.res[1]) return false;
6743		var resX = rule.res[0];
6744		var resY = rule.res[1];
6745		if (Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || Math.max(screenWidth, screenHeight) != Math.max(resX, resY)) {
6746		  return false;
6747		}
6748	  }
6749	  return true;
6750	};
6751	function DeviceParams(params) {
6752	  this.xdpi = params.xdpi;
6753	  this.ydpi = params.ydpi;
6754	  this.bevelMm = params.bevelMm;
6755	}
6756	function SensorSample(sample, timestampS) {
6757	  this.set(sample, timestampS);
6758	}
6759	SensorSample.prototype.set = function (sample, timestampS) {
6760	  this.sample = sample;
6761	  this.timestampS = timestampS;
6762	};
6763	SensorSample.prototype.copy = function (sensorSample) {
6764	  this.set(sensorSample.sample, sensorSample.timestampS);
6765	};
6766	function ComplementaryFilter(kFilter, isDebug) {
6767	  this.kFilter = kFilter;
6768	  this.isDebug = isDebug;
6769	  this.currentAccelMeasurement = new SensorSample();
6770	  this.currentGyroMeasurement = new SensorSample();
6771	  this.previousGyroMeasurement = new SensorSample();
6772	  if (isIOS()) {
6773		this.filterQ = new Quaternion(-1, 0, 0, 1);
6774	  } else {
6775		this.filterQ = new Quaternion(1, 0, 0, 1);
6776	  }
6777	  this.previousFilterQ = new Quaternion();
6778	  this.previousFilterQ.copy(this.filterQ);
6779	  this.accelQ = new Quaternion();
6780	  this.isOrientationInitialized = false;
6781	  this.estimatedGravity = new Vector3();
6782	  this.measuredGravity = new Vector3();
6783	  this.gyroIntegralQ = new Quaternion();
6784	}
6785	ComplementaryFilter.prototype.addAccelMeasurement = function (vector, timestampS) {
6786	  this.currentAccelMeasurement.set(vector, timestampS);
6787	};
6788	ComplementaryFilter.prototype.addGyroMeasurement = function (vector, timestampS) {
6789	  this.currentGyroMeasurement.set(vector, timestampS);
6790	  var deltaT = timestampS - this.previousGyroMeasurement.timestampS;
6791	  if (isTimestampDeltaValid(deltaT)) {
6792		this.run_();
6793	  }
6794	  this.previousGyroMeasurement.copy(this.currentGyroMeasurement);
6795	};
6796	ComplementaryFilter.prototype.run_ = function () {
6797	  if (!this.isOrientationInitialized) {
6798		this.accelQ = this.accelToQuaternion_(this.currentAccelMeasurement.sample);
6799		this.previousFilterQ.copy(this.accelQ);
6800		this.isOrientationInitialized = true;
6801		return;
6802	  }
6803	  var deltaT = this.currentGyroMeasurement.timestampS - this.previousGyroMeasurement.timestampS;
6804	  var gyroDeltaQ = this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample, deltaT);
6805	  this.gyroIntegralQ.multiply(gyroDeltaQ);
6806	  this.filterQ.copy(this.previousFilterQ);
6807	  this.filterQ.multiply(gyroDeltaQ);
6808	  var invFilterQ = new Quaternion();
6809	  invFilterQ.copy(this.filterQ);
6810	  invFilterQ.inverse();
6811	  this.estimatedGravity.set(0, 0, -1);
6812	  this.estimatedGravity.applyQuaternion(invFilterQ);
6813	  this.estimatedGravity.normalize();
6814	  this.measuredGravity.copy(this.currentAccelMeasurement.sample);
6815	  this.measuredGravity.normalize();
6816	  var deltaQ = new Quaternion();
6817	  deltaQ.setFromUnitVectors(this.estimatedGravity, this.measuredGravity);
6818	  deltaQ.inverse();
6819	  if (this.isDebug) {
6820		console.log('Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)', radToDeg * getQuaternionAngle(deltaQ), this.estimatedGravity.x.toFixed(1), this.estimatedGravity.y.toFixed(1), this.estimatedGravity.z.toFixed(1), this.measuredGravity.x.toFixed(1), this.measuredGravity.y.toFixed(1), this.measuredGravity.z.toFixed(1));
6821	  }
6822	  var targetQ = new Quaternion();
6823	  targetQ.copy(this.filterQ);
6824	  targetQ.multiply(deltaQ);
6825	  this.filterQ.slerp(targetQ, 1 - this.kFilter);
6826	  this.previousFilterQ.copy(this.filterQ);
6827	};
6828	ComplementaryFilter.prototype.getOrientation = function () {
6829	  return this.filterQ;
6830	};
6831	ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) {
6832	  var normAccel = new Vector3();
6833	  normAccel.copy(accel);
6834	  normAccel.normalize();
6835	  var quat = new Quaternion();
6836	  quat.setFromUnitVectors(new Vector3(0, 0, -1), normAccel);
6837	  quat.inverse();
6838	  return quat;
6839	};
6840	ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function (gyro, dt) {
6841	  var quat = new Quaternion();
6842	  var axis = new Vector3();
6843	  axis.copy(gyro);
6844	  axis.normalize();
6845	  quat.setFromAxisAngle(axis, gyro.length() * dt);
6846	  return quat;
6847	};
6848	function PosePredictor(predictionTimeS, isDebug) {
6849	  this.predictionTimeS = predictionTimeS;
6850	  this.isDebug = isDebug;
6851	  this.previousQ = new Quaternion();
6852	  this.previousTimestampS = null;
6853	  this.deltaQ = new Quaternion();
6854	  this.outQ = new Quaternion();
6855	}
6856	PosePredictor.prototype.getPrediction = function (currentQ, gyro, timestampS) {
6857	  if (!this.previousTimestampS) {
6858		this.previousQ.copy(currentQ);
6859		this.previousTimestampS = timestampS;
6860		return currentQ;
6861	  }
6862	  var axis = new Vector3();
6863	  axis.copy(gyro);
6864	  axis.normalize();
6865	  var angularSpeed = gyro.length();
6866	  if (angularSpeed < degToRad * 20) {
6867		if (this.isDebug) {
6868		  console.log('Moving slowly, at %s deg/s: no prediction', (radToDeg * angularSpeed).toFixed(1));
6869		}
6870		this.outQ.copy(currentQ);
6871		this.previousQ.copy(currentQ);
6872		return this.outQ;
6873	  }
6874	  var predictAngle = angularSpeed * this.predictionTimeS;
6875	  this.deltaQ.setFromAxisAngle(axis, predictAngle);
6876	  this.outQ.copy(this.previousQ);
6877	  this.outQ.multiply(this.deltaQ);
6878	  this.previousQ.copy(currentQ);
6879	  this.previousTimestampS = timestampS;
6880	  return this.outQ;
6881	};
6882	function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) {
6883	  this.yawOnly = yawOnly;
6884	  this.accelerometer = new Vector3();
6885	  this.gyroscope = new Vector3();
6886	  this.filter = new ComplementaryFilter(kFilter, isDebug);
6887	  this.posePredictor = new PosePredictor(predictionTime, isDebug);
6888	  this.isFirefoxAndroid = isFirefoxAndroid();
6889	  this.isIOS = isIOS();
6890	  var chromeVersion = getChromeVersion();
6891	  this.isDeviceMotionInRadians = !this.isIOS && chromeVersion && chromeVersion < 66;
6892	  this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion();
6893	  this.filterToWorldQ = new Quaternion();
6894	  if (isIOS()) {
6895		this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2);
6896	  } else {
6897		this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
6898	  }
6899	  this.inverseWorldToScreenQ = new Quaternion();
6900	  this.worldToScreenQ = new Quaternion();
vendor: 7,633 bytes, lines 6901-7107
6901	  this.originalPoseAdjustQ = new Quaternion();
6902	  this.originalPoseAdjustQ.setFromAxisAngle(new Vector3(0, 0, 1), -window.orientation * Math.PI / 180);
6903	  this.setScreenTransform_();
6904	  if (isLandscapeMode()) {
6905		this.filterToWorldQ.multiply(this.inverseWorldToScreenQ);
6906	  }
6907	  this.resetQ = new Quaternion();
6908	  this.orientationOut_ = new Float32Array(4);
6909	  this.start();
6910	}
6911	FusionPoseSensor.prototype.getPosition = function () {
6912	  return null;
6913	};
6914	FusionPoseSensor.prototype.getOrientation = function () {
6915	  var orientation = void 0;
6916	  if (this.isWithoutDeviceMotion && this._deviceOrientationQ) {
6917		this.deviceOrientationFixQ = this.deviceOrientationFixQ || function () {
6918		  var z = new Quaternion().setFromAxisAngle(new Vector3(0, 0, -1), 0);
6919		  var y = new Quaternion();
6920		  if (window.orientation === -90) {
6921			y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / -2);
6922		  } else {
6923			y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2);
6924		  }
6925		  return z.multiply(y);
6926		}();
6927		this.deviceOrientationFilterToWorldQ = this.deviceOrientationFilterToWorldQ || function () {
6928		  var q = new Quaternion();
6929		  q.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
6930		  return q;
6931		}();
6932		orientation = this._deviceOrientationQ;
6933		var out = new Quaternion();
6934		out.copy(orientation);
6935		out.multiply(this.deviceOrientationFilterToWorldQ);
6936		out.multiply(this.resetQ);
6937		out.multiply(this.worldToScreenQ);
6938		out.multiplyQuaternions(this.deviceOrientationFixQ, out);
6939		if (this.yawOnly) {
6940		  out.x = 0;
6941		  out.z = 0;
6942		  out.normalize();
6943		}
6944		this.orientationOut_[0] = out.x;
6945		this.orientationOut_[1] = out.y;
6946		this.orientationOut_[2] = out.z;
6947		this.orientationOut_[3] = out.w;
6948		return this.orientationOut_;
6949	  } else {
6950		var filterOrientation = this.filter.getOrientation();
6951		orientation = this.posePredictor.getPrediction(filterOrientation, this.gyroscope, this.previousTimestampS);
6952	  }
6953	  var out = new Quaternion();
6954	  out.copy(this.filterToWorldQ);
6955	  out.multiply(this.resetQ);
6956	  out.multiply(orientation);
6957	  out.multiply(this.worldToScreenQ);
6958	  if (this.yawOnly) {
6959		out.x = 0;
6960		out.z = 0;
6961		out.normalize();
6962	  }
6963	  this.orientationOut_[0] = out.x;
6964	  this.orientationOut_[1] = out.y;
6965	  this.orientationOut_[2] = out.z;
6966	  this.orientationOut_[3] = out.w;
6967	  return this.orientationOut_;
6968	};
6969	FusionPoseSensor.prototype.resetPose = function () {
6970	  this.resetQ.copy(this.filter.getOrientation());
6971	  this.resetQ.x = 0;
6972	  this.resetQ.y = 0;
6973	  this.resetQ.z *= -1;
6974	  this.resetQ.normalize();
6975	  if (isLandscapeMode()) {
6976		this.resetQ.multiply(this.inverseWorldToScreenQ);
6977	  }
6978	  this.resetQ.multiply(this.originalPoseAdjustQ);
6979	};
6980	FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) {
6981	  this._deviceOrientationQ = this._deviceOrientationQ || new Quaternion();
6982	  var alpha = e.alpha,
6983		  beta = e.beta,
6984		  gamma = e.gamma;
6985	  alpha = (alpha || 0) * Math.PI / 180;
6986	  beta = (beta || 0) * Math.PI / 180;
6987	  gamma = (gamma || 0) * Math.PI / 180;
6988	  this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma);
6989	};
6990	FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) {
6991	  this.updateDeviceMotion_(deviceMotion);
6992	};
6993	FusionPoseSensor.prototype.updateDeviceMotion_ = function (deviceMotion) {
6994	  var accGravity = deviceMotion.accelerationIncludingGravity;
6995	  var rotRate = deviceMotion.rotationRate;
6996	  var timestampS = deviceMotion.timeStamp / 1000;
6997	  var deltaS = timestampS - this.previousTimestampS;
6998	  if (deltaS < 0) {
6999		warnOnce('fusion-pose-sensor:invalid:non-monotonic', 'Invalid timestamps detected: non-monotonic timestamp from devicemotion');
7000		this.previousTimestampS = timestampS;
7001		return;
7002	  } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) {
7003		warnOnce('fusion-pose-sensor:invalid:outside-threshold', 'Invalid timestamps detected: Timestamp from devicemotion outside expected range.');
7004		this.previousTimestampS = timestampS;
7005		return;
7006	  }
7007	  this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z);
7008	  if (isR7()) {
7009		this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma);
7010	  } else {
7011		this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma);
7012	  }
7013	  if (!this.isDeviceMotionInRadians) {
7014		this.gyroscope.multiplyScalar(Math.PI / 180);
7015	  }
7016	  this.filter.addAccelMeasurement(this.accelerometer, timestampS);
7017	  this.filter.addGyroMeasurement(this.gyroscope, timestampS);
7018	  this.previousTimestampS = timestampS;
7019	};
7020	FusionPoseSensor.prototype.onOrientationChange_ = function (screenOrientation) {
7021	  this.setScreenTransform_();
7022	};
7023	FusionPoseSensor.prototype.onMessage_ = function (event) {
7024	  var message = event.data;
7025	  if (!message || !message.type) {
7026		return;
7027	  }
7028	  var type = message.type.toLowerCase();
7029	  if (type !== 'devicemotion') {
7030		return;
7031	  }
7032	  this.updateDeviceMotion_(message.deviceMotionEvent);
7033	};
7034	FusionPoseSensor.prototype.setScreenTransform_ = function () {
7035	  this.worldToScreenQ.set(0, 0, 0, 1);
7036	  switch (window.orientation) {
7037		case 0:
7038		  break;
7039		case 90:
7040		  this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI / 2);
7041		  break;
7042		case -90:
7043		  this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2);
7044		  break;
7045	  }
7046	  this.inverseWorldToScreenQ.copy(this.worldToScreenQ);
7047	  this.inverseWorldToScreenQ.inverse();
7048	};
7049	FusionPoseSensor.prototype.start = function () {
7050	  this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this);
7051	  this.onOrientationChangeCallback_ = this.onOrientationChange_.bind(this);
7052	  this.onMessageCallback_ = this.onMessage_.bind(this);
7053	  this.onDeviceOrientationCallback_ = this.onDeviceOrientation_.bind(this);
7054	  if (isIOS() && isInsideCrossOriginIFrame()) {
7055		window.addEventListener('message', this.onMessageCallback_);
7056	  }
7057	  window.addEventListener('orientationchange', this.onOrientationChangeCallback_);
7058	  if (this.isWithoutDeviceMotion) {
7059		window.addEventListener('deviceorientation', this.onDeviceOrientationCallback_);
7060	  } else {
7061		window.addEventListener('devicemotion', this.onDeviceMotionCallback_);
7062	  }
7063	};
7064	FusionPoseSensor.prototype.stop = function () {
7065	  window.removeEventListener('devicemotion', this.onDeviceMotionCallback_);
7066	  window.removeEventListener('deviceorientation', this.onDeviceOrientationCallback_);
7067	  window.removeEventListener('orientationchange', this.onOrientationChangeCallback_);
7068	  window.removeEventListener('message', this.onMessageCallback_);
7069	};
7070	var SENSOR_FREQUENCY = 60;
7071	var X_AXIS = new Vector3(1, 0, 0);
7072	var Z_AXIS = new Vector3(0, 0, 1);
7073	var orientation = {};
7074	if (screen.orientation) {
7075	  orientation = screen.orientation;
7076	} else if (screen.msOrientation) {
7077	  orientation = screen.msOrientation;
7078	} else {
7079	  Object.defineProperty(orientation, 'angle', {
7080		get: function get$$1() {
7081		  return window.orientation || 0;
7082		}
7083	  });
7084	}
7085	var SENSOR_TO_VR = new Quaternion();
7086	SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2);
7087	SENSOR_TO_VR.multiply(new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2));
7088	var PoseSensor = function () {
7089	  function PoseSensor(config) {
7090		classCallCheck(this, PoseSensor);
7091		this.config = config;
7092		this.sensor = null;
7093		this.fusionSensor = null;
7094		this._out = new Float32Array(4);
7095		this.api = null;
7096		this.errors = [];
7097		this._sensorQ = new Quaternion();
7098		this._worldToScreenQ = new Quaternion();
7099		this._outQ = new Quaternion();
7100		this._onSensorRead = this._onSensorRead.bind(this);
7101		this._onSensorError = this._onSensorError.bind(this);
7102		this._onOrientationChange = this._onOrientationChange.bind(this);
7103		this._onOrientationChange();
7104		this.init();
7105	  }
7106	  createClass(PoseSensor, [{
7107		key: 'init',
vendor: 5,556 bytes, lines 7108-7196
7108		value: function init() {
7109		  var sensor = null;
7110		  try {
7111			sensor = new RelativeOrientationSensor({ frequency: SENSOR_FREQUENCY });
7112			sensor.addEventListener('error', this._onSensorError);
7113		  } catch (error) {
7114			this.errors.push(error);
7115			if (error.name === 'SecurityError') {
7116			  console.error('Cannot construct sensors due to the Feature Policy');
7117			  console.warn('Attempting to fall back using "devicemotion"; however this will ' + 'fail in the future without correct permissions.');
7118			  this.useDeviceMotion();
7119			} else if (error.name === 'ReferenceError') {
7120			  this.useDeviceMotion();
7121			} else {
7122			  console.error(error);
7123			}
7124		  }
7125		  if (sensor) {
7126			this.api = 'sensor';
7127			this.sensor = sensor;
7128			this.sensor.addEventListener('reading', this._onSensorRead);
7129			this.sensor.start();
7130		  }
7131		  window.addEventListener('orientationchange', this._onOrientationChange);
7132		}
7133	  }, {
7134		key: 'useDeviceMotion',
7135		value: function useDeviceMotion() {
7136		  this.api = 'devicemotion';
7137		  this.fusionSensor = new FusionPoseSensor(this.config.K_FILTER, this.config.PREDICTION_TIME_S, this.config.YAW_ONLY, this.config.DEBUG);
7138		  if (this.sensor) {
7139			this.sensor.removeEventListener('reading', this._onSensorRead);
7140			this.sensor.removeEventListener('error', this._onSensorError);
7141			this.sensor = null;
7142		  }
7143		}
7144	  }, {
7145		key: 'getOrientation',
7146		value: function getOrientation() {
7147		  if (this.fusionSensor) {
7148			return this.fusionSensor.getOrientation();
7149		  }
7150		  if (!this.sensor || !this.sensor.quaternion) {
7151			this._out[0] = this._out[1] = this._out[2] = 0;
7152			this._out[3] = 1;
7153			return this._out;
7154		  }
7155		  var q = this.sensor.quaternion;
7156		  this._sensorQ.set(q[0], q[1], q[2], q[3]);
7157		  var out = this._outQ;
7158		  out.copy(SENSOR_TO_VR);
7159		  out.multiply(this._sensorQ);
7160		  out.multiply(this._worldToScreenQ);
7161		  if (this.config.YAW_ONLY) {
7162			out.x = out.z = 0;
7163			out.normalize();
7164		  }
7165		  this._out[0] = out.x;
7166		  this._out[1] = out.y;
7167		  this._out[2] = out.z;
7168		  this._out[3] = out.w;
7169		  return this._out;
7170		}
7171	  }, {
7172		key: '_onSensorError',
7173		value: function _onSensorError(event) {
7174		  this.errors.push(event.error);
7175		  if (event.error.name === 'NotAllowedError') {
7176			console.error('Permission to access sensor was denied');
7177		  } else if (event.error.name === 'NotReadableError') {
7178			console.error('Sensor could not be read');
7179		  } else {
7180			console.error(event.error);
7181		  }
7182		  this.useDeviceMotion();
7183		}
7184	  }, {
7185		key: '_onSensorRead',
7186		value: function _onSensorRead() {}
7187	  }, {
7188		key: '_onOrientationChange',
7189		value: function _onOrientationChange() {
7190		  var angle = -orientation.angle * Math.PI / 180;
7191		  this._worldToScreenQ.setFromAxisAngle(Z_AXIS, angle);
7192		}
7193	  }]);
7194	  return PoseSensor;
7195	}();
7196	var rotateInstructionsAsset = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyB
7196DNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCB
7196DMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE
71965LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEM
7196xMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4y
7196MTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzL
7196DE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE
71965Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSB
7196MNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiB
7196MMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2L
7196DY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+';
7197	function RotateInstructions() {
7198	  this.loadIcon_();
7199	  var overlay = document.createElement('div');
7200	  var s = overlay.style;
7201	  s.position = 'fixed';
7202	  s.top = 0;
7203	  s.right = 0;
7204	  s.bottom = 0;
7205	  s.left = 0;
7206	  s.backgroundColor = 'gray';
7207	  s.fontFamily = 'sans-serif';
7208	  s.zIndex = 1000000;
7209	  var img = document.createElement('img');
7210	  img.src = this.icon;
7211	  var s = img.style;
7212	  s.marginLeft = '25%';
7213	  s.marginTop = '25%';
7214	  s.width = '50%';
7215	  overlay.appendChild(img);
7216	  var text = document.createElement('div');
7217	  var s = text.style;
7218	  s.textAlign = 'center';
7219	  s.fontSize = '16px';
7220	  s.lineHeight = '24px';
7221	  s.margin = '24px 25%';
7222	  s.width = '50%';
7223	  text.innerHTML = 'Place your phone into your Cardboard viewer.';
7224	  overlay.appendChild(text);
7225	  var snackbar = document.createElement('div');
7226	  var s = snackbar.style;
7227	  s.backgroundColor = '#CFD8DC';
7228	  s.position = 'fixed';
7229	  s.bottom = 0;
7230	  s.width = '100%';
7231	  s.height = '48px';
7232	  s.padding = '14px 24px';
7233	  s.boxSizing = 'border-box';
7234	  s.color = '#656A6B';
7235	  overlay.appendChild(snackbar);
7236	  var snackbarText = document.createElement('div');
7237	  snackbarText.style.float = 'left';
7238	  snackbarText.innerHTML = 'No Cardboard viewer?';
7239	  var snackbarButton = document.createElement('a');
7240	  snackbarButton.href = 'https://www.google.com/get/cardboard/get-cardboard/';
7241	  snackbarButton.innerHTML = 'get one';
7242	  snackbarButton.target = '_blank';
7243	  var s = snackbarButton.style;
7244	  s.float = 'right';
7245	  s.fontWeight = 600;
7246	  s.textTransform = 'uppercase';
7247	  s.borderLeft = '1px solid gray';
7248	  s.paddingLeft = '24px';
vendor: 4,328 bytes, lines 7249-7384
7249	  s.textDecoration = 'none';
7250	  s.color = '#656A6B';
7251	  snackbar.appendChild(snackbarText);
7252	  snackbar.appendChild(snackbarButton);
7253	  this.overlay = overlay;
7254	  this.text = text;
7255	  this.hide();
7256	}
7257	RotateInstructions.prototype.show = function (parent) {
7258	  if (!parent && !this.overlay.parentElement) {
7259		document.body.appendChild(this.overlay);
7260	  } else if (parent) {
7261		if (this.overlay.parentElement && this.overlay.parentElement != parent) this.overlay.parentElement.removeChild(this.overlay);
7262		parent.appendChild(this.overlay);
7263	  }
7264	  this.overlay.style.display = 'block';
7265	  var img = this.overlay.querySelector('img');
7266	  var s = img.style;
7267	  if (isLandscapeMode()) {
7268		s.width = '20%';
7269		s.marginLeft = '40%';
7270		s.marginTop = '3%';
7271	  } else {
7272		s.width = '50%';
7273		s.marginLeft = '25%';
7274		s.marginTop = '25%';
7275	  }
7276	};
7277	RotateInstructions.prototype.hide = function () {
7278	  this.overlay.style.display = 'none';
7279	};
7280	RotateInstructions.prototype.showTemporarily = function (ms, parent) {
7281	  this.show(parent);
7282	  this.timer = setTimeout(this.hide.bind(this), ms);
7283	};
7284	RotateInstructions.prototype.disableShowTemporarily = function () {
7285	  clearTimeout(this.timer);
7286	};
7287	RotateInstructions.prototype.update = function () {
7288	  this.disableShowTemporarily();
7289	  if (!isLandscapeMode() && isMobile()) {
7290		this.show();
7291	  } else {
7292		this.hide();
7293	  }
7294	};
7295	RotateInstructions.prototype.loadIcon_ = function () {
7296	  this.icon = base64('image/svg+xml', rotateInstructionsAsset);
7297	};
7298	var DEFAULT_VIEWER = 'CardboardV1';
7299	var VIEWER_KEY = 'WEBVR_CARDBOARD_VIEWER';
7300	var CLASS_NAME = 'webvr-polyfill-viewer-selector';
7301	function ViewerSelector(defaultViewer) {
7302	  try {
7303		this.selectedKey = localStorage.getItem(VIEWER_KEY);
7304	  } catch (error) {
7305		console.error('Failed to load viewer profile: %s', error);
7306	  }
7307	  if (!this.selectedKey) {
7308		this.selectedKey = defaultViewer || DEFAULT_VIEWER;
7309	  }
7310	  this.dialog = this.createDialog_(DeviceInfo.Viewers);
7311	  this.root = null;
7312	  this.onChangeCallbacks_ = [];
7313	}
7314	ViewerSelector.prototype.show = function (root) {
7315	  this.root = root;
7316	  root.appendChild(this.dialog);
7317	  var selected = this.dialog.querySelector('#' + this.selectedKey);
7318	  selected.checked = true;
7319	  this.dialog.style.display = 'block';
7320	};
7321	ViewerSelector.prototype.hide = function () {
7322	  if (this.root && this.root.contains(this.dialog)) {
7323		this.root.removeChild(this.dialog);
7324	  }
7325	  this.dialog.style.display = 'none';
7326	};
7327	ViewerSelector.prototype.getCurrentViewer = function () {
7328	  return DeviceInfo.Viewers[this.selectedKey];
7329	};
7330	ViewerSelector.prototype.getSelectedKey_ = function () {
7331	  var input = this.dialog.querySelector('input[name=field]:checked');
7332	  if (input) {
7333		return input.id;
7334	  }
7335	  return null;
7336	};
7337	ViewerSelector.prototype.onChange = function (cb) {
7338	  this.onChangeCallbacks_.push(cb);
7339	};
7340	ViewerSelector.prototype.fireOnChange_ = function (viewer) {
7341	  for (var i = 0; i < this.onChangeCallbacks_.length; i++) {
7342		this.onChangeCallbacks_[i](viewer);
7343	  }
7344	};
7345	ViewerSelector.prototype.onSave_ = function () {
7346	  this.selectedKey = this.getSelectedKey_();
7347	  if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) {
7348		console.error('ViewerSelector.onSave_: this should never happen!');
7349		return;
7350	  }
7351	  this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]);
7352	  try {
7353		localStorage.setItem(VIEWER_KEY, this.selectedKey);
7354	  } catch (error) {
7355		console.error('Failed to save viewer profile: %s', error);
7356	  }
7357	  this.hide();
7358	};
7359	ViewerSelector.prototype.createDialog_ = function (options) {
7360	  var container = document.createElement('div');
7361	  container.classList.add(CLASS_NAME);
7362	  container.style.display = 'none';
7363	  var overlay = document.createElement('div');
7364	  var s = overlay.style;
7365	  s.position = 'fixed';
7366	  s.left = 0;
7367	  s.top = 0;
7368	  s.width = '100%';
7369	  s.height = '100%';
7370	  s.background = 'rgba(0, 0, 0, 0.3)';
7371	  overlay.addEventListener('click', this.hide.bind(this));
7372	  var width = 280;
7373	  var dialog = document.createElement('div');
7374	  var s = dialog.style;
7375	  s.boxSizing = 'border-box';
7376	  s.position = 'fixed';
7377	  s.top = '24px';
7378	  s.left = '50%';
7379	  s.marginLeft = -width / 2 + 'px';
7380	  s.width = width + 'px';
7381	  s.padding = '24px';
7382	  s.overflow = 'hidden';
7383	  s.background = '#fafafa';
7384	  s.fontFamily = "'Roboto', sans-serif";
vendor: 8,869 bytes, lines 7385-7540
7385	  s.boxShadow = '0px 5px 20px #666';
7386	  dialog.appendChild(this.createH1_('Select your viewer'));
7387	  for (var id in options) {
7388		dialog.appendChild(this.createChoice_(id, options[id].label));
7389	  }
7390	  dialog.appendChild(this.createButton_('Save', this.onSave_.bind(this)));
7391	  container.appendChild(overlay);
7392	  container.appendChild(dialog);
7393	  return container;
7394	};
7395	ViewerSelector.prototype.createH1_ = function (name) {
7396	  var h1 = document.createElement('h1');
7397	  var s = h1.style;
7398	  s.color = 'black';
7399	  s.fontSize = '20px';
7400	  s.fontWeight = 'bold';
7401	  s.marginTop = 0;
7402	  s.marginBottom = '24px';
7403	  h1.innerHTML = name;
7404	  return h1;
7405	};
7406	ViewerSelector.prototype.createChoice_ = function (id, name) {
7407	  var div = document.createElement('div');
7408	  div.style.marginTop = '8px';
7409	  div.style.color = 'black';
7410	  var input = document.createElement('input');
7411	  input.style.fontSize = '30px';
7412	  input.setAttribute('id', id);
7413	  input.setAttribute('type', 'radio');
7414	  input.setAttribute('value', id);
7415	  input.setAttribute('name', 'field');
7416	  var label = document.createElement('label');
7417	  label.style.marginLeft = '4px';
7418	  label.setAttribute('for', id);
7419	  label.innerHTML = name;
7420	  div.appendChild(input);
7421	  div.appendChild(label);
7422	  return div;
7423	};
7424	ViewerSelector.prototype.createButton_ = function (label, onclick) {
7425	  var button = document.createElement('button');
7426	  button.innerHTML = label;
7427	  var s = button.style;
7428	  s.float = 'right';
7429	  s.textTransform = 'uppercase';
7430	  s.color = '#1094f7';
7431	  s.fontSize = '14px';
7432	  s.letterSpacing = 0;
7433	  s.border = 0;
7434	  s.background = 'none';
7435	  s.marginTop = '16px';
7436	  button.addEventListener('click', onclick);
7437	  return button;
7438	};
7439	var commonjsGlobal$$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal$1 !== 'undefined' ? commonjsGlobal$1 : typeof self !== 'undefined' ? self : {};
7440	function unwrapExports$$1 (x) {
7441		return x && x.__esModule ? x['default'] : x;
7442	}
7443	function createCommonjsModule$$1(fn, module) {
7444		return module = { exports: {} }, fn(module, module.exports), module.exports;
7445	}
7446	var NoSleep = createCommonjsModule$$1(function (module, exports) {
7447	(function webpackUniversalModuleDefinition(root, factory) {
7448		module.exports = factory();
7449	})(commonjsGlobal$$1, function() {
7450	return          (function(modules) {
7451				 var installedModules = {};
7452				 function __webpack_require__(moduleId) {
7453					 if(installedModules[moduleId]) {
7454						 return installedModules[moduleId].exports;
7455					 }
7456					 var module = installedModules[moduleId] = {
7457						 i: moduleId,
7458						 l: false,
7459						 exports: {}
7460					 };
7461					 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
7462					 module.l = true;
7463					 return module.exports;
7464				 }
7465				 __webpack_require__.m = modules;
7466				 __webpack_require__.c = installedModules;
7467				 __webpack_require__.d = function(exports, name, getter) {
7468					 if(!__webpack_require__.o(exports, name)) {
7469						 Object.defineProperty(exports, name, {
7470							 configurable: false,
7471							 enumerable: true,
7472							 get: getter
7473						 });
7474					 }
7475				 };
7476				 __webpack_require__.n = function(module) {
7477					 var getter = module && module.__esModule ?
7478						 function getDefault() { return module['default']; } :
7479						 function getModuleExports() { return module; };
7480					 __webpack_require__.d(getter, 'a', getter);
7481					 return getter;
7482				 };
7483				 __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
7484				 __webpack_require__.p = "";
7485				 return __webpack_require__(__webpack_require__.s = 0);
7486			 })
7487			 ([
7488		  (function(module, exports, __webpack_require__) {
7489	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
7490	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
7491	var mediaFile = __webpack_require__(1);
7492	var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream;
7493	var NoSleep = function () {
7494	  function NoSleep() {
7495		_classCallCheck(this, NoSleep);
7496		if (oldIOS) {
7497		  this.noSleepTimer = null;
7498		} else {
7499		  this.noSleepVideo = document.createElement('video');
7500		  this.noSleepVideo.setAttribute('playsinline', '');
7501		  this.noSleepVideo.setAttribute('src', mediaFile);
7502		  this.noSleepVideo.addEventListener('timeupdate', function (e) {
7503			if (this.noSleepVideo.currentTime > 0.5) {
7504			  this.noSleepVideo.currentTime = Math.random();
7505			}
7506		  }.bind(this));
7507		}
7508	  }
7509	  _createClass(NoSleep, [{
7510		key: 'enable',
7511		value: function enable() {
7512		  if (oldIOS) {
7513			this.disable();
7514			this.noSleepTimer = window.setInterval(function () {
7515			  window.location.href = '/';
7516			  window.setTimeout(window.stop, 0);
7517			}, 15000);
7518		  } else {
7519			this.noSleepVideo.play();
7520		  }
7521		}
7522	  }, {
7523		key: 'disable',
7524		value: function disable() {
7525		  if (oldIOS) {
7526			if (this.noSleepTimer) {
7527			  window.clearInterval(this.noSleepTimer);
7528			  this.noSleepTimer = null;
7529			}
7530		  } else {
7531			this.noSleepVideo.pause();
7532		  }
7533		}
7534	  }]);
7535	  return NoSleep;
7536	}();
7537	module.exports = NoSleep;
7538		  }),
7539		  (function(module, exports, __webpack_require__) {
7540	module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+U
7540Qn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA=';
7541		  })
7542			 ]);
7543	});
7544	});
7545	var NoSleep$1 = unwrapExports$$1(NoSleep);
7546	var nextDisplayId = 1000;
7547	var defaultLeftBounds = [0, 0, 0.5, 1];
7548	var defaultRightBounds = [0.5, 0, 0.5, 1];
7549	var raf = window.requestAnimationFrame;
7550	var caf = window.cancelAnimationFrame;
7551	function VRFrameData() {
7552	  this.leftProjectionMatrix = new Float32Array(16);
vendor: 23,756 bytes, lines 7553-8221
7553	  this.leftViewMatrix = new Float32Array(16);
7554	  this.rightProjectionMatrix = new Float32Array(16);
7555	  this.rightViewMatrix = new Float32Array(16);
7556	  this.pose = null;
7557	}
7558	function VRDisplayCapabilities(config) {
7559	  Object.defineProperties(this, {
7560		hasPosition: {
7561		  writable: false, enumerable: true, value: config.hasPosition
7562		},
7563		hasExternalDisplay: {
7564		  writable: false, enumerable: true, value: config.hasExternalDisplay
7565		},
7566		canPresent: {
7567		  writable: false, enumerable: true, value: config.canPresent
7568		},
7569		maxLayers: {
7570		  writable: false, enumerable: true, value: config.maxLayers
7571		},
7572		hasOrientation: {
7573		  enumerable: true, get: function get() {
7574			deprecateWarning('VRDisplayCapabilities.prototype.hasOrientation', 'VRDisplay.prototype.getFrameData');
7575			return config.hasOrientation;
7576		  }
7577		}
7578	  });
7579	}
7580	function VRDisplay(config) {
7581	  config = config || {};
7582	  var USE_WAKELOCK = 'wakelock' in config ? config.wakelock : true;
7583	  this.isPolyfilled = true;
7584	  this.displayId = nextDisplayId++;
7585	  this.displayName = '';
7586	  this.depthNear = 0.01;
7587	  this.depthFar = 10000.0;
7588	  this.isPresenting = false;
7589	  Object.defineProperty(this, 'isConnected', {
7590		get: function get() {
7591		  deprecateWarning('VRDisplay.prototype.isConnected', 'VRDisplayCapabilities.prototype.hasExternalDisplay');
7592		  return false;
7593		}
7594	  });
7595	  this.capabilities = new VRDisplayCapabilities({
7596		hasPosition: false,
7597		hasOrientation: false,
7598		hasExternalDisplay: false,
7599		canPresent: false,
7600		maxLayers: 1
7601	  });
7602	  this.stageParameters = null;
7603	  this.waitingForPresent_ = false;
7604	  this.layer_ = null;
7605	  this.originalParent_ = null;
7606	  this.fullscreenElement_ = null;
7607	  this.fullscreenWrapper_ = null;
7608	  this.fullscreenElementCachedStyle_ = null;
7609	  this.fullscreenEventTarget_ = null;
7610	  this.fullscreenChangeHandler_ = null;
7611	  this.fullscreenErrorHandler_ = null;
7612	  if (USE_WAKELOCK && isMobile()) {
7613		this.wakelock_ = new NoSleep$1();
7614	  }
7615	}
7616	VRDisplay.prototype.getFrameData = function (frameData) {
7617	  return frameDataFromPose(frameData, this._getPose(), this);
7618	};
7619	VRDisplay.prototype.getPose = function () {
7620	  deprecateWarning('VRDisplay.prototype.getPose', 'VRDisplay.prototype.getFrameData');
7621	  return this._getPose();
7622	};
7623	VRDisplay.prototype.resetPose = function () {
7624	  deprecateWarning('VRDisplay.prototype.resetPose');
7625	  return this._resetPose();
7626	};
7627	VRDisplay.prototype.getImmediatePose = function () {
7628	  deprecateWarning('VRDisplay.prototype.getImmediatePose', 'VRDisplay.prototype.getFrameData');
7629	  return this._getPose();
7630	};
7631	VRDisplay.prototype.requestAnimationFrame = function (callback) {
7632	  return raf(callback);
7633	};
7634	VRDisplay.prototype.cancelAnimationFrame = function (id) {
7635	  return caf(id);
7636	};
7637	VRDisplay.prototype.wrapForFullscreen = function (element) {
7638	  if (isIOS()) {
7639		return element;
7640	  }
7641	  if (!this.fullscreenWrapper_) {
7642		this.fullscreenWrapper_ = document.createElement('div');
7643		var cssProperties = ['height: ' + Math.min(screen.height, screen.width) + 'px !important', 'top: 0 !important', 'left: 0 !important', 'right: 0 !important', 'border: 0', 'margin: 0', 'padding: 0', 'z-index: 999999 !important', 'position: fixed'];
7644		this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';');
7645		this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper');
7646	  }
7647	  if (this.fullscreenElement_ == element) {
7648		return this.fullscreenWrapper_;
7649	  }
7650	  if (this.fullscreenElement_) {
7651		if (this.originalParent_) {
7652		  this.originalParent_.appendChild(this.fullscreenElement_);
7653		} else {
7654		  this.fullscreenElement_.parentElement.removeChild(this.fullscreenElement_);
7655		}
7656	  }
7657	  this.fullscreenElement_ = element;
7658	  this.originalParent_ = element.parentElement;
7659	  if (!this.originalParent_) {
7660		document.body.appendChild(element);
7661	  }
7662	  if (!this.fullscreenWrapper_.parentElement) {
7663		var parent = this.fullscreenElement_.parentElement;
7664		parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_);
7665		parent.removeChild(this.fullscreenElement_);
7666	  }
7667	  this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild);
7668	  this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style');
7669	  var self = this;
7670	  function applyFullscreenElementStyle() {
7671		if (!self.fullscreenElement_) {
7672		  return;
7673		}
7674		var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 'width: ' + Math.max(screen.width, screen.height) + 'px', 'height: ' + Math.min(screen.height, screen.width) + 'px', 'border: 0', 'margin: 0', 'padding: 0'];
7675		self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';');
7676	  }
7677	  applyFullscreenElementStyle();
7678	  return this.fullscreenWrapper_;
7679	};
7680	VRDisplay.prototype.removeFullscreenWrapper = function () {
7681	  if (!this.fullscreenElement_) {
7682		return;
7683	  }
7684	  var element = this.fullscreenElement_;
7685	  if (this.fullscreenElementCachedStyle_) {
7686		element.setAttribute('style', this.fullscreenElementCachedStyle_);
7687	  } else {
7688		element.removeAttribute('style');
7689	  }
7690	  this.fullscreenElement_ = null;
7691	  this.fullscreenElementCachedStyle_ = null;
7692	  var parent = this.fullscreenWrapper_.parentElement;
7693	  this.fullscreenWrapper_.removeChild(element);
7694	  if (this.originalParent_ === parent) {
7695		parent.insertBefore(element, this.fullscreenWrapper_);
7696	  }
7697	  else if (this.originalParent_) {
7698		  this.originalParent_.appendChild(element);
7699		}
7700	  parent.removeChild(this.fullscreenWrapper_);
7701	  return element;
7702	};
7703	VRDisplay.prototype.requestPresent = function (layers) {
7704	  var wasPresenting = this.isPresenting;
7705	  var self = this;
7706	  if (!(layers instanceof Array)) {
7707		deprecateWarning('VRDisplay.prototype.requestPresent with non-array argument', 'an array of VRLayers as the first argument');
7708		layers = [layers];
7709	  }
7710	  return new Promise(function (resolve, reject) {
7711		if (!self.capabilities.canPresent) {
7712		  reject(new Error('VRDisplay is not capable of presenting.'));
7713		  return;
7714		}
7715		if (layers.length == 0 || layers.length > self.capabilities.maxLayers) {
7716		  reject(new Error('Invalid number of layers.'));
7717		  return;
7718		}
7719		var incomingLayer = layers[0];
7720		if (!incomingLayer.source) {
7721		  resolve();
7722		  return;
7723		}
7724		var leftBounds = incomingLayer.leftBounds || defaultLeftBounds;
7725		var rightBounds = incomingLayer.rightBounds || defaultRightBounds;
7726		if (wasPresenting) {
7727		  var layer = self.layer_;
7728		  if (layer.source !== incomingLayer.source) {
7729			layer.source = incomingLayer.source;
7730		  }
7731		  for (var i = 0; i < 4; i++) {
7732			layer.leftBounds[i] = leftBounds[i];
7733			layer.rightBounds[i] = rightBounds[i];
7734		  }
7735		  self.wrapForFullscreen(self.layer_.source);
7736		  self.updatePresent_();
7737		  resolve();
7738		  return;
7739		}
7740		self.layer_ = {
7741		  predistorted: incomingLayer.predistorted,
7742		  source: incomingLayer.source,
7743		  leftBounds: leftBounds.slice(0),
7744		  rightBounds: rightBounds.slice(0)
7745		};
7746		self.waitingForPresent_ = false;
7747		if (self.layer_ && self.layer_.source) {
7748		  var fullscreenElement = self.wrapForFullscreen(self.layer_.source);
7749		  var onFullscreenChange = function onFullscreenChange() {
7750			var actualFullscreenElement = getFullscreenElement();
7751			self.isPresenting = fullscreenElement === actualFullscreenElement;
7752			if (self.isPresenting) {
7753			  if (screen.orientation && screen.orientation.lock) {
7754				screen.orientation.lock('landscape-primary').catch(function (error) {
7755				  console.error('screen.orientation.lock() failed due to', error.message);
7756				});
7757			  }
7758			  self.waitingForPresent_ = false;
7759			  self.beginPresent_();
7760			  resolve();
7761			} else {
7762			  if (screen.orientation && screen.orientation.unlock) {
7763				screen.orientation.unlock();
7764			  }
7765			  self.removeFullscreenWrapper();
7766			  self.disableWakeLock();
7767			  self.endPresent_();
7768			  self.removeFullscreenListeners_();
7769			}
7770			self.fireVRDisplayPresentChange_();
7771		  };
7772		  var onFullscreenError = function onFullscreenError() {
7773			if (!self.waitingForPresent_) {
7774			  return;
7775			}
7776			self.removeFullscreenWrapper();
7777			self.removeFullscreenListeners_();
7778			self.disableWakeLock();
7779			self.waitingForPresent_ = false;
7780			self.isPresenting = false;
7781			reject(new Error('Unable to present.'));
7782		  };
7783		  self.addFullscreenListeners_(fullscreenElement, onFullscreenChange, onFullscreenError);
7784		  if (requestFullscreen(fullscreenElement)) {
7785			self.enableWakeLock();
7786			self.waitingForPresent_ = true;
7787		  } else if (isIOS() || isWebViewAndroid()) {
7788			self.enableWakeLock();
7789			self.isPresenting = true;
7790			self.beginPresent_();
7791			self.fireVRDisplayPresentChange_();
7792			resolve();
7793		  }
7794		}
7795		if (!self.waitingForPresent_ && !isIOS()) {
7796		  exitFullscreen();
7797		  reject(new Error('Unable to present.'));
7798		}
7799	  });
7800	};
7801	VRDisplay.prototype.exitPresent = function () {
7802	  var wasPresenting = this.isPresenting;
7803	  var self = this;
7804	  this.isPresenting = false;
7805	  this.layer_ = null;
7806	  this.disableWakeLock();
7807	  return new Promise(function (resolve, reject) {
7808		if (wasPresenting) {
7809		  if (!exitFullscreen() && isIOS()) {
7810			self.endPresent_();
7811			self.fireVRDisplayPresentChange_();
7812		  }
7813		  if (isWebViewAndroid()) {
7814			self.removeFullscreenWrapper();
7815			self.removeFullscreenListeners_();
7816			self.endPresent_();
7817			self.fireVRDisplayPresentChange_();
7818		  }
7819		  resolve();
7820		} else {
7821		  reject(new Error('Was not presenting to VRDisplay.'));
7822		}
7823	  });
7824	};
7825	VRDisplay.prototype.getLayers = function () {
7826	  if (this.layer_) {
7827		return [this.layer_];
7828	  }
7829	  return [];
7830	};
7831	VRDisplay.prototype.fireVRDisplayPresentChange_ = function () {
7832	  var event = new CustomEvent('vrdisplaypresentchange', { detail: { display: this } });
7833	  window.dispatchEvent(event);
7834	};
7835	VRDisplay.prototype.fireVRDisplayConnect_ = function () {
7836	  var event = new CustomEvent('vrdisplayconnect', { detail: { display: this } });
7837	  window.dispatchEvent(event);
7838	};
7839	VRDisplay.prototype.addFullscreenListeners_ = function (element, changeHandler, errorHandler) {
7840	  this.removeFullscreenListeners_();
7841	  this.fullscreenEventTarget_ = element;
7842	  this.fullscreenChangeHandler_ = changeHandler;
7843	  this.fullscreenErrorHandler_ = errorHandler;
7844	  if (changeHandler) {
7845		if (document.fullscreenEnabled) {
7846		  element.addEventListener('fullscreenchange', changeHandler, false);
7847		} else if (document.webkitFullscreenEnabled) {
7848		  element.addEventListener('webkitfullscreenchange', changeHandler, false);
7849		} else if (document.mozFullScreenEnabled) {
7850		  document.addEventListener('mozfullscreenchange', changeHandler, false);
7851		} else if (document.msFullscreenEnabled) {
7852		  element.addEventListener('msfullscreenchange', changeHandler, false);
7853		}
7854	  }
7855	  if (errorHandler) {
7856		if (document.fullscreenEnabled) {
7857		  element.addEventListener('fullscreenerror', errorHandler, false);
7858		} else if (document.webkitFullscreenEnabled) {
7859		  element.addEventListener('webkitfullscreenerror', errorHandler, false);
7860		} else if (document.mozFullScreenEnabled) {
7861		  document.addEventListener('mozfullscreenerror', errorHandler, false);
7862		} else if (document.msFullscreenEnabled) {
7863		  element.addEventListener('msfullscreenerror', errorHandler, false);
7864		}
7865	  }
7866	};
7867	VRDisplay.prototype.removeFullscreenListeners_ = function () {
7868	  if (!this.fullscreenEventTarget_) return;
7869	  var element = this.fullscreenEventTarget_;
7870	  if (this.fullscreenChangeHandler_) {
7871		var changeHandler = this.fullscreenChangeHandler_;
7872		element.removeEventListener('fullscreenchange', changeHandler, false);
7873		element.removeEventListener('webkitfullscreenchange', changeHandler, false);
7874		document.removeEventListener('mozfullscreenchange', changeHandler, false);
7875		element.removeEventListener('msfullscreenchange', changeHandler, false);
7876	  }
7877	  if (this.fullscreenErrorHandler_) {
7878		var errorHandler = this.fullscreenErrorHandler_;
7879		element.removeEventListener('fullscreenerror', errorHandler, false);
7880		element.removeEventListener('webkitfullscreenerror', errorHandler, false);
7881		document.removeEventListener('mozfullscreenerror', errorHandler, false);
7882		element.removeEventListener('msfullscreenerror', errorHandler, false);
7883	  }
7884	  this.fullscreenEventTarget_ = null;
7885	  this.fullscreenChangeHandler_ = null;
7886	  this.fullscreenErrorHandler_ = null;
7887	};
7888	VRDisplay.prototype.enableWakeLock = function () {
7889	  if (this.wakelock_) {
7890		this.wakelock_.enable();
7891	  }
7892	};
7893	VRDisplay.prototype.disableWakeLock = function () {
7894	  if (this.wakelock_) {
7895		this.wakelock_.disable();
7896	  }
7897	};
7898	VRDisplay.prototype.beginPresent_ = function () {
7899	};
7900	VRDisplay.prototype.endPresent_ = function () {
7901	};
7902	VRDisplay.prototype.submitFrame = function (pose) {
7903	};
7904	VRDisplay.prototype.getEyeParameters = function (whichEye) {
7905	  return null;
7906	};
7907	var config = {
7908	  ADDITIONAL_VIEWERS: [],
7909	  DEFAULT_VIEWER: '',
7910	  MOBILE_WAKE_LOCK: true,
7911	  DEBUG: false,
7912	  DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json',
7913	  K_FILTER: 0.98,
7914	  PREDICTION_TIME_S: 0.040,
7915	  CARDBOARD_UI_DISABLED: false,
7916	  ROTATE_INSTRUCTIONS_DISABLED: false,
7917	  YAW_ONLY: false,
7918	  BUFFER_SCALE: 0.5,
7919	  DIRTY_SUBMIT_FRAME_BINDINGS: false
7920	};
7921	var Eye = {
7922	  LEFT: 'left',
7923	  RIGHT: 'right'
7924	};
7925	function CardboardVRDisplay(config$$1) {
7926	  var defaults = extend({}, config);
7927	  config$$1 = extend(defaults, config$$1 || {});
7928	  VRDisplay.call(this, {
7929		wakelock: config$$1.MOBILE_WAKE_LOCK
7930	  });
7931	  this.config = config$$1;
7932	  this.displayName = 'Cardboard VRDisplay';
7933	  this.capabilities = new VRDisplayCapabilities({
7934		hasPosition: false,
7935		hasOrientation: true,
7936		hasExternalDisplay: false,
7937		canPresent: true,
7938		maxLayers: 1
7939	  });
7940	  this.stageParameters = null;
7941	  this.bufferScale_ = this.config.BUFFER_SCALE;
7942	  this.poseSensor_ = new PoseSensor(this.config);
7943	  this.distorter_ = null;
7944	  this.cardboardUI_ = null;
7945	  this.dpdb_ = new Dpdb(this.config.DPDB_URL, this.onDeviceParamsUpdated_.bind(this));
7946	  this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams(), config$$1.ADDITIONAL_VIEWERS);
7947	  this.viewerSelector_ = new ViewerSelector(config$$1.DEFAULT_VIEWER);
7948	  this.viewerSelector_.onChange(this.onViewerChanged_.bind(this));
7949	  this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer());
7950	  if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) {
7951		this.rotateInstructions_ = new RotateInstructions();
7952	  }
7953	  if (isIOS()) {
7954		window.addEventListener('resize', this.onResize_.bind(this));
7955	  }
7956	}
7957	CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype);
7958	CardboardVRDisplay.prototype._getPose = function () {
7959	  return {
7960		position: null,
7961		orientation: this.poseSensor_.getOrientation(),
7962		linearVelocity: null,
7963		linearAcceleration: null,
7964		angularVelocity: null,
7965		angularAcceleration: null
7966	  };
7967	};
7968	CardboardVRDisplay.prototype._resetPose = function () {
7969	  if (this.poseSensor_.resetPose) {
7970		this.poseSensor_.resetPose();
7971	  }
7972	};
7973	CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) {
7974	  var fieldOfView;
7975	  if (whichEye == Eye.LEFT) {
7976		fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye();
7977	  } else if (whichEye == Eye.RIGHT) {
7978		fieldOfView = this.deviceInfo_.getFieldOfViewRightEye();
7979	  } else {
7980		console.error('Invalid eye provided: %s', whichEye);
7981		return null;
7982	  }
7983	  return fieldOfView;
7984	};
7985	CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) {
7986	  var offset;
7987	  if (whichEye == Eye.LEFT) {
7988		offset = [-this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
7989	  } else if (whichEye == Eye.RIGHT) {
7990		offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
7991	  } else {
7992		console.error('Invalid eye provided: %s', whichEye);
7993		return null;
7994	  }
7995	  return offset;
7996	};
7997	CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) {
7998	  var offset = this._getEyeOffset(whichEye);
7999	  var fieldOfView = this._getFieldOfView(whichEye);
8000	  var eyeParams = {
8001		offset: offset,
8002		renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_,
8003		renderHeight: this.deviceInfo_.device.height * this.bufferScale_
8004	  };
8005	  Object.defineProperty(eyeParams, 'fieldOfView', {
8006		enumerable: true,
8007		get: function get() {
8008		  deprecateWarning('VRFieldOfView', 'VRFrameData\'s projection matrices');
8009		  return fieldOfView;
8010		}
8011	  });
8012	  return eyeParams;
8013	};
8014	CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function (newParams) {
8015	  if (this.config.DEBUG) {
8016		console.log('DPDB reported that device params were updated.');
8017	  }
8018	  this.deviceInfo_.updateDeviceParams(newParams);
8019	  if (this.distorter_) {
8020		this.distorter_.updateDeviceInfo(this.deviceInfo_);
8021	  }
8022	};
8023	CardboardVRDisplay.prototype.updateBounds_ = function () {
8024	  if (this.layer_ && this.distorter_ && (this.layer_.leftBounds || this.layer_.rightBounds)) {
8025		this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds);
8026	  }
8027	};
8028	CardboardVRDisplay.prototype.beginPresent_ = function () {
8029	  var gl = this.layer_.source.getContext('webgl');
8030	  if (!gl) gl = this.layer_.source.getContext('experimental-webgl');
8031	  if (!gl) gl = this.layer_.source.getContext('webgl2');
8032	  if (!gl) return;
8033	  if (this.layer_.predistorted) {
8034		if (!this.config.CARDBOARD_UI_DISABLED) {
8035		  gl.canvas.width = getScreenWidth() * this.bufferScale_;
8036		  gl.canvas.height = getScreenHeight() * this.bufferScale_;
8037		  this.cardboardUI_ = new CardboardUI(gl);
8038		}
8039	  } else {
8040		if (!this.config.CARDBOARD_UI_DISABLED) {
8041		  this.cardboardUI_ = new CardboardUI(gl);
8042		}
8043		this.distorter_ = new CardboardDistorter(gl, this.cardboardUI_, this.config.BUFFER_SCALE, this.config.DIRTY_SUBMIT_FRAME_BINDINGS);
8044		this.distorter_.updateDeviceInfo(this.deviceInfo_);
8045	  }
8046	  if (this.cardboardUI_) {
8047		this.cardboardUI_.listen(function (e) {
8048		  this.viewerSelector_.show(this.layer_.source.parentElement);
8049		  e.stopPropagation();
8050		  e.preventDefault();
8051		}.bind(this), function (e) {
8052		  this.exitPresent();
8053		  e.stopPropagation();
8054		  e.preventDefault();
8055		}.bind(this));
8056	  }
8057	  if (this.rotateInstructions_) {
8058		if (isLandscapeMode() && isMobile()) {
8059		  this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement);
8060		} else {
8061		  this.rotateInstructions_.update();
8062		}
8063	  }
8064	  this.orientationHandler = this.onOrientationChange_.bind(this);
8065	  window.addEventListener('orientationchange', this.orientationHandler);
8066	  this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this);
8067	  window.addEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler);
8068	  this.fireVRDisplayDeviceParamsChange_();
8069	};
8070	CardboardVRDisplay.prototype.endPresent_ = function () {
8071	  if (this.distorter_) {
8072		this.distorter_.destroy();
8073		this.distorter_ = null;
8074	  }
8075	  if (this.cardboardUI_) {
8076		this.cardboardUI_.destroy();
8077		this.cardboardUI_ = null;
8078	  }
8079	  if (this.rotateInstructions_) {
8080		this.rotateInstructions_.hide();
8081	  }
8082	  this.viewerSelector_.hide();
8083	  window.removeEventListener('orientationchange', this.orientationHandler);
8084	  window.removeEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler);
8085	};
8086	CardboardVRDisplay.prototype.updatePresent_ = function () {
8087	  this.endPresent_();
8088	  this.beginPresent_();
8089	};
8090	CardboardVRDisplay.prototype.submitFrame = function (pose) {
8091	  if (this.distorter_) {
8092		this.updateBounds_();
8093		this.distorter_.submitFrame();
8094	  } else if (this.cardboardUI_ && this.layer_) {
8095		var canvas = this.layer_.source.getContext('webgl').canvas;
8096		if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) {
8097		  this.cardboardUI_.onResize();
8098		}
8099		this.lastWidth = canvas.width;
8100		this.lastHeight = canvas.height;
8101		this.cardboardUI_.render();
8102	  }
8103	};
8104	CardboardVRDisplay.prototype.onOrientationChange_ = function (e) {
8105	  this.viewerSelector_.hide();
8106	  if (this.rotateInstructions_) {
8107		this.rotateInstructions_.update();
8108	  }
8109	  this.onResize_();
8110	};
8111	CardboardVRDisplay.prototype.onResize_ = function (e) {
8112	  if (this.layer_) {
8113		var gl = this.layer_.source.getContext('webgl');
8114		var cssProperties = ['position: absolute', 'top: 0', 'left: 0',
8115		'width: 100vw', 'height: 100vh', 'border: 0', 'margin: 0',
8116		'padding: 0px', 'box-sizing: content-box'];
8117		gl.canvas.setAttribute('style', cssProperties.join('; ') + ';');
8118		safariCssSizeWorkaround(gl.canvas);
8119	  }
8120	};
8121	CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) {
8122	  this.deviceInfo_.setViewer(viewer);
8123	  if (this.distorter_) {
8124		this.distorter_.updateDeviceInfo(this.deviceInfo_);
8125	  }
8126	  this.fireVRDisplayDeviceParamsChange_();
8127	};
8128	CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function () {
8129	  var event = new CustomEvent('vrdisplaydeviceparamschange', {
8130		detail: {
8131		  vrdisplay: this,
8132		  deviceInfo: this.deviceInfo_
8133		}
8134	  });
8135	  window.dispatchEvent(event);
8136	};
8137	CardboardVRDisplay.VRFrameData = VRFrameData;
8138	CardboardVRDisplay.VRDisplay = VRDisplay;
8139	return CardboardVRDisplay;
8140	})));
8141	});
8142	var CardboardVRDisplay = unwrapExports(cardboardVrDisplay);
8143  
8144	var version = "0.10.6";
8145  
8146	var DefaultConfig = {
8147	  ADDITIONAL_VIEWERS: [],
8148	  DEFAULT_VIEWER: '',
8149	  PROVIDE_MOBILE_VRDISPLAY: true,
8150	  GET_VR_DISPLAYS_TIMEOUT: 1000,
8151	  MOBILE_WAKE_LOCK: true,
8152	  DEBUG: false,
8153	  DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json',
8154	  K_FILTER: 0.98,
8155	  PREDICTION_TIME_S: 0.040,
8156	  TOUCH_PANNER_DISABLED: true,
8157	  CARDBOARD_UI_DISABLED: false,
8158	  ROTATE_INSTRUCTIONS_DISABLED: false,
8159	  YAW_ONLY: false,
8160	  BUFFER_SCALE: 0.5,
8161	  DIRTY_SUBMIT_FRAME_BINDINGS: false
8162	};
8163  
8164	function WebVRPolyfill(config) {
8165	  this.config = extend(extend({}, DefaultConfig), config);
8166	  this.polyfillDisplays = [];
8167	  this.enabled = false;
8168	  this.hasNative = 'getVRDisplays' in navigator;
8169	  this.native = {};
8170	  this.native.getVRDisplays = navigator.getVRDisplays;
8171	  this.native.VRFrameData = window.VRFrameData;
8172	  this.native.VRDisplay = window.VRDisplay;
8173	  if (!this.hasNative || this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) {
8174		this.enable();
8175		this.getVRDisplays().then(function (displays) {
8176		  if (displays && displays[0] && displays[0].fireVRDisplayConnect_) {
8177			displays[0].fireVRDisplayConnect_();
8178		  }
8179		});
8180	  }
8181	}
8182	WebVRPolyfill.prototype.getPolyfillDisplays = function () {
8183	  if (this._polyfillDisplaysPopulated) {
8184		return this.polyfillDisplays;
8185	  }
8186	  if (isMobile()) {
8187		var vrDisplay = new CardboardVRDisplay({
8188		  ADDITIONAL_VIEWERS: this.config.ADDITIONAL_VIEWERS,
8189		  DEFAULT_VIEWER: this.config.DEFAULT_VIEWER,
8190		  MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK,
8191		  DEBUG: this.config.DEBUG,
8192		  DPDB_URL: this.config.DPDB_URL,
8193		  CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED,
8194		  K_FILTER: this.config.K_FILTER,
8195		  PREDICTION_TIME_S: this.config.PREDICTION_TIME_S,
8196		  TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED,
8197		  ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED,
8198		  YAW_ONLY: this.config.YAW_ONLY,
8199		  BUFFER_SCALE: this.config.BUFFER_SCALE,
8200		  DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS
8201		});
8202		this.polyfillDisplays.push(vrDisplay);
8203	  }
8204	  this._polyfillDisplaysPopulated = true;
8205	  return this.polyfillDisplays;
8206	};
8207	WebVRPolyfill.prototype.enable = function () {
8208	  this.enabled = true;
8209	  if (this.hasNative && this.native.VRFrameData) {
8210		var NativeVRFrameData = this.native.VRFrameData;
8211		var nativeFrameData = new this.native.VRFrameData();
8212		var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData;
8213		window.VRDisplay.prototype.getFrameData = function (frameData) {
8214		  if (frameData instanceof NativeVRFrameData) {
8215			nativeGetFrameData.call(this, frameData);
8216			return;
8217		  }
8218		  nativeGetFrameData.call(this, nativeFrameData);
8219		  frameData.pose = nativeFrameData.pose;
8220		  copyArray(nativeFrameData.leftProjectionMatrix, frameData.leftProjectionMatrix);
8221		  copyArray(nativeFrameData.rightProjectionMatrix, frameData.rightProjectionMatrix);
8222		  copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix);
8223		  copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix);
8224		};
8225	  }
8226	  navigator.getVRDisplays = this.getVRDisplays.bind(this);
8227	  window.VRDisplay = CardboardVRDisplay.VRDisplay;
8228	  window.VRFrameData = CardboardVRDisplay.VRFrameData;
8229	};
8230	WebVRPolyfill.prototype.getVRDisplays = function () {
8231	  var _this = this;
8232	  var config = this.config;
8233	  if (!this.hasNative) {
8234		return Promise.resolve(this.getPolyfillDisplays());
8235	  }
8236	  var timeoutId;
8237	  var vrDisplaysNative = this.native.getVRDisplays.call(navigator);
8238	  var timeoutPromise = new Promise(function (resolve) {
8239		timeoutId = setTimeout(function () {
8240		  console.warn('Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill.');
8241		  resolve([]);
8242		}, config.GET_VR_DISPLAYS_TIMEOUT);
8243	  });
8244	  return race([vrDisplaysNative, timeoutPromise]).then(function (nativeDisplays) {
8245		clearTimeout(timeoutId);
8246		return nativeDisplays.length > 0 ? nativeDisplays : _this.getPolyfillDisplays();
8247	  });
8248	};
8249	WebVRPolyfill.version = version;
8250	WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData;
8251	WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay;
8252  
8253  
8254	var webvrPolyfill = Object.freeze({
8255		default: WebVRPolyfill
8256	});
8257  
8258	var require$$0 = ( webvrPolyfill && WebVRPolyfill ) || webvrPolyfill;
8259  
8260	if (typeof commonjsGlobal$1 !== 'undefined' && commonjsGlobal$1.window) {
8261	  if (!commonjsGlobal$1.document) {
8262		commonjsGlobal$1.document = commonjsGlobal$1.window.document;
8263	  }
8264	  if (!commonjsGlobal$1.navigator) {
8265		commonjsGlobal$1.navigator = commonjsGlobal$1.window.navigator;
8266	  }
8267	}
8268	var src = require$$0;
8269  
8270	return src;
8271  
8272	})));
8273	});
8274  
8275	var WebVRPolyfill = unwrapExports(webvrPolyfill);
8276  
8277	// Polyfills
8278  
8279	if ( Number.EPSILON === undefined ) {
8280  
8281		Number.EPSILON = Math.pow( 2, - 52 );
8282  
8283	}
8284  
8285	if ( Number.isInteger === undefined ) {
8286  
8287		// Missing in IE
8288		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
8289  
8290		Number.isInteger = function ( value ) {
8291  
8292			return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
8293  
8294		};
8295  
8296	}
8297  
8298	//
8299  
8300	if ( Math.sign === undefined ) {
8301  
8302		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
8303  
8304		Math.sign = function ( x ) {
8305  
8306			return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
8307  
8308		};
8309  
8310	}
8311  
8312	if ( 'name' in Function.prototype === false ) {
8313  
8314		// Missing in IE
8315		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
8316  
8317		Object.defineProperty( Function.prototype, 'name', {
8318  
8319			get: function () {
8320  
8321				return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
8322  
8323			}
8324  
8325		} );
8326  
8327	}
8328  
8329	if ( Object.assign === undefined ) {
8330  
8331		// Missing in IE
8332		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
8333  
8334		( function () {
8335  
8336			Object.assign = function ( target ) {
8337  
8338				if ( target === undefined || target === null ) {
8339  
8340					throw new TypeError( 'Cannot convert undefined or null to object' );
8341  
8342				}
8343  
8344				var output = Object( target );
8345  
8346				for ( var index = 1; index < arguments.length; index ++ ) {
8347  
8348					var source = arguments[ index ];
8349  
8350					if ( source !== undefined && source !== null ) {
8351  
8352						for ( var nextKey in source ) {
8353  
8354							if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
8355  
8356								output[ nextKey ] = source[ nextKey ];
8357  
8358							}
8359  
8360						}
8361  
8362					}
8363  
8364				}
8365  
8366				return output;
8367  
8368			};
8369  
8370		} )();
8371  
8372	}
8373  
8374	/**
8375	 * https://github.com/mrdoob/eventdispatcher.js/
8376	 */
8377  
8378	function EventDispatcher() {}
8379  
8380	Object.assign( EventDispatcher.prototype, {
8381  
vendor: 22,083 bytes, lines 8382-9520
8382		addEventListener: function ( type, listener ) {
8383  
8384			if ( this._listeners === undefined ) this._listeners = {};
8385  
8386			var listeners = this._listeners;
8387  
8388			if ( listeners[ type ] === undefined ) {
8389  
8390				listeners[ type ] = [];
8391  
8392			}
8393  
8394			if ( listeners[ type ].indexOf( listener ) === - 1 ) {
8395  
8396				listeners[ type ].push( listener );
8397  
8398			}
8399  
8400		},
8401  
8402		hasEventListener: function ( type, listener ) {
8403  
8404			if ( this._listeners === undefined ) return false;
8405  
8406			var listeners = this._listeners;
8407  
8408			return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
8409  
8410		},
8411  
8412		removeEventListener: function ( type, listener ) {
8413  
8414			if ( this._listeners === undefined ) return;
8415  
8416			var listeners = this._listeners;
8417			var listenerArray = listeners[ type ];
8418  
8419			if ( listenerArray !== undefined ) {
8420  
8421				var index = listenerArray.indexOf( listener );
8422  
8423				if ( index !== - 1 ) {
8424  
8425					listenerArray.splice( index, 1 );
8426  
8427				}
8428  
8429			}
8430  
8431		},
8432  
8433		dispatchEvent: function ( event ) {
8434  
8435			if ( this._listeners === undefined ) return;
8436  
8437			var listeners = this._listeners;
8438			var listenerArray = listeners[ event.type ];
8439  
8440			if ( listenerArray !== undefined ) {
8441  
8442				event.target = this;
8443  
8444				var array = listenerArray.slice( 0 );
8445  
8446				for ( var i = 0, l = array.length; i < l; i ++ ) {
8447  
8448					array[ i ].call( this, event );
8449  
8450				}
8451  
8452			}
8453  
8454		}
8455  
8456	} );
8457  
8458	var REVISION = '93';
8459	var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
8460	var CullFaceNone = 0;
8461	var CullFaceBack = 1;
8462	var CullFaceFront = 2;
8463	var PCFShadowMap = 1;
8464	var PCFSoftShadowMap = 2;
8465	var FrontSide = 0;
8466	var BackSide = 1;
8467	var DoubleSide = 2;
8468	var FlatShading = 1;
8469	var NoColors = 0;
8470	var FaceColors = 1;
8471	var VertexColors = 2;
8472	var NoBlending = 0;
8473	var NormalBlending = 1;
8474	var AdditiveBlending = 2;
8475	var SubtractiveBlending = 3;
8476	var MultiplyBlending = 4;
8477	var CustomBlending = 5;
8478	var AddEquation = 100;
8479	var SubtractEquation = 101;
8480	var ReverseSubtractEquation = 102;
8481	var MinEquation = 103;
8482	var MaxEquation = 104;
8483	var ZeroFactor = 200;
8484	var OneFactor = 201;
8485	var SrcColorFactor = 202;
8486	var OneMinusSrcColorFactor = 203;
8487	var SrcAlphaFactor = 204;
8488	var OneMinusSrcAlphaFactor = 205;
8489	var DstAlphaFactor = 206;
8490	var OneMinusDstAlphaFactor = 207;
8491	var DstColorFactor = 208;
8492	var OneMinusDstColorFactor = 209;
8493	var SrcAlphaSaturateFactor = 210;
8494	var NeverDepth = 0;
8495	var AlwaysDepth = 1;
8496	var LessDepth = 2;
8497	var LessEqualDepth = 3;
8498	var EqualDepth = 4;
8499	var GreaterEqualDepth = 5;
8500	var GreaterDepth = 6;
8501	var NotEqualDepth = 7;
8502	var MultiplyOperation = 0;
8503	var MixOperation = 1;
8504	var AddOperation = 2;
8505	var NoToneMapping = 0;
8506	var LinearToneMapping = 1;
8507	var ReinhardToneMapping = 2;
8508	var Uncharted2ToneMapping = 3;
8509	var CineonToneMapping = 4;
8510	var UVMapping = 300;
8511	var CubeReflectionMapping = 301;
8512	var CubeRefractionMapping = 302;
8513	var EquirectangularReflectionMapping = 303;
8514	var EquirectangularRefractionMapping = 304;
8515	var SphericalReflectionMapping = 305;
8516	var CubeUVReflectionMapping = 306;
8517	var CubeUVRefractionMapping = 307;
8518	var RepeatWrapping = 1000;
8519	var ClampToEdgeWrapping = 1001;
8520	var MirroredRepeatWrapping = 1002;
8521	var NearestFilter = 1003;
8522	var NearestMipMapNearestFilter = 1004;
8523	var NearestMipMapLinearFilter = 1005;
8524	var LinearFilter = 1006;
8525	var LinearMipMapNearestFilter = 1007;
8526	var LinearMipMapLinearFilter = 1008;
8527	var UnsignedByteType = 1009;
8528	var ByteType = 1010;
8529	var ShortType = 1011;
8530	var UnsignedShortType = 1012;
8531	var IntType = 1013;
8532	var UnsignedIntType = 1014;
8533	var FloatType = 1015;
8534	var HalfFloatType = 1016;
8535	var UnsignedShort4444Type = 1017;
8536	var UnsignedShort5551Type = 1018;
8537	var UnsignedShort565Type = 1019;
8538	var UnsignedInt248Type = 1020;
8539	var AlphaFormat = 1021;
8540	var RGBFormat = 1022;
8541	var RGBAFormat = 1023;
8542	var LuminanceFormat = 1024;
8543	var LuminanceAlphaFormat = 1025;
8544	var DepthFormat = 1026;
8545	var DepthStencilFormat = 1027;
8546	var RGB_S3TC_DXT1_Format = 33776;
8547	var RGBA_S3TC_DXT1_Format = 33777;
8548	var RGBA_S3TC_DXT3_Format = 33778;
8549	var RGBA_S3TC_DXT5_Format = 33779;
8550	var RGB_PVRTC_4BPPV1_Format = 35840;
8551	var RGB_PVRTC_2BPPV1_Format = 35841;
8552	var RGBA_PVRTC_4BPPV1_Format = 35842;
8553	var RGBA_PVRTC_2BPPV1_Format = 35843;
8554	var RGB_ETC1_Format = 36196;
8555	var RGBA_ASTC_4x4_Format = 37808;
8556	var RGBA_ASTC_5x4_Format = 37809;
8557	var RGBA_ASTC_5x5_Format = 37810;
8558	var RGBA_ASTC_6x5_Format = 37811;
8559	var RGBA_ASTC_6x6_Format = 37812;
8560	var RGBA_ASTC_8x5_Format = 37813;
8561	var RGBA_ASTC_8x6_Format = 37814;
8562	var RGBA_ASTC_8x8_Format = 37815;
8563	var RGBA_ASTC_10x5_Format = 37816;
8564	var RGBA_ASTC_10x6_Format = 37817;
8565	var RGBA_ASTC_10x8_Format = 37818;
8566	var RGBA_ASTC_10x10_Format = 37819;
8567	var RGBA_ASTC_12x10_Format = 37820;
8568	var RGBA_ASTC_12x12_Format = 37821;
8569	var LoopOnce = 2200;
8570	var LoopRepeat = 2201;
8571	var LoopPingPong = 2202;
8572	var InterpolateDiscrete = 2300;
8573	var InterpolateLinear = 2301;
8574	var InterpolateSmooth = 2302;
8575	var ZeroCurvatureEnding = 2400;
8576	var ZeroSlopeEnding = 2401;
8577	var WrapAroundEnding = 2402;
8578	var TrianglesDrawMode = 0;
8579	var TriangleStripDrawMode = 1;
8580	var TriangleFanDrawMode = 2;
8581	var LinearEncoding = 3000;
8582	var sRGBEncoding = 3001;
8583	var GammaEncoding = 3007;
8584	var RGBEEncoding = 3002;
8585	var RGBM7Encoding = 3004;
8586	var RGBM16Encoding = 3005;
8587	var RGBDEncoding = 3006;
8588	var BasicDepthPacking = 3200;
8589	var RGBADepthPacking = 3201;
8590  
8591	/**
8592	 * @author alteredq / http://alteredqualia.com/
8593	 * @author mrdoob / http://mrdoob.com/
8594	 */
8595  
8596	var _Math = {
8597  
8598		DEG2RAD: Math.PI / 180,
8599		RAD2DEG: 180 / Math.PI,
8600  
8601		generateUUID: ( function () {
8602  
8603			// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
8604  
8605			var lut = [];
8606  
8607			for ( var i = 0; i < 256; i ++ ) {
8608  
8609				lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
8610  
8611			}
8612  
8613			return function generateUUID() {
8614  
8615				var d0 = Math.random() * 0xffffffff | 0;
8616				var d1 = Math.random() * 0xffffffff | 0;
8617				var d2 = Math.random() * 0xffffffff | 0;
8618				var d3 = Math.random() * 0xffffffff | 0;
8619				var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
8620					lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
8621					lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
8622					lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
8623  
8624				// .toUpperCase() here flattens concatenated strings to save heap memory space.
8625				return uuid.toUpperCase();
8626  
8627			};
8628  
8629		} )(),
8630  
8631		clamp: function ( value, min, max ) {
8632  
8633			return Math.max( min, Math.min( max, value ) );
8634  
8635		},
8636  
8637		// compute euclidian modulo of m % n
8638		// https://en.wikipedia.org/wiki/Modulo_operation
8639  
8640		euclideanModulo: function ( n, m ) {
8641  
8642			return ( ( n % m ) + m ) % m;
8643  
8644		},
8645  
8646		// Linear mapping from range <a1, a2> to range <b1, b2>
8647  
8648		mapLinear: function ( x, a1, a2, b1, b2 ) {
8649  
8650			return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
8651  
8652		},
8653  
8654		// https://en.wikipedia.org/wiki/Linear_interpolation
8655  
8656		lerp: function ( x, y, t ) {
8657  
8658			return ( 1 - t ) * x + t * y;
8659  
8660		},
8661  
8662		// http://en.wikipedia.org/wiki/Smoothstep
8663  
8664		smoothstep: function ( x, min, max ) {
8665  
8666			if ( x <= min ) return 0;
8667			if ( x >= max ) return 1;
8668  
8669			x = ( x - min ) / ( max - min );
8670  
8671			return x * x * ( 3 - 2 * x );
8672  
8673		},
8674  
8675		smootherstep: function ( x, min, max ) {
8676  
8677			if ( x <= min ) return 0;
8678			if ( x >= max ) return 1;
8679  
8680			x = ( x - min ) / ( max - min );
8681  
8682			return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
8683  
8684		},
8685  
8686		// Random integer from <low, high> interval
8687  
8688		randInt: function ( low, high ) {
8689  
8690			return low + Math.floor( Math.random() * ( high - low + 1 ) );
8691  
8692		},
8693  
8694		// Random float from <low, high> interval
8695  
8696		randFloat: function ( low, high ) {
8697  
8698			return low + Math.random() * ( high - low );
8699  
8700		},
8701  
8702		// Random float from <-range/2, range/2> interval
8703  
8704		randFloatSpread: function ( range ) {
8705  
8706			return range * ( 0.5 - Math.random() );
8707  
8708		},
8709  
8710		degToRad: function ( degrees ) {
8711  
8712			return degrees * _Math.DEG2RAD;
8713  
8714		},
8715  
8716		radToDeg: function ( radians ) {
8717  
8718			return radians * _Math.RAD2DEG;
8719  
8720		},
8721  
8722		isPowerOfTwo: function ( value ) {
8723  
8724			return ( value & ( value - 1 ) ) === 0 && value !== 0;
8725  
8726		},
8727  
8728		ceilPowerOfTwo: function ( value ) {
8729  
8730			return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
8731  
8732		},
8733  
8734		floorPowerOfTwo: function ( value ) {
8735  
8736			return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
8737  
8738		}
8739  
8740	};
8741  
8742	/**
8743	 * @author mrdoob / http://mrdoob.com/
8744	 * @author philogb / http://blog.thejit.org/
8745	 * @author egraether / http://egraether.com/
8746	 * @author zz85 / http://www.lab4games.net/zz85/blog
8747	 */
8748  
8749	function Vector2( x, y ) {
8750  
8751		this.x = x || 0;
8752		this.y = y || 0;
8753  
8754	}
8755  
8756	Object.defineProperties( Vector2.prototype, {
8757  
8758		"width": {
8759  
8760			get: function () {
8761  
8762				return this.x;
8763  
8764			},
8765  
8766			set: function ( value ) {
8767  
8768				this.x = value;
8769  
8770			}
8771  
8772		},
8773  
8774		"height": {
8775  
8776			get: function () {
8777  
8778				return this.y;
8779  
8780			},
8781  
8782			set: function ( value ) {
8783  
8784				this.y = value;
8785  
8786			}
8787  
8788		}
8789  
8790	} );
8791  
8792	Object.assign( Vector2.prototype, {
8793  
8794		isVector2: true,
8795  
8796		set: function ( x, y ) {
8797  
8798			this.x = x;
8799			this.y = y;
8800  
8801			return this;
8802  
8803		},
8804  
8805		setScalar: function ( scalar ) {
8806  
8807			this.x = scalar;
8808			this.y = scalar;
8809  
8810			return this;
8811  
8812		},
8813  
8814		setX: function ( x ) {
8815  
8816			this.x = x;
8817  
8818			return this;
8819  
8820		},
8821  
8822		setY: function ( y ) {
8823  
8824			this.y = y;
8825  
8826			return this;
8827  
8828		},
8829  
8830		setComponent: function ( index, value ) {
8831  
8832			switch ( index ) {
8833  
8834				case 0: this.x = value; break;
8835				case 1: this.y = value; break;
8836				default: throw new Error( 'index is out of range: ' + index );
8837  
8838			}
8839  
8840			return this;
8841  
8842		},
8843  
8844		getComponent: function ( index ) {
8845  
8846			switch ( index ) {
8847  
8848				case 0: return this.x;
8849				case 1: return this.y;
8850				default: throw new Error( 'index is out of range: ' + index );
8851  
8852			}
8853  
8854		},
8855  
8856		clone: function () {
8857  
8858			return new this.constructor( this.x, this.y );
8859  
8860		},
8861  
8862		copy: function ( v ) {
8863  
8864			this.x = v.x;
8865			this.y = v.y;
8866  
8867			return this;
8868  
8869		},
8870  
8871		add: function ( v, w ) {
8872  
8873			if ( w !== undefined ) {
8874  
8875				console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
8876				return this.addVectors( v, w );
8877  
8878			}
8879  
8880			this.x += v.x;
8881			this.y += v.y;
8882  
8883			return this;
8884  
8885		},
8886  
8887		addScalar: function ( s ) {
8888  
8889			this.x += s;
8890			this.y += s;
8891  
8892			return this;
8893  
8894		},
8895  
8896		addVectors: function ( a, b ) {
8897  
8898			this.x = a.x + b.x;
8899			this.y = a.y + b.y;
8900  
8901			return this;
8902  
8903		},
8904  
8905		addScaledVector: function ( v, s ) {
8906  
8907			this.x += v.x * s;
8908			this.y += v.y * s;
8909  
8910			return this;
8911  
8912		},
8913  
8914		sub: function ( v, w ) {
8915  
8916			if ( w !== undefined ) {
8917  
8918				console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
8919				return this.subVectors( v, w );
8920  
8921			}
8922  
8923			this.x -= v.x;
8924			this.y -= v.y;
8925  
8926			return this;
8927  
8928		},
8929  
8930		subScalar: function ( s ) {
8931  
8932			this.x -= s;
8933			this.y -= s;
8934  
8935			return this;
8936  
8937		},
8938  
8939		subVectors: function ( a, b ) {
8940  
8941			this.x = a.x - b.x;
8942			this.y = a.y - b.y;
8943  
8944			return this;
8945  
8946		},
8947  
8948		multiply: function ( v ) {
8949  
8950			this.x *= v.x;
8951			this.y *= v.y;
8952  
8953			return this;
8954  
8955		},
8956  
8957		multiplyScalar: function ( scalar ) {
8958  
8959			this.x *= scalar;
8960			this.y *= scalar;
8961  
8962			return this;
8963  
8964		},
8965  
8966		divide: function ( v ) {
8967  
8968			this.x /= v.x;
8969			this.y /= v.y;
8970  
8971			return this;
8972  
8973		},
8974  
8975		divideScalar: function ( scalar ) {
8976  
8977			return this.multiplyScalar( 1 / scalar );
8978  
8979		},
8980  
8981		applyMatrix3: function ( m ) {
8982  
8983			var x = this.x, y = this.y;
8984			var e = m.elements;
8985  
8986			this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
8987			this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
8988  
8989			return this;
8990  
8991		},
8992  
8993		min: function ( v ) {
8994  
8995			this.x = Math.min( this.x, v.x );
8996			this.y = Math.min( this.y, v.y );
8997  
8998			return this;
8999  
9000		},
9001  
9002		max: function ( v ) {
9003  
9004			this.x = Math.max( this.x, v.x );
9005			this.y = Math.max( this.y, v.y );
9006  
9007			return this;
9008  
9009		},
9010  
9011		clamp: function ( min, max ) {
9012  
9013			// assumes min < max, componentwise
9014  
9015			this.x = Math.max( min.x, Math.min( max.x, this.x ) );
9016			this.y = Math.max( min.y, Math.min( max.y, this.y ) );
9017  
9018			return this;
9019  
9020		},
9021  
9022		clampScalar: function () {
9023  
9024			var min = new Vector2();
9025			var max = new Vector2();
9026  
9027			return function clampScalar( minVal, maxVal ) {
9028  
9029				min.set( minVal, minVal );
9030				max.set( maxVal, maxVal );
9031  
9032				return this.clamp( min, max );
9033  
9034			};
9035  
9036		}(),
9037  
9038		clampLength: function ( min, max ) {
9039  
9040			var length = this.length();
9041  
9042			return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
9043  
9044		},
9045  
9046		floor: function () {
9047  
9048			this.x = Math.floor( this.x );
9049			this.y = Math.floor( this.y );
9050  
9051			return this;
9052  
9053		},
9054  
9055		ceil: function () {
9056  
9057			this.x = Math.ceil( this.x );
9058			this.y = Math.ceil( this.y );
9059  
9060			return this;
9061  
9062		},
9063  
9064		round: function () {
9065  
9066			this.x = Math.round( this.x );
9067			this.y = Math.round( this.y );
9068  
9069			return this;
9070  
9071		},
9072  
9073		roundToZero: function () {
9074  
9075			this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
9076			this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
9077  
9078			return this;
9079  
9080		},
9081  
9082		negate: function () {
9083  
9084			this.x = - this.x;
9085			this.y = - this.y;
9086  
9087			return this;
9088  
9089		},
9090  
9091		dot: function ( v ) {
9092  
9093			return this.x * v.x + this.y * v.y;
9094  
9095		},
9096  
9097		lengthSq: function () {
9098  
9099			return this.x * this.x + this.y * this.y;
9100  
9101		},
9102  
9103		length: function () {
9104  
9105			return Math.sqrt( this.x * this.x + this.y * this.y );
9106  
9107		},
9108  
9109		manhattanLength: function () {
9110  
9111			return Math.abs( this.x ) + Math.abs( this.y );
9112  
9113		},
9114  
9115		normalize: function () {
9116  
9117			return this.divideScalar( this.length() || 1 );
9118  
9119		},
9120  
9121		angle: function () {
9122  
9123			// computes the angle in radians with respect to the positive x-axis
9124  
9125			var angle = Math.atan2( this.y, this.x );
9126  
9127			if ( angle < 0 ) angle += 2 * Math.PI;
9128  
9129			return angle;
9130  
9131		},
9132  
9133		distanceTo: function ( v ) {
9134  
9135			return Math.sqrt( this.distanceToSquared( v ) );
9136  
9137		},
9138  
9139		distanceToSquared: function ( v ) {
9140  
9141			var dx = this.x - v.x, dy = this.y - v.y;
9142			return dx * dx + dy * dy;
9143  
9144		},
9145  
9146		manhattanDistanceTo: function ( v ) {
9147  
9148			return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
9149  
9150		},
9151  
9152		setLength: function ( length ) {
9153  
9154			return this.normalize().multiplyScalar( length );
9155  
9156		},
9157  
9158		lerp: function ( v, alpha ) {
9159  
9160			this.x += ( v.x - this.x ) * alpha;
9161			this.y += ( v.y - this.y ) * alpha;
9162  
9163			return this;
9164  
9165		},
9166  
9167		lerpVectors: function ( v1, v2, alpha ) {
9168  
9169			return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
9170  
9171		},
9172  
9173		equals: function ( v ) {
9174  
9175			return ( ( v.x === this.x ) && ( v.y === this.y ) );
9176  
9177		},
9178  
9179		fromArray: function ( array, offset ) {
9180  
9181			if ( offset === undefined ) offset = 0;
9182  
9183			this.x = array[ offset ];
9184			this.y = array[ offset + 1 ];
9185  
9186			return this;
9187  
9188		},
9189  
9190		toArray: function ( array, offset ) {
9191  
9192			if ( array === undefined ) array = [];
9193			if ( offset === undefined ) offset = 0;
9194  
9195			array[ offset ] = this.x;
9196			array[ offset + 1 ] = this.y;
9197  
9198			return array;
9199  
9200		},
9201  
9202		fromBufferAttribute: function ( attribute, index, offset ) {
9203  
9204			if ( offset !== undefined ) {
9205  
9206				console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
9207  
9208			}
9209  
9210			this.x = attribute.getX( index );
9211			this.y = attribute.getY( index );
9212  
9213			return this;
9214  
9215		},
9216  
9217		rotateAround: function ( center, angle ) {
9218  
9219			var c = Math.cos( angle ), s = Math.sin( angle );
9220  
9221			var x = this.x - center.x;
9222			var y = this.y - center.y;
9223  
9224			this.x = x * c - y * s + center.x;
9225			this.y = x * s + y * c + center.y;
9226  
9227			return this;
9228  
9229		}
9230  
9231	} );
9232  
9233	/**
9234	 * @author mrdoob / http://mrdoob.com/
9235	 * @author supereggbert / http://www.paulbrunt.co.uk/
9236	 * @author philogb / http://blog.thejit.org/
9237	 * @author jordi_ros / http://plattsoft.com
9238	 * @author D1plo1d / http://github.com/D1plo1d
9239	 * @author alteredq / http://alteredqualia.com/
9240	 * @author mikael emtinger / http://gomo.se/
9241	 * @author timknip / http://www.floorplanner.com/
9242	 * @author bhouston / http://clara.io
9243	 * @author WestLangley / http://github.com/WestLangley
9244	 */
9245  
9246	function Matrix4() {
9247  
9248		this.elements = [
9249  
9250			1, 0, 0, 0,
9251			0, 1, 0, 0,
9252			0, 0, 1, 0,
9253			0, 0, 0, 1
9254  
9255		];
9256  
9257		if ( arguments.length > 0 ) {
9258  
9259			console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
9260  
9261		}
9262  
9263	}
9264  
9265	Object.assign( Matrix4.prototype, {
9266  
9267		isMatrix4: true,
9268  
9269		set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
9270  
9271			var te = this.elements;
9272  
9273			te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
9274			te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
9275			te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
9276			te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
9277  
9278			return this;
9279  
9280		},
9281  
9282		identity: function () {
9283  
9284			this.set(
9285  
9286				1, 0, 0, 0,
9287				0, 1, 0, 0,
9288				0, 0, 1, 0,
9289				0, 0, 0, 1
9290  
9291			);
9292  
9293			return this;
9294  
9295		},
9296  
9297		clone: function () {
9298  
9299			return new Matrix4().fromArray( this.elements );
9300  
9301		},
9302  
9303		copy: function ( m ) {
9304  
9305			var te = this.elements;
9306			var me = m.elements;
9307  
9308			te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
9309			te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
9310			te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
9311			te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
9312  
9313			return this;
9314  
9315		},
9316  
9317		copyPosition: function ( m ) {
9318  
9319			var te = this.elements, me = m.elements;
9320  
9321			te[ 12 ] = me[ 12 ];
9322			te[ 13 ] = me[ 13 ];
9323			te[ 14 ] = me[ 14 ];
9324  
9325			return this;
9326  
9327		},
9328  
9329		extractBasis: function ( xAxis, yAxis, zAxis ) {
9330  
9331			xAxis.setFromMatrixColumn( this, 0 );
9332			yAxis.setFromMatrixColumn( this, 1 );
9333			zAxis.setFromMatrixColumn( this, 2 );
9334  
9335			return this;
9336  
9337		},
9338  
9339		makeBasis: function ( xAxis, yAxis, zAxis ) {
9340  
9341			this.set(
9342				xAxis.x, yAxis.x, zAxis.x, 0,
9343				xAxis.y, yAxis.y, zAxis.y, 0,
9344				xAxis.z, yAxis.z, zAxis.z, 0,
9345				0, 0, 0, 1
9346			);
9347  
9348			return this;
9349  
9350		},
9351  
9352		extractRotation: function () {
9353  
9354			var v1 = new Vector3();
9355  
9356			return function extractRotation( m ) {
9357  
9358				// this method does not support reflection matrices
9359  
9360				var te = this.elements;
9361				var me = m.elements;
9362  
9363				var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
9364				var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
9365				var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
9366  
9367				te[ 0 ] = me[ 0 ] * scaleX;
9368				te[ 1 ] = me[ 1 ] * scaleX;
9369				te[ 2 ] = me[ 2 ] * scaleX;
9370				te[ 3 ] = 0;
9371  
9372				te[ 4 ] = me[ 4 ] * scaleY;
9373				te[ 5 ] = me[ 5 ] * scaleY;
9374				te[ 6 ] = me[ 6 ] * scaleY;
9375				te[ 7 ] = 0;
9376  
9377				te[ 8 ] = me[ 8 ] * scaleZ;
9378				te[ 9 ] = me[ 9 ] * scaleZ;
9379				te[ 10 ] = me[ 10 ] * scaleZ;
9380				te[ 11 ] = 0;
9381  
9382				te[ 12 ] = 0;
9383				te[ 13 ] = 0;
9384				te[ 14 ] = 0;
9385				te[ 15 ] = 1;
9386  
9387				return this;
9388  
9389			};
9390  
9391		}(),
9392  
9393		makeRotationFromEuler: function ( euler ) {
9394  
9395			if ( ! ( euler && euler.isEuler ) ) {
9396  
9397				console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
9398  
9399			}
9400  
9401			var te = this.elements;
9402  
9403			var x = euler.x, y = euler.y, z = euler.z;
9404			var a = Math.cos( x ), b = Math.sin( x );
9405			var c = Math.cos( y ), d = Math.sin( y );
9406			var e = Math.cos( z ), f = Math.sin( z );
9407  
9408			if ( euler.order === 'XYZ' ) {
9409  
9410				var ae = a * e, af = a * f, be = b * e, bf = b * f;
9411  
9412				te[ 0 ] = c * e;
9413				te[ 4 ] = - c * f;
9414				te[ 8 ] = d;
9415  
9416				te[ 1 ] = af + be * d;
9417				te[ 5 ] = ae - bf * d;
9418				te[ 9 ] = - b * c;
9419  
9420				te[ 2 ] = bf - ae * d;
9421				te[ 6 ] = be + af * d;
9422				te[ 10 ] = a * c;
9423  
9424			} else if ( euler.order === 'YXZ' ) {
9425  
9426				var ce = c * e, cf = c * f, de = d * e, df = d * f;
9427  
9428				te[ 0 ] = ce + df * b;
9429				te[ 4 ] = de * b - cf;
9430				te[ 8 ] = a * d;
9431  
9432				te[ 1 ] = a * f;
9433				te[ 5 ] = a * e;
9434				te[ 9 ] = - b;
9435  
9436				te[ 2 ] = cf * b - de;
9437				te[ 6 ] = df + ce * b;
9438				te[ 10 ] = a * c;
9439  
9440			} else if ( euler.order === 'ZXY' ) {
9441  
9442				var ce = c * e, cf = c * f, de = d * e, df = d * f;
9443  
9444				te[ 0 ] = ce - df * b;
9445				te[ 4 ] = - a * f;
9446				te[ 8 ] = de + cf * b;
9447  
9448				te[ 1 ] = cf + de * b;
9449				te[ 5 ] = a * e;
9450				te[ 9 ] = df - ce * b;
9451  
9452				te[ 2 ] = - a * d;
9453				te[ 6 ] = b;
9454				te[ 10 ] = a * c;
9455  
9456			} else if ( euler.order === 'ZYX' ) {
9457  
9458				var ae = a * e, af = a * f, be = b * e, bf = b * f;
9459  
9460				te[ 0 ] = c * e;
9461				te[ 4 ] = be * d - af;
9462				te[ 8 ] = ae * d + bf;
9463  
9464				te[ 1 ] = c * f;
9465				te[ 5 ] = bf * d + ae;
9466				te[ 9 ] = af * d - be;
9467  
9468				te[ 2 ] = - d;
9469				te[ 6 ] = b * c;
9470				te[ 10 ] = a * c;
9471  
9472			} else if ( euler.order === 'YZX' ) {
9473  
9474				var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
9475  
9476				te[ 0 ] = c * e;
9477				te[ 4 ] = bd - ac * f;
9478				te[ 8 ] = bc * f + ad;
9479  
9480				te[ 1 ] = f;
9481				te[ 5 ] = a * e;
9482				te[ 9 ] = - b * e;
9483  
9484				te[ 2 ] = - d * e;
9485				te[ 6 ] = ad * f + bc;
9486				te[ 10 ] = ac - bd * f;
9487  
9488			} else if ( euler.order === 'XZY' ) {
9489  
9490				var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
9491  
9492				te[ 0 ] = c * e;
9493				te[ 4 ] = - f;
9494				te[ 8 ] = d * e;
9495  
9496				te[ 1 ] = ac * f + bd;
9497				te[ 5 ] = a * e;
9498				te[ 9 ] = ad * f - bc;
9499  
9500				te[ 2 ] = bc * f - ad;
9501				te[ 6 ] = b * e;
9502				te[ 10 ] = bd * f + ac;
9503  
9504			}
9505  
9506			// bottom row
9507			te[ 3 ] = 0;
9508			te[ 7 ] = 0;
9509			te[ 11 ] = 0;
9510  
9511			// last column
9512			te[ 12 ] = 0;
9513			te[ 13 ] = 0;
9514			te[ 14 ] = 0;
9515			te[ 15 ] = 1;
9516  
9517			return this;
9518  
9519		},
9520  
9521		makeRotationFromQuaternion: function () {
9522  
9523			var zero = new Vector3( 0, 0, 0 );
9524			var one = new Vector3( 1, 1, 1 );
9525  
9526			return function makeRotationFromQuaternion( q ) {
9527  
9528				return this.compose( zero, q, one );
9529  
9530			};
9531  
9532		}(),
9533  
9534		lookAt: function () {
9535  
9536			var x = new Vector3();
9537			var y = new Vector3();
9538			var z = new Vector3();
9539  
9540			return function lookAt( eye, target, up ) {
9541  
9542				var te = this.elements;
9543  
9544				z.subVectors( eye, target );
9545  
9546				if ( z.lengthSq() === 0 ) {
9547  
9548					// eye and target are in the same position
9549  
9550					z.z = 1;
9551  
9552				}
9553  
9554				z.normalize();
9555				x.crossVectors( up, z );
9556  
9557				if ( x.lengthSq() === 0 ) {
9558  
9559					// up and z are parallel
9560  
9561					if ( Math.abs( up.z ) === 1 ) {
9562  
9563						z.x += 0.0001;
9564  
9565					} else {
9566  
9567						z.z += 0.0001;
9568  
9569					}
9570  
9571					z.normalize();
9572					x.crossVectors( up, z );
9573  
9574				}
9575  
9576				x.normalize();
9577				y.crossVectors( z, x );
9578  
9579				te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
9580				te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
9581				te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
9582  
9583				return this;
9584  
9585			};
9586  
9587		}(),
9588  
9589		multiply: function ( m, n ) {
9590  
9591			if ( n !== undefined ) {
9592  
9593				console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
9594				return this.multiplyMatrices( m, n );
9595  
9596			}
9597  
9598			return this.multiplyMatrices( this, m );
9599  
9600		},
9601  
9602		premultiply: function ( m ) {
9603  
9604			return this.multiplyMatrices( m, this );
9605  
9606		},
9607  
9608		multiplyMatrices: function ( a, b ) {
9609  
9610			var ae = a.elements;
9611			var be = b.elements;
9612			var te = this.elements;
9613  
9614			var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
9615			var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
9616			var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
9617			var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
9618  
9619			var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
9620			var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
9621			var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
9622			var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
9623  
9624			te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
9625			te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
9626			te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
9627			te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
9628  
9629			te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
9630			te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
9631			te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
9632			te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
9633  
9634			te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
9635			te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
9636			te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
9637			te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
9638  
9639			te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
9640			te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
9641			te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
9642			te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
9643  
9644			return this;
9645  
9646		},
9647  
9648		multiplyScalar: function ( s ) {
9649  
9650			var te = this.elements;
9651  
9652			te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
9653			te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
9654			te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
9655			te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
9656  
9657			return this;
9658  
9659		},
9660  
9661		applyToBufferAttribute: function () {
9662  
9663			var v1 = new Vector3();
9664  
9665			return function applyToBufferAttribute( attribute ) {
9666  
9667				for ( var i = 0, l = attribute.count; i < l; i ++ ) {
9668  
9669					v1.x = attribute.getX( i );
9670					v1.y = attribute.getY( i );
9671					v1.z = attribute.getZ( i );
9672  
9673					v1.applyMatrix4( this );
9674  
9675					attribute.setXYZ( i, v1.x, v1.y, v1.z );
9676  
9677				}
9678  
9679				return attribute;
9680  
9681			};
9682  
9683		}(),
9684  
9685		determinant: function () {
9686  
9687			var te = this.elements;
9688  
9689			var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
9690			var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
9691			var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
9692			var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
9693  
9694			//TODO: make this more efficient
9695			//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
9696  
9697			return (
9698				n41 * (
9699					+ n14 * n23 * n32
9700					 - n13 * n24 * n32
9701					 - n14 * n22 * n33
9702					 + n12 * n24 * n33
9703					 + n13 * n22 * n34
9704					 - n12 * n23 * n34
9705				) +
9706				n42 * (
9707					+ n11 * n23 * n34
9708					 - n11 * n24 * n33
9709					 + n14 * n21 * n33
9710					 - n13 * n21 * n34
9711					 + n13 * n24 * n31
9712					 - n14 * n23 * n31
9713				) +
9714				n43 * (
9715					+ n11 * n24 * n32
9716					 - n11 * n22 * n34
9717					 - n14 * n21 * n32
9718					 + n12 * n21 * n34
9719					 + n14 * n22 * n31
9720					 - n12 * n24 * n31
9721				) +
9722				n44 * (
9723					- n13 * n22 * n31
9724					 - n11 * n23 * n32
9725					 + n11 * n22 * n33
9726					 + n13 * n21 * n32
9727					 - n12 * n21 * n33
9728					 + n12 * n23 * n31
9729				)
9730  
9731			);
9732  
9733		},
9734  
vendor: 31,485 bytes, lines 9735-11274
9735		transpose: function () {
9736  
9737			var te = this.elements;
9738			var tmp;
9739  
9740			tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
9741			tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
9742			tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
9743  
9744			tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
9745			tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
9746			tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
9747  
9748			return this;
9749  
9750		},
9751  
9752		setPosition: function ( v ) {
9753  
9754			var te = this.elements;
9755  
9756			te[ 12 ] = v.x;
9757			te[ 13 ] = v.y;
9758			te[ 14 ] = v.z;
9759  
9760			return this;
9761  
9762		},
9763  
9764		getInverse: function ( m, throwOnDegenerate ) {
9765  
9766			// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
9767			var te = this.elements,
9768				me = m.elements,
9769  
9770				n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
9771				n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
9772				n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
9773				n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
9774  
9775				t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
9776				t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
9777				t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
9778				t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
9779  
9780			var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
9781  
9782			if ( det === 0 ) {
9783  
9784				var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
9785  
9786				if ( throwOnDegenerate === true ) {
9787  
9788					throw new Error( msg );
9789  
9790				} else {
9791  
9792					console.warn( msg );
9793  
9794				}
9795  
9796				return this.identity();
9797  
9798			}
9799  
9800			var detInv = 1 / det;
9801  
9802			te[ 0 ] = t11 * detInv;
9803			te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
9804			te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
9805			te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
9806  
9807			te[ 4 ] = t12 * detInv;
9808			te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
9809			te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
9810			te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
9811  
9812			te[ 8 ] = t13 * detInv;
9813			te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
9814			te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
9815			te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
9816  
9817			te[ 12 ] = t14 * detInv;
9818			te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
9819			te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
9820			te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
9821  
9822			return this;
9823  
9824		},
9825  
9826		scale: function ( v ) {
9827  
9828			var te = this.elements;
9829			var x = v.x, y = v.y, z = v.z;
9830  
9831			te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
9832			te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
9833			te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
9834			te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
9835  
9836			return this;
9837  
9838		},
9839  
9840		getMaxScaleOnAxis: function () {
9841  
9842			var te = this.elements;
9843  
9844			var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
9845			var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
9846			var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
9847  
9848			return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
9849  
9850		},
9851  
9852		makeTranslation: function ( x, y, z ) {
9853  
9854			this.set(
9855  
9856				1, 0, 0, x,
9857				0, 1, 0, y,
9858				0, 0, 1, z,
9859				0, 0, 0, 1
9860  
9861			);
9862  
9863			return this;
9864  
9865		},
9866  
9867		makeRotationX: function ( theta ) {
9868  
9869			var c = Math.cos( theta ), s = Math.sin( theta );
9870  
9871			this.set(
9872  
9873				1, 0, 0, 0,
9874				0, c, - s, 0,
9875				0, s, c, 0,
9876				0, 0, 0, 1
9877  
9878			);
9879  
9880			return this;
9881  
9882		},
9883  
9884		makeRotationY: function ( theta ) {
9885  
9886			var c = Math.cos( theta ), s = Math.sin( theta );
9887  
9888			this.set(
9889  
9890				 c, 0, s, 0,
9891				 0, 1, 0, 0,
9892				- s, 0, c, 0,
9893				 0, 0, 0, 1
9894  
9895			);
9896  
9897			return this;
9898  
9899		},
9900  
9901		makeRotationZ: function ( theta ) {
9902  
9903			var c = Math.cos( theta ), s = Math.sin( theta );
9904  
9905			this.set(
9906  
9907				c, - s, 0, 0,
9908				s, c, 0, 0,
9909				0, 0, 1, 0,
9910				0, 0, 0, 1
9911  
9912			);
9913  
9914			return this;
9915  
9916		},
9917  
9918		makeRotationAxis: function ( axis, angle ) {
9919  
9920			// Based on http://www.gamedev.net/reference/articles/article1199.asp
9921  
9922			var c = Math.cos( angle );
9923			var s = Math.sin( angle );
9924			var t = 1 - c;
9925			var x = axis.x, y = axis.y, z = axis.z;
9926			var tx = t * x, ty = t * y;
9927  
9928			this.set(
9929  
9930				tx * x + c, tx * y - s * z, tx * z + s * y, 0,
9931				tx * y + s * z, ty * y + c, ty * z - s * x, 0,
9932				tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
9933				0, 0, 0, 1
9934  
9935			);
9936  
9937			 return this;
9938  
9939		},
9940  
9941		makeScale: function ( x, y, z ) {
9942  
9943			this.set(
9944  
9945				x, 0, 0, 0,
9946				0, y, 0, 0,
9947				0, 0, z, 0,
9948				0, 0, 0, 1
9949  
9950			);
9951  
9952			return this;
9953  
9954		},
9955  
9956		makeShear: function ( x, y, z ) {
9957  
9958			this.set(
9959  
9960				1, y, z, 0,
9961				x, 1, z, 0,
9962				x, y, 1, 0,
9963				0, 0, 0, 1
9964  
9965			);
9966  
9967			return this;
9968  
9969		},
9970  
9971		compose: function ( position, quaternion, scale ) {
9972  
9973			var te = this.elements;
9974  
9975			var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
9976			var x2 = x + x,	y2 = y + y, z2 = z + z;
9977			var xx = x * x2, xy = x * y2, xz = x * z2;
9978			var yy = y * y2, yz = y * z2, zz = z * z2;
9979			var wx = w * x2, wy = w * y2, wz = w * z2;
9980  
9981			var sx = scale.x, sy = scale.y, sz = scale.z;
9982  
9983				te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
9984				te[ 1 ] = ( xy + wz ) * sx;
9985				te[ 2 ] = ( xz - wy ) * sx;
9986				te[ 3 ] = 0;
9987  
9988				te[ 4 ] = ( xy - wz ) * sy;
9989				te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
9990				te[ 6 ] = ( yz + wx ) * sy;
9991				te[ 7 ] = 0;
9992  
9993				te[ 8 ] = ( xz + wy ) * sz;
9994				te[ 9 ] = ( yz - wx ) * sz;
9995				te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
9996				te[ 11 ] = 0;
9997  
9998				te[ 12 ] = position.x;
9999				te[ 13 ] = position.y;
10000				te[ 14 ] = position.z;
10001				te[ 15 ] = 1;
10002  
10003				return this;
10004  
10005		},
10006  
10007		decompose: function () {
10008  
10009			var vector = new Vector3();
10010			var matrix = new Matrix4();
10011  
10012			return function decompose( position, quaternion, scale ) {
10013  
10014				var te = this.elements;
10015  
10016				var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
10017				var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
10018				var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
10019  
10020				// if determine is negative, we need to invert one scale
10021				var det = this.determinant();
10022				if ( det < 0 ) sx = - sx;
10023  
10024				position.x = te[ 12 ];
10025				position.y = te[ 13 ];
10026				position.z = te[ 14 ];
10027  
10028				// scale the rotation part
10029				matrix.copy( this );
10030  
10031				var invSX = 1 / sx;
10032				var invSY = 1 / sy;
10033				var invSZ = 1 / sz;
10034  
10035				matrix.elements[ 0 ] *= invSX;
10036				matrix.elements[ 1 ] *= invSX;
10037				matrix.elements[ 2 ] *= invSX;
10038  
10039				matrix.elements[ 4 ] *= invSY;
10040				matrix.elements[ 5 ] *= invSY;
10041				matrix.elements[ 6 ] *= invSY;
10042  
10043				matrix.elements[ 8 ] *= invSZ;
10044				matrix.elements[ 9 ] *= invSZ;
10045				matrix.elements[ 10 ] *= invSZ;
10046  
10047				quaternion.setFromRotationMatrix( matrix );
10048  
10049				scale.x = sx;
10050				scale.y = sy;
10051				scale.z = sz;
10052  
10053				return this;
10054  
10055			};
10056  
10057		}(),
10058  
10059		makePerspective: function ( left, right, top, bottom, near, far ) {
10060  
10061			if ( far === undefined ) {
10062  
10063				console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
10064  
10065			}
10066  
10067			var te = this.elements;
10068			var x = 2 * near / ( right - left );
10069			var y = 2 * near / ( top - bottom );
10070  
10071			var a = ( right + left ) / ( right - left );
10072			var b = ( top + bottom ) / ( top - bottom );
10073			var c = - ( far + near ) / ( far - near );
10074			var d = - 2 * far * near / ( far - near );
10075  
10076			te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
10077			te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
10078			te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
10079			te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
10080  
10081			return this;
10082  
10083		},
10084  
10085		makeOrthographic: function ( left, right, top, bottom, near, far ) {
10086  
10087			var te = this.elements;
10088			var w = 1.0 / ( right - left );
10089			var h = 1.0 / ( top - bottom );
10090			var p = 1.0 / ( far - near );
10091  
10092			var x = ( right + left ) * w;
10093			var y = ( top + bottom ) * h;
10094			var z = ( far + near ) * p;
10095  
10096			te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
10097			te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
10098			te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 2 * p;	te[ 14 ] = - z;
10099			te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
10100  
10101			return this;
10102  
10103		},
10104  
10105		equals: function ( matrix ) {
10106  
10107			var te = this.elements;
10108			var me = matrix.elements;
10109  
10110			for ( var i = 0; i < 16; i ++ ) {
10111  
10112				if ( te[ i ] !== me[ i ] ) return false;
10113  
10114			}
10115  
10116			return true;
10117  
10118		},
10119  
10120		fromArray: function ( array, offset ) {
10121  
10122			if ( offset === undefined ) offset = 0;
10123  
10124			for ( var i = 0; i < 16; i ++ ) {
10125  
10126				this.elements[ i ] = array[ i + offset ];
10127  
10128			}
10129  
10130			return this;
10131  
10132		},
10133  
10134		toArray: function ( array, offset ) {
10135  
10136			if ( array === undefined ) array = [];
10137			if ( offset === undefined ) offset = 0;
10138  
10139			var te = this.elements;
10140  
10141			array[ offset ] = te[ 0 ];
10142			array[ offset + 1 ] = te[ 1 ];
10143			array[ offset + 2 ] = te[ 2 ];
10144			array[ offset + 3 ] = te[ 3 ];
10145  
10146			array[ offset + 4 ] = te[ 4 ];
10147			array[ offset + 5 ] = te[ 5 ];
10148			array[ offset + 6 ] = te[ 6 ];
10149			array[ offset + 7 ] = te[ 7 ];
10150  
10151			array[ offset + 8 ] = te[ 8 ];
10152			array[ offset + 9 ] = te[ 9 ];
10153			array[ offset + 10 ] = te[ 10 ];
10154			array[ offset + 11 ] = te[ 11 ];
10155  
10156			array[ offset + 12 ] = te[ 12 ];
10157			array[ offset + 13 ] = te[ 13 ];
10158			array[ offset + 14 ] = te[ 14 ];
10159			array[ offset + 15 ] = te[ 15 ];
10160  
10161			return array;
10162  
10163		}
10164  
10165	} );
10166  
10167	/**
10168	 * @author mikael emtinger / http://gomo.se/
10169	 * @author alteredq / http://alteredqualia.com/
10170	 * @author WestLangley / http://github.com/WestLangley
10171	 * @author bhouston / http://clara.io
10172	 */
10173  
10174	function Quaternion( x, y, z, w ) {
10175  
10176		this._x = x || 0;
10177		this._y = y || 0;
10178		this._z = z || 0;
10179		this._w = ( w !== undefined ) ? w : 1;
10180  
10181	}
10182  
10183	Object.assign( Quaternion, {
10184  
10185		slerp: function ( qa, qb, qm, t ) {
10186  
10187			return qm.copy( qa ).slerp( qb, t );
10188  
10189		},
10190  
10191		slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
10192  
10193			// fuzz-free, array-based Quaternion SLERP operation
10194  
10195			var x0 = src0[ srcOffset0 + 0 ],
10196				y0 = src0[ srcOffset0 + 1 ],
10197				z0 = src0[ srcOffset0 + 2 ],
10198				w0 = src0[ srcOffset0 + 3 ],
10199  
10200				x1 = src1[ srcOffset1 + 0 ],
10201				y1 = src1[ srcOffset1 + 1 ],
10202				z1 = src1[ srcOffset1 + 2 ],
10203				w1 = src1[ srcOffset1 + 3 ];
10204  
10205			if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
10206  
10207				var s = 1 - t,
10208  
10209					cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
10210  
10211					dir = ( cos >= 0 ? 1 : - 1 ),
10212					sqrSin = 1 - cos * cos;
10213  
10214				// Skip the Slerp for tiny steps to avoid numeric problems:
10215				if ( sqrSin > Number.EPSILON ) {
10216  
10217					var sin = Math.sqrt( sqrSin ),
10218						len = Math.atan2( sin, cos * dir );
10219  
10220					s = Math.sin( s * len ) / sin;
10221					t = Math.sin( t * len ) / sin;
10222  
10223				}
10224  
10225				var tDir = t * dir;
10226  
10227				x0 = x0 * s + x1 * tDir;
10228				y0 = y0 * s + y1 * tDir;
10229				z0 = z0 * s + z1 * tDir;
10230				w0 = w0 * s + w1 * tDir;
10231  
10232				// Normalize in case we just did a lerp:
10233				if ( s === 1 - t ) {
10234  
10235					var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
10236  
10237					x0 *= f;
10238					y0 *= f;
10239					z0 *= f;
10240					w0 *= f;
10241  
10242				}
10243  
10244			}
10245  
10246			dst[ dstOffset ] = x0;
10247			dst[ dstOffset + 1 ] = y0;
10248			dst[ dstOffset + 2 ] = z0;
10249			dst[ dstOffset + 3 ] = w0;
10250  
10251		}
10252  
10253	} );
10254  
10255	Object.defineProperties( Quaternion.prototype, {
10256  
10257		x: {
10258  
10259			get: function () {
10260  
10261				return this._x;
10262  
10263			},
10264  
10265			set: function ( value ) {
10266  
10267				this._x = value;
10268				this.onChangeCallback();
10269  
10270			}
10271  
10272		},
10273  
10274		y: {
10275  
10276			get: function () {
10277  
10278				return this._y;
10279  
10280			},
10281  
10282			set: function ( value ) {
10283  
10284				this._y = value;
10285				this.onChangeCallback();
10286  
10287			}
10288  
10289		},
10290  
10291		z: {
10292  
10293			get: function () {
10294  
10295				return this._z;
10296  
10297			},
10298  
10299			set: function ( value ) {
10300  
10301				this._z = value;
10302				this.onChangeCallback();
10303  
10304			}
10305  
10306		},
10307  
10308		w: {
10309  
10310			get: function () {
10311  
10312				return this._w;
10313  
10314			},
10315  
10316			set: function ( value ) {
10317  
10318				this._w = value;
10319				this.onChangeCallback();
10320  
10321			}
10322  
10323		}
10324  
10325	} );
10326  
10327	Object.assign( Quaternion.prototype, {
10328  
10329		set: function ( x, y, z, w ) {
10330  
10331			this._x = x;
10332			this._y = y;
10333			this._z = z;
10334			this._w = w;
10335  
10336			this.onChangeCallback();
10337  
10338			return this;
10339  
10340		},
10341  
10342		clone: function () {
10343  
10344			return new this.constructor( this._x, this._y, this._z, this._w );
10345  
10346		},
10347  
10348		copy: function ( quaternion ) {
10349  
10350			this._x = quaternion.x;
10351			this._y = quaternion.y;
10352			this._z = quaternion.z;
10353			this._w = quaternion.w;
10354  
10355			this.onChangeCallback();
10356  
10357			return this;
10358  
10359		},
10360  
10361		setFromEuler: function ( euler, update ) {
10362  
10363			if ( ! ( euler && euler.isEuler ) ) {
10364  
10365				throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
10366  
10367			}
10368  
10369			var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
10370  
10371			// http://www.mathworks.com/matlabcentral/fileexchange/
10372			// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
10373			//	content/SpinCalc.m
10374  
10375			var cos = Math.cos;
10376			var sin = Math.sin;
10377  
10378			var c1 = cos( x / 2 );
10379			var c2 = cos( y / 2 );
10380			var c3 = cos( z / 2 );
10381  
10382			var s1 = sin( x / 2 );
10383			var s2 = sin( y / 2 );
10384			var s3 = sin( z / 2 );
10385  
10386			if ( order === 'XYZ' ) {
10387  
10388				this._x = s1 * c2 * c3 + c1 * s2 * s3;
10389				this._y = c1 * s2 * c3 - s1 * c2 * s3;
10390				this._z = c1 * c2 * s3 + s1 * s2 * c3;
10391				this._w = c1 * c2 * c3 - s1 * s2 * s3;
10392  
10393			} else if ( order === 'YXZ' ) {
10394  
10395				this._x = s1 * c2 * c3 + c1 * s2 * s3;
10396				this._y = c1 * s2 * c3 - s1 * c2 * s3;
10397				this._z = c1 * c2 * s3 - s1 * s2 * c3;
10398				this._w = c1 * c2 * c3 + s1 * s2 * s3;
10399  
10400			} else if ( order === 'ZXY' ) {
10401  
10402				this._x = s1 * c2 * c3 - c1 * s2 * s3;
10403				this._y = c1 * s2 * c3 + s1 * c2 * s3;
10404				this._z = c1 * c2 * s3 + s1 * s2 * c3;
10405				this._w = c1 * c2 * c3 - s1 * s2 * s3;
10406  
10407			} else if ( order === 'ZYX' ) {
10408  
10409				this._x = s1 * c2 * c3 - c1 * s2 * s3;
10410				this._y = c1 * s2 * c3 + s1 * c2 * s3;
10411				this._z = c1 * c2 * s3 - s1 * s2 * c3;
10412				this._w = c1 * c2 * c3 + s1 * s2 * s3;
10413  
10414			} else if ( order === 'YZX' ) {
10415  
10416				this._x = s1 * c2 * c3 + c1 * s2 * s3;
10417				this._y = c1 * s2 * c3 + s1 * c2 * s3;
10418				this._z = c1 * c2 * s3 - s1 * s2 * c3;
10419				this._w = c1 * c2 * c3 - s1 * s2 * s3;
10420  
10421			} else if ( order === 'XZY' ) {
10422  
10423				this._x = s1 * c2 * c3 - c1 * s2 * s3;
10424				this._y = c1 * s2 * c3 - s1 * c2 * s3;
10425				this._z = c1 * c2 * s3 + s1 * s2 * c3;
10426				this._w = c1 * c2 * c3 + s1 * s2 * s3;
10427  
10428			}
10429  
10430			if ( update !== false ) this.onChangeCallback();
10431  
10432			return this;
10433  
10434		},
10435  
10436		setFromAxisAngle: function ( axis, angle ) {
10437  
10438			// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
10439  
10440			// assumes axis is normalized
10441  
10442			var halfAngle = angle / 2, s = Math.sin( halfAngle );
10443  
10444			this._x = axis.x * s;
10445			this._y = axis.y * s;
10446			this._z = axis.z * s;
10447			this._w = Math.cos( halfAngle );
10448  
10449			this.onChangeCallback();
10450  
10451			return this;
10452  
10453		},
10454  
10455		setFromRotationMatrix: function ( m ) {
10456  
10457			// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
10458  
10459			// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
10460  
10461			var te = m.elements,
10462  
10463				m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
10464				m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
10465				m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
10466  
10467				trace = m11 + m22 + m33,
10468				s;
10469  
10470			if ( trace > 0 ) {
10471  
10472				s = 0.5 / Math.sqrt( trace + 1.0 );
10473  
10474				this._w = 0.25 / s;
10475				this._x = ( m32 - m23 ) * s;
10476				this._y = ( m13 - m31 ) * s;
10477				this._z = ( m21 - m12 ) * s;
10478  
10479			} else if ( m11 > m22 && m11 > m33 ) {
10480  
10481				s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
10482  
10483				this._w = ( m32 - m23 ) / s;
10484				this._x = 0.25 * s;
10485				this._y = ( m12 + m21 ) / s;
10486				this._z = ( m13 + m31 ) / s;
10487  
10488			} else if ( m22 > m33 ) {
10489  
10490				s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
10491  
10492				this._w = ( m13 - m31 ) / s;
10493				this._x = ( m12 + m21 ) / s;
10494				this._y = 0.25 * s;
10495				this._z = ( m23 + m32 ) / s;
10496  
10497			} else {
10498  
10499				s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
10500  
10501				this._w = ( m21 - m12 ) / s;
10502				this._x = ( m13 + m31 ) / s;
10503				this._y = ( m23 + m32 ) / s;
10504				this._z = 0.25 * s;
10505  
10506			}
10507  
10508			this.onChangeCallback();
10509  
10510			return this;
10511  
10512		},
10513  
10514		setFromUnitVectors: function () {
10515  
10516			// assumes direction vectors vFrom and vTo are normalized
10517  
10518			var v1 = new Vector3();
10519			var r;
10520  
10521			var EPS = 0.000001;
10522  
10523			return function setFromUnitVectors( vFrom, vTo ) {
10524  
10525				if ( v1 === undefined ) v1 = new Vector3();
10526  
10527				r = vFrom.dot( vTo ) + 1;
10528  
10529				if ( r < EPS ) {
10530  
10531					r = 0;
10532  
10533					if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
10534  
10535						v1.set( - vFrom.y, vFrom.x, 0 );
10536  
10537					} else {
10538  
10539						v1.set( 0, - vFrom.z, vFrom.y );
10540  
10541					}
10542  
10543				} else {
10544  
10545					v1.crossVectors( vFrom, vTo );
10546  
10547				}
10548  
10549				this._x = v1.x;
10550				this._y = v1.y;
10551				this._z = v1.z;
10552				this._w = r;
10553  
10554				return this.normalize();
10555  
10556			};
10557  
10558		}(),
10559  
10560		inverse: function () {
10561  
10562			// quaternion is assumed to have unit length
10563  
10564			return this.conjugate();
10565  
10566		},
10567  
10568		conjugate: function () {
10569  
10570			this._x *= - 1;
10571			this._y *= - 1;
10572			this._z *= - 1;
10573  
10574			this.onChangeCallback();
10575  
10576			return this;
10577  
10578		},
10579  
10580		dot: function ( v ) {
10581  
10582			return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
10583  
10584		},
10585  
10586		lengthSq: function () {
10587  
10588			return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
10589  
10590		},
10591  
10592		length: function () {
10593  
10594			return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
10595  
10596		},
10597  
10598		normalize: function () {
10599  
10600			var l = this.length();
10601  
10602			if ( l === 0 ) {
10603  
10604				this._x = 0;
10605				this._y = 0;
10606				this._z = 0;
10607				this._w = 1;
10608  
10609			} else {
10610  
10611				l = 1 / l;
10612  
10613				this._x = this._x * l;
10614				this._y = this._y * l;
10615				this._z = this._z * l;
10616				this._w = this._w * l;
10617  
10618			}
10619  
10620			this.onChangeCallback();
10621  
10622			return this;
10623  
10624		},
10625  
10626		multiply: function ( q, p ) {
10627  
10628			if ( p !== undefined ) {
10629  
10630				console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
10631				return this.multiplyQuaternions( q, p );
10632  
10633			}
10634  
10635			return this.multiplyQuaternions( this, q );
10636  
10637		},
10638  
10639		premultiply: function ( q ) {
10640  
10641			return this.multiplyQuaternions( q, this );
10642  
10643		},
10644  
10645		multiplyQuaternions: function ( a, b ) {
10646  
10647			// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
10648  
10649			var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
10650			var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
10651  
10652			this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
10653			this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
10654			this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
10655			this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
10656  
10657			this.onChangeCallback();
10658  
10659			return this;
10660  
10661		},
10662  
10663		slerp: function ( qb, t ) {
10664  
10665			if ( t === 0 ) return this;
10666			if ( t === 1 ) return this.copy( qb );
10667  
10668			var x = this._x, y = this._y, z = this._z, w = this._w;
10669  
10670			// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
10671  
10672			var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
10673  
10674			if ( cosHalfTheta < 0 ) {
10675  
10676				this._w = - qb._w;
10677				this._x = - qb._x;
10678				this._y = - qb._y;
10679				this._z = - qb._z;
10680  
10681				cosHalfTheta = - cosHalfTheta;
10682  
10683			} else {
10684  
10685				this.copy( qb );
10686  
10687			}
10688  
10689			if ( cosHalfTheta >= 1.0 ) {
10690  
10691				this._w = w;
10692				this._x = x;
10693				this._y = y;
10694				this._z = z;
10695  
10696				return this;
10697  
10698			}
10699  
10700			var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
10701  
10702			if ( Math.abs( sinHalfTheta ) < 0.001 ) {
10703  
10704				this._w = 0.5 * ( w + this._w );
10705				this._x = 0.5 * ( x + this._x );
10706				this._y = 0.5 * ( y + this._y );
10707				this._z = 0.5 * ( z + this._z );
10708  
10709				return this;
10710  
10711			}
10712  
10713			var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
10714			var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
10715				ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
10716  
10717			this._w = ( w * ratioA + this._w * ratioB );
10718			this._x = ( x * ratioA + this._x * ratioB );
10719			this._y = ( y * ratioA + this._y * ratioB );
10720			this._z = ( z * ratioA + this._z * ratioB );
10721  
10722			this.onChangeCallback();
10723  
10724			return this;
10725  
10726		},
10727  
10728		equals: function ( quaternion ) {
10729  
10730			return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
10731  
10732		},
10733  
10734		fromArray: function ( array, offset ) {
10735  
10736			if ( offset === undefined ) offset = 0;
10737  
10738			this._x = array[ offset ];
10739			this._y = array[ offset + 1 ];
10740			this._z = array[ offset + 2 ];
10741			this._w = array[ offset + 3 ];
10742  
10743			this.onChangeCallback();
10744  
10745			return this;
10746  
10747		},
10748  
10749		toArray: function ( array, offset ) {
10750  
10751			if ( array === undefined ) array = [];
10752			if ( offset === undefined ) offset = 0;
10753  
10754			array[ offset ] = this._x;
10755			array[ offset + 1 ] = this._y;
10756			array[ offset + 2 ] = this._z;
10757			array[ offset + 3 ] = this._w;
10758  
10759			return array;
10760  
10761		},
10762  
10763		onChange: function ( callback ) {
10764  
10765			this.onChangeCallback = callback;
10766  
10767			return this;
10768  
10769		},
10770  
10771		onChangeCallback: function () {}
10772  
10773	} );
10774  
10775	/**
10776	 * @author mrdoob / http://mrdoob.com/
10777	 * @author kile / http://kile.stravaganza.org/
10778	 * @author philogb / http://blog.thejit.org/
10779	 * @author mikael emtinger / http://gomo.se/
10780	 * @author egraether / http://egraether.com/
10781	 * @author WestLangley / http://github.com/WestLangley
10782	 */
10783  
10784	function Vector3( x, y, z ) {
10785  
10786		this.x = x || 0;
10787		this.y = y || 0;
10788		this.z = z || 0;
10789  
10790	}
10791  
10792	Object.assign( Vector3.prototype, {
10793  
10794		isVector3: true,
10795  
10796		set: function ( x, y, z ) {
10797  
10798			this.x = x;
10799			this.y = y;
10800			this.z = z;
10801  
10802			return this;
10803  
10804		},
10805  
10806		setScalar: function ( scalar ) {
10807  
10808			this.x = scalar;
10809			this.y = scalar;
10810			this.z = scalar;
10811  
10812			return this;
10813  
10814		},
10815  
10816		setX: function ( x ) {
10817  
10818			this.x = x;
10819  
10820			return this;
10821  
10822		},
10823  
10824		setY: function ( y ) {
10825  
10826			this.y = y;
10827  
10828			return this;
10829  
10830		},
10831  
10832		setZ: function ( z ) {
10833  
10834			this.z = z;
10835  
10836			return this;
10837  
10838		},
10839  
10840		setComponent: function ( index, value ) {
10841  
10842			switch ( index ) {
10843  
10844				case 0: this.x = value; break;
10845				case 1: this.y = value; break;
10846				case 2: this.z = value; break;
10847				default: throw new Error( 'index is out of range: ' + index );
10848  
10849			}
10850  
10851			return this;
10852  
10853		},
10854  
10855		getComponent: function ( index ) {
10856  
10857			switch ( index ) {
10858  
10859				case 0: return this.x;
10860				case 1: return this.y;
10861				case 2: return this.z;
10862				default: throw new Error( 'index is out of range: ' + index );
10863  
10864			}
10865  
10866		},
10867  
10868		clone: function () {
10869  
10870			return new this.constructor( this.x, this.y, this.z );
10871  
10872		},
10873  
10874		copy: function ( v ) {
10875  
10876			this.x = v.x;
10877			this.y = v.y;
10878			this.z = v.z;
10879  
10880			return this;
10881  
10882		},
10883  
10884		add: function ( v, w ) {
10885  
10886			if ( w !== undefined ) {
10887  
10888				console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
10889				return this.addVectors( v, w );
10890  
10891			}
10892  
10893			this.x += v.x;
10894			this.y += v.y;
10895			this.z += v.z;
10896  
10897			return this;
10898  
10899		},
10900  
10901		addScalar: function ( s ) {
10902  
10903			this.x += s;
10904			this.y += s;
10905			this.z += s;
10906  
10907			return this;
10908  
10909		},
10910  
10911		addVectors: function ( a, b ) {
10912  
10913			this.x = a.x + b.x;
10914			this.y = a.y + b.y;
10915			this.z = a.z + b.z;
10916  
10917			return this;
10918  
10919		},
10920  
10921		addScaledVector: function ( v, s ) {
10922  
10923			this.x += v.x * s;
10924			this.y += v.y * s;
10925			this.z += v.z * s;
10926  
10927			return this;
10928  
10929		},
10930  
10931		sub: function ( v, w ) {
10932  
10933			if ( w !== undefined ) {
10934  
10935				console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
10936				return this.subVectors( v, w );
10937  
10938			}
10939  
10940			this.x -= v.x;
10941			this.y -= v.y;
10942			this.z -= v.z;
10943  
10944			return this;
10945  
10946		},
10947  
10948		subScalar: function ( s ) {
10949  
10950			this.x -= s;
10951			this.y -= s;
10952			this.z -= s;
10953  
10954			return this;
10955  
10956		},
10957  
10958		subVectors: function ( a, b ) {
10959  
10960			this.x = a.x - b.x;
10961			this.y = a.y - b.y;
10962			this.z = a.z - b.z;
10963  
10964			return this;
10965  
10966		},
10967  
10968		multiply: function ( v, w ) {
10969  
10970			if ( w !== undefined ) {
10971  
10972				console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
10973				return this.multiplyVectors( v, w );
10974  
10975			}
10976  
10977			this.x *= v.x;
10978			this.y *= v.y;
10979			this.z *= v.z;
10980  
10981			return this;
10982  
10983		},
10984  
10985		multiplyScalar: function ( scalar ) {
10986  
10987			this.x *= scalar;
10988			this.y *= scalar;
10989			this.z *= scalar;
10990  
10991			return this;
10992  
10993		},
10994  
10995		multiplyVectors: function ( a, b ) {
10996  
10997			this.x = a.x * b.x;
10998			this.y = a.y * b.y;
10999			this.z = a.z * b.z;
11000  
11001			return this;
11002  
11003		},
11004  
11005		applyEuler: function () {
11006  
11007			var quaternion = new Quaternion();
11008  
11009			return function applyEuler( euler ) {
11010  
11011				if ( ! ( euler && euler.isEuler ) ) {
11012  
11013					console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
11014  
11015				}
11016  
11017				return this.applyQuaternion( quaternion.setFromEuler( euler ) );
11018  
11019			};
11020  
11021		}(),
11022  
11023		applyAxisAngle: function () {
11024  
11025			var quaternion = new Quaternion();
11026  
11027			return function applyAxisAngle( axis, angle ) {
11028  
11029				return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
11030  
11031			};
11032  
11033		}(),
11034  
11035		applyMatrix3: function ( m ) {
11036  
11037			var x = this.x, y = this.y, z = this.z;
11038			var e = m.elements;
11039  
11040			this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
11041			this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
11042			this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
11043  
11044			return this;
11045  
11046		},
11047  
11048		applyMatrix4: function ( m ) {
11049  
11050			var x = this.x, y = this.y, z = this.z;
11051			var e = m.elements;
11052  
11053			var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
11054  
11055			this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
11056			this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
11057			this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
11058  
11059			return this;
11060  
11061		},
11062  
11063		applyQuaternion: function ( q ) {
11064  
11065			var x = this.x, y = this.y, z = this.z;
11066			var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
11067  
11068			// calculate quat * vector
11069  
11070			var ix = qw * x + qy * z - qz * y;
11071			var iy = qw * y + qz * x - qx * z;
11072			var iz = qw * z + qx * y - qy * x;
11073			var iw = - qx * x - qy * y - qz * z;
11074  
11075			// calculate result * inverse quat
11076  
11077			this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
11078			this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
11079			this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
11080  
11081			return this;
11082  
11083		},
11084  
11085		project: function () {
11086  
11087			var matrix = new Matrix4();
11088  
11089			return function project( camera ) {
11090  
11091				matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
11092				return this.applyMatrix4( matrix );
11093  
11094			};
11095  
11096		}(),
11097  
11098		unproject: function () {
11099  
11100			var matrix = new Matrix4();
11101  
11102			return function unproject( camera ) {
11103  
11104				matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
11105				return this.applyMatrix4( matrix );
11106  
11107			};
11108  
11109		}(),
11110  
11111		transformDirection: function ( m ) {
11112  
11113			// input: THREE.Matrix4 affine matrix
11114			// vector interpreted as a direction
11115  
11116			var x = this.x, y = this.y, z = this.z;
11117			var e = m.elements;
11118  
11119			this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
11120			this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
11121			this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
11122  
11123			return this.normalize();
11124  
11125		},
11126  
11127		divide: function ( v ) {
11128  
11129			this.x /= v.x;
11130			this.y /= v.y;
11131			this.z /= v.z;
11132  
11133			return this;
11134  
11135		},
11136  
11137		divideScalar: function ( scalar ) {
11138  
11139			return this.multiplyScalar( 1 / scalar );
11140  
11141		},
11142  
11143		min: function ( v ) {
11144  
11145			this.x = Math.min( this.x, v.x );
11146			this.y = Math.min( this.y, v.y );
11147			this.z = Math.min( this.z, v.z );
11148  
11149			return this;
11150  
11151		},
11152  
11153		max: function ( v ) {
11154  
11155			this.x = Math.max( this.x, v.x );
11156			this.y = Math.max( this.y, v.y );
11157			this.z = Math.max( this.z, v.z );
11158  
11159			return this;
11160  
11161		},
11162  
11163		clamp: function ( min, max ) {
11164  
11165			// assumes min < max, componentwise
11166  
11167			this.x = Math.max( min.x, Math.min( max.x, this.x ) );
11168			this.y = Math.max( min.y, Math.min( max.y, this.y ) );
11169			this.z = Math.max( min.z, Math.min( max.z, this.z ) );
11170  
11171			return this;
11172  
11173		},
11174  
11175		clampScalar: function () {
11176  
11177			var min = new Vector3();
11178			var max = new Vector3();
11179  
11180			return function clampScalar( minVal, maxVal ) {
11181  
11182				min.set( minVal, minVal, minVal );
11183				max.set( maxVal, maxVal, maxVal );
11184  
11185				return this.clamp( min, max );
11186  
11187			};
11188  
11189		}(),
11190  
11191		clampLength: function ( min, max ) {
11192  
11193			var length = this.length();
11194  
11195			return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
11196  
11197		},
11198  
11199		floor: function () {
11200  
11201			this.x = Math.floor( this.x );
11202			this.y = Math.floor( this.y );
11203			this.z = Math.floor( this.z );
11204  
11205			return this;
11206  
11207		},
11208  
11209		ceil: function () {
11210  
11211			this.x = Math.ceil( this.x );
11212			this.y = Math.ceil( this.y );
11213			this.z = Math.ceil( this.z );
11214  
11215			return this;
11216  
11217		},
11218  
11219		round: function () {
11220  
11221			this.x = Math.round( this.x );
11222			this.y = Math.round( this.y );
11223			this.z = Math.round( this.z );
11224  
11225			return this;
11226  
11227		},
11228  
11229		roundToZero: function () {
11230  
11231			this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
11232			this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
11233			this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
11234  
11235			return this;
11236  
11237		},
11238  
11239		negate: function () {
11240  
11241			this.x = - this.x;
11242			this.y = - this.y;
11243			this.z = - this.z;
11244  
11245			return this;
11246  
11247		},
11248  
11249		dot: function ( v ) {
11250  
11251			return this.x * v.x + this.y * v.y + this.z * v.z;
11252  
11253		},
11254  
11255		// TODO lengthSquared?
11256  
11257		lengthSq: function () {
11258  
11259			return this.x * this.x + this.y * this.y + this.z * this.z;
11260  
11261		},
11262  
11263		length: function () {
11264  
11265			return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
11266  
11267		},
11268  
11269		manhattanLength: function () {
11270  
11271			return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
11272  
11273		},
11274  
11275		normalize: function () {
11276  
11277			return this.divideScalar( this.length() || 1 );
11278  
11279		},
11280  
11281		setLength: function ( length ) {
11282  
11283			return this.normalize().multiplyScalar( length );
11284  
11285		},
11286  
11287		lerp: function ( v, alpha ) {
11288  
11289			this.x += ( v.x - this.x ) * alpha;
11290			this.y += ( v.y - this.y ) * alpha;
11291			this.z += ( v.z - this.z ) * alpha;
11292  
11293			return this;
11294  
11295		},
11296  
11297		lerpVectors: function ( v1, v2, alpha ) {
11298  
11299			return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
11300  
11301		},
11302  
11303		cross: function ( v, w ) {
11304  
11305			if ( w !== undefined ) {
11306  
11307				console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
11308				return this.crossVectors( v, w );
11309  
11310			}
11311  
11312			return this.crossVectors( this, v );
11313  
11314		},
11315  
11316		crossVectors: function ( a, b ) {
11317  
11318			var ax = a.x, ay = a.y, az = a.z;
11319			var bx = b.x, by = b.y, bz = b.z;
11320  
11321			this.x = ay * bz - az * by;
11322			this.y = az * bx - ax * bz;
11323			this.z = ax * by - ay * bx;
11324  
11325			return this;
11326  
11327		},
11328  
11329		projectOnVector: function ( vector ) {
11330  
11331			var scalar = vector.dot( this ) / vector.lengthSq();
11332  
11333			return this.copy( vector ).multiplyScalar( scalar );
11334  
11335		},
11336  
11337		projectOnPlane: function () {
11338  
11339			var v1 = new Vector3();
11340  
11341			return function projectOnPlane( planeNormal ) {
11342  
11343				v1.copy( this ).projectOnVector( planeNormal );
11344  
11345				return this.sub( v1 );
11346  
11347			};
11348  
11349		}(),
11350  
11351		reflect: function () {
11352  
11353			// reflect incident vector off plane orthogonal to normal
11354			// normal is assumed to have unit length
11355  
11356			var v1 = new Vector3();
11357  
11358			return function reflect( normal ) {
11359  
11360				return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
11361  
11362			};
11363  
11364		}(),
11365  
11366		angleTo: function ( v ) {
11367  
11368			var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
11369  
11370			// clamp, to handle numerical problems
11371  
11372			return Math.acos( _Math.clamp( theta, - 1, 1 ) );
11373  
11374		},
11375  
11376		distanceTo: function ( v ) {
11377  
11378			return Math.sqrt( this.distanceToSquared( v ) );
11379  
11380		},
11381  
11382		distanceToSquared: function ( v ) {
11383  
11384			var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
11385  
11386			return dx * dx + dy * dy + dz * dz;
11387  
11388		},
11389  
11390		manhattanDistanceTo: function ( v ) {
11391  
11392			return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
11393  
11394		},
11395  
11396		setFromSpherical: function ( s ) {
11397  
11398			var sinPhiRadius = Math.sin( s.phi ) * s.radius;
11399  
11400			this.x = sinPhiRadius * Math.sin( s.theta );
11401			this.y = Math.cos( s.phi ) * s.radius;
11402			this.z = sinPhiRadius * Math.cos( s.theta );
11403  
11404			return this;
11405  
11406		},
11407  
11408		setFromCylindrical: function ( c ) {
11409  
11410			this.x = c.radius * Math.sin( c.theta );
11411			this.y = c.y;
11412			this.z = c.radius * Math.cos( c.theta );
11413  
11414			return this;
11415  
11416		},
11417  
11418		setFromMatrixPosition: function ( m ) {
11419  
11420			var e = m.elements;
11421  
11422			this.x = e[ 12 ];
11423			this.y = e[ 13 ];
11424			this.z = e[ 14 ];
11425  
11426			return this;
11427  
11428		},
11429  
11430		setFromMatrixScale: function ( m ) {
11431  
11432			var sx = this.setFromMatrixColumn( m, 0 ).length();
11433			var sy = this.setFromMatrixColumn( m, 1 ).length();
11434			var sz = this.setFromMatrixColumn( m, 2 ).length();
11435  
11436			this.x = sx;
11437			this.y = sy;
11438			this.z = sz;
11439  
11440			return this;
11441  
11442		},
11443  
11444		setFromMatrixColumn: function ( m, index ) {
11445  
11446			return this.fromArray( m.elements, index * 4 );
11447  
11448		},
11449  
11450		equals: function ( v ) {
11451  
11452			return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
11453  
11454		},
11455  
11456		fromArray: function ( array, offset ) {
11457  
11458			if ( offset === undefined ) offset = 0;
11459  
11460			this.x = array[ offset ];
11461			this.y = array[ offset + 1 ];
11462			this.z = array[ offset + 2 ];
11463  
11464			return this;
11465  
11466		},
11467  
11468		toArray: function ( array, offset ) {
11469  
11470			if ( array === undefined ) array = [];
11471			if ( offset === undefined ) offset = 0;
11472  
11473			array[ offset ] = this.x;
11474			array[ offset + 1 ] = this.y;
11475			array[ offset + 2 ] = this.z;
11476  
11477			return array;
11478  
11479		},
11480  
11481		fromBufferAttribute: function ( attribute, index, offset ) {
11482  
11483			if ( offset !== undefined ) {
11484  
11485				console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
11486  
11487			}
11488  
11489			this.x = attribute.getX( index );
11490			this.y = attribute.getY( index );
11491			this.z = attribute.getZ( index );
11492  
11493			return this;
11494  
11495		}
11496  
11497	} );
11498  
11499	/**
11500	 * @author alteredq / http://alteredqualia.com/
11501	 * @author WestLangley / http://github.com/WestLangley
11502	 * @author bhouston / http://clara.io
11503	 * @author tschw
11504	 */
11505  
11506	function Matrix3() {
11507  
11508		this.elements = [
11509  
11510			1, 0, 0,
11511			0, 1, 0,
11512			0, 0, 1
11513  
11514		];
11515  
11516		if ( arguments.length > 0 ) {
11517  
11518			console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
11519  
11520		}
11521  
11522	}
11523  
vendor: 8,497 bytes, lines 11524-11924
11524	Object.assign( Matrix3.prototype, {
11525  
11526		isMatrix3: true,
11527  
11528		set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
11529  
11530			var te = this.elements;
11531  
11532			te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
11533			te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
11534			te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
11535  
11536			return this;
11537  
11538		},
11539  
11540		identity: function () {
11541  
11542			this.set(
11543  
11544				1, 0, 0,
11545				0, 1, 0,
11546				0, 0, 1
11547  
11548			);
11549  
11550			return this;
11551  
11552		},
11553  
11554		clone: function () {
11555  
11556			return new this.constructor().fromArray( this.elements );
11557  
11558		},
11559  
11560		copy: function ( m ) {
11561  
11562			var te = this.elements;
11563			var me = m.elements;
11564  
11565			te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
11566			te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
11567			te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
11568  
11569			return this;
11570  
11571		},
11572  
11573		setFromMatrix4: function ( m ) {
11574  
11575			var me = m.elements;
11576  
11577			this.set(
11578  
11579				me[ 0 ], me[ 4 ], me[ 8 ],
11580				me[ 1 ], me[ 5 ], me[ 9 ],
11581				me[ 2 ], me[ 6 ], me[ 10 ]
11582  
11583			);
11584  
11585			return this;
11586  
11587		},
11588  
11589		applyToBufferAttribute: function () {
11590  
11591			var v1 = new Vector3();
11592  
11593			return function applyToBufferAttribute( attribute ) {
11594  
11595				for ( var i = 0, l = attribute.count; i < l; i ++ ) {
11596  
11597					v1.x = attribute.getX( i );
11598					v1.y = attribute.getY( i );
11599					v1.z = attribute.getZ( i );
11600  
11601					v1.applyMatrix3( this );
11602  
11603					attribute.setXYZ( i, v1.x, v1.y, v1.z );
11604  
11605				}
11606  
11607				return attribute;
11608  
11609			};
11610  
11611		}(),
11612  
11613		multiply: function ( m ) {
11614  
11615			return this.multiplyMatrices( this, m );
11616  
11617		},
11618  
11619		premultiply: function ( m ) {
11620  
11621			return this.multiplyMatrices( m, this );
11622  
11623		},
11624  
11625		multiplyMatrices: function ( a, b ) {
11626  
11627			var ae = a.elements;
11628			var be = b.elements;
11629			var te = this.elements;
11630  
11631			var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
11632			var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
11633			var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
11634  
11635			var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
11636			var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
11637			var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
11638  
11639			te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
11640			te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
11641			te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
11642  
11643			te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
11644			te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
11645			te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
11646  
11647			te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
11648			te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
11649			te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
11650  
11651			return this;
11652  
11653		},
11654  
11655		multiplyScalar: function ( s ) {
11656  
11657			var te = this.elements;
11658  
11659			te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
11660			te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
11661			te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
11662  
11663			return this;
11664  
11665		},
11666  
11667		determinant: function () {
11668  
11669			var te = this.elements;
11670  
11671			var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
11672				d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
11673				g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
11674  
11675			return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
11676  
11677		},
11678  
11679		getInverse: function ( matrix, throwOnDegenerate ) {
11680  
11681			if ( matrix && matrix.isMatrix4 ) {
11682  
11683				console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
11684  
11685			}
11686  
11687			var me = matrix.elements,
11688				te = this.elements,
11689  
11690				n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
11691				n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
11692				n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
11693  
11694				t11 = n33 * n22 - n32 * n23,
11695				t12 = n32 * n13 - n33 * n12,
11696				t13 = n23 * n12 - n22 * n13,
11697  
11698				det = n11 * t11 + n21 * t12 + n31 * t13;
11699  
11700			if ( det === 0 ) {
11701  
11702				var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
11703  
11704				if ( throwOnDegenerate === true ) {
11705  
11706					throw new Error( msg );
11707  
11708				} else {
11709  
11710					console.warn( msg );
11711  
11712				}
11713  
11714				return this.identity();
11715  
11716			}
11717  
11718			var detInv = 1 / det;
11719  
11720			te[ 0 ] = t11 * detInv;
11721			te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
11722			te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
11723  
11724			te[ 3 ] = t12 * detInv;
11725			te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
11726			te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
11727  
11728			te[ 6 ] = t13 * detInv;
11729			te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
11730			te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
11731  
11732			return this;
11733  
11734		},
11735  
11736		transpose: function () {
11737  
11738			var tmp, m = this.elements;
11739  
11740			tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
11741			tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
11742			tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
11743  
11744			return this;
11745  
11746		},
11747  
11748		getNormalMatrix: function ( matrix4 ) {
11749  
11750			return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
11751  
11752		},
11753  
11754		transposeIntoArray: function ( r ) {
11755  
11756			var m = this.elements;
11757  
11758			r[ 0 ] = m[ 0 ];
11759			r[ 1 ] = m[ 3 ];
11760			r[ 2 ] = m[ 6 ];
11761			r[ 3 ] = m[ 1 ];
11762			r[ 4 ] = m[ 4 ];
11763			r[ 5 ] = m[ 7 ];
11764			r[ 6 ] = m[ 2 ];
11765			r[ 7 ] = m[ 5 ];
11766			r[ 8 ] = m[ 8 ];
11767  
11768			return this;
11769  
11770		},
11771  
11772		setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
11773  
11774			var c = Math.cos( rotation );
11775			var s = Math.sin( rotation );
11776  
11777			this.set(
11778				sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
11779				- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
11780				0, 0, 1
11781			);
11782  
11783		},
11784  
11785		scale: function ( sx, sy ) {
11786  
11787			var te = this.elements;
11788  
11789			te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
11790			te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
11791  
11792			return this;
11793  
11794		},
11795  
11796		rotate: function ( theta ) {
11797  
11798			var c = Math.cos( theta );
11799			var s = Math.sin( theta );
11800  
11801			var te = this.elements;
11802  
11803			var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
11804			var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
11805  
11806			te[ 0 ] = c * a11 + s * a21;
11807			te[ 3 ] = c * a12 + s * a22;
11808			te[ 6 ] = c * a13 + s * a23;
11809  
11810			te[ 1 ] = - s * a11 + c * a21;
11811			te[ 4 ] = - s * a12 + c * a22;
11812			te[ 7 ] = - s * a13 + c * a23;
11813  
11814			return this;
11815  
11816		},
11817  
11818		translate: function ( tx, ty ) {
11819  
11820			var te = this.elements;
11821  
11822			te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
11823			te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
11824  
11825			return this;
11826  
11827		},
11828  
11829		equals: function ( matrix ) {
11830  
11831			var te = this.elements;
11832			var me = matrix.elements;
11833  
11834			for ( var i = 0; i < 9; i ++ ) {
11835  
11836				if ( te[ i ] !== me[ i ] ) return false;
11837  
11838			}
11839  
11840			return true;
11841  
11842		},
11843  
11844		fromArray: function ( array, offset ) {
11845  
11846			if ( offset === undefined ) offset = 0;
11847  
11848			for ( var i = 0; i < 9; i ++ ) {
11849  
11850				this.elements[ i ] = array[ i + offset ];
11851  
11852			}
11853  
11854			return this;
11855  
11856		},
11857  
11858		toArray: function ( array, offset ) {
11859  
11860			if ( array === undefined ) array = [];
11861			if ( offset === undefined ) offset = 0;
11862  
11863			var te = this.elements;
11864  
11865			array[ offset ] = te[ 0 ];
11866			array[ offset + 1 ] = te[ 1 ];
11867			array[ offset + 2 ] = te[ 2 ];
11868  
11869			array[ offset + 3 ] = te[ 3 ];
11870			array[ offset + 4 ] = te[ 4 ];
11871			array[ offset + 5 ] = te[ 5 ];
11872  
11873			array[ offset + 6 ] = te[ 6 ];
11874			array[ offset + 7 ] = te[ 7 ];
11875			array[ offset + 8 ] = te[ 8 ];
11876  
11877			return array;
11878  
11879		}
11880  
11881	} );
11882  
11883	/**
11884	 * @author mrdoob / http://mrdoob.com/
11885	 * @author alteredq / http://alteredqualia.com/
11886	 * @author szimek / https://github.com/szimek/
11887	 */
11888  
11889	var textureId = 0;
11890  
11891	function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
11892  
11893		Object.defineProperty( this, 'id', { value: textureId ++ } );
11894  
11895		this.uuid = _Math.generateUUID();
11896  
11897		this.name = '';
11898  
11899		this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
11900		this.mipmaps = [];
11901  
11902		this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
11903  
11904		this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
11905		this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
11906  
11907		this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
11908		this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
11909  
11910		this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
11911  
11912		this.format = format !== undefined ? format : RGBAFormat;
11913		this.type = type !== undefined ? type : UnsignedByteType;
11914  
11915		this.offset = new Vector2( 0, 0 );
11916		this.repeat = new Vector2( 1, 1 );
11917		this.center = new Vector2( 0, 0 );
11918		this.rotation = 0;
11919  
11920		this.matrixAutoUpdate = true;
11921		this.matrix = new Matrix3();
11922  
11923		this.generateMipmaps = true;
11924		this.premultiplyAlpha = false;
11925		this.flipY = true;
11926		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
11927  
11928		// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
11929		//
11930		// Also changing the encoding after already used by a Material will not automatically make the Material
11931		// update.  You need to explicitly call Material.needsUpdate to trigger it to recompile.
11932		this.encoding = encoding !== undefined ? encoding : LinearEncoding;
11933  
11934		this.version = 0;
11935		this.onUpdate = null;
11936  
11937	}
11938  
11939	Texture.DEFAULT_IMAGE = undefined;
11940	Texture.DEFAULT_MAPPING = UVMapping;
11941  
11942	Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
11943  
11944		constructor: Texture,
11945  
11946		isTexture: true,
11947  
11948		updateMatrix: function () {
11949  
11950			this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
11951  
11952		},
11953  
11954		clone: function () {
11955  
11956			return new this.constructor().copy( this );
11957  
11958		},
11959  
11960		copy: function ( source ) {
11961  
11962			this.name = source.name;
11963  
11964			this.image = source.image;
11965			this.mipmaps = source.mipmaps.slice( 0 );
11966  
11967			this.mapping = source.mapping;
11968  
11969			this.wrapS = source.wrapS;
11970			this.wrapT = source.wrapT;
11971  
11972			this.magFilter = source.magFilter;
11973			this.minFilter = source.minFilter;
11974  
11975			this.anisotropy = source.anisotropy;
11976  
11977			this.format = source.format;
11978			this.type = source.type;
11979  
11980			this.offset.copy( source.offset );
11981			this.repeat.copy( source.repeat );
11982			this.center.copy( source.center );
11983			this.rotation = source.rotation;
11984  
11985			this.matrixAutoUpdate = source.matrixAutoUpdate;
11986			this.matrix.copy( source.matrix );
11987  
11988			this.generateMipmaps = source.generateMipmaps;
11989			this.premultiplyAlpha = source.premultiplyAlpha;
11990			this.flipY = source.flipY;
11991			this.unpackAlignment = source.unpackAlignment;
11992			this.encoding = source.encoding;
11993  
11994			return this;
11995  
11996		},
11997  
11998		toJSON: function ( meta ) {
11999  
12000			var isRootObject = ( meta === undefined || typeof meta === 'string' );
12001  
12002			if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
12003  
12004				return meta.textures[ this.uuid ];
12005  
12006			}
12007  
12008			function getDataURL( image ) {
12009  
12010				var canvas;
12011  
12012				if ( image instanceof HTMLCanvasElement ) {
12013  
12014					canvas = image;
12015  
12016				} else {
12017  
12018					canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
12019					canvas.width = image.width;
12020					canvas.height = image.height;
12021  
12022					var context = canvas.getContext( '2d' );
12023  
12024					if ( image instanceof ImageData ) {
12025  
12026						context.putImageData( image, 0, 0 );
12027  
12028					} else {
12029  
12030						context.drawImage( image, 0, 0, image.width, image.height );
12031  
12032					}
12033  
12034				}
12035  
12036				if ( canvas.width > 2048 || canvas.height > 2048 ) {
12037  
12038					return canvas.toDataURL( 'image/jpeg', 0.6 );
12039  
12040				} else {
12041  
12042					return canvas.toDataURL( 'image/png' );
12043  
12044				}
12045  
12046			}
12047  
12048			var output = {
12049  
12050				metadata: {
12051					version: 4.5,
12052					type: 'Texture',
12053					generator: 'Texture.toJSON'
12054				},
12055  
12056				uuid: this.uuid,
12057				name: this.name,
12058  
12059				mapping: this.mapping,
12060  
12061				repeat: [ this.repeat.x, this.repeat.y ],
12062				offset: [ this.offset.x, this.offset.y ],
12063				center: [ this.center.x, this.center.y ],
12064				rotation: this.rotation,
12065  
12066				wrap: [ this.wrapS, this.wrapT ],
12067  
12068				format: this.format,
12069				minFilter: this.minFilter,
12070				magFilter: this.magFilter,
12071				anisotropy: this.anisotropy,
12072  
12073				flipY: this.flipY
12074  
12075			};
12076  
12077			if ( this.image !== undefined ) {
12078  
12079				// TODO: Move to THREE.Image
12080  
12081				var image = this.image;
12082  
12083				if ( image.uuid === undefined ) {
12084  
12085					image.uuid = _Math.generateUUID(); // UGH
12086  
12087				}
12088  
12089				if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
12090  
12091					meta.images[ image.uuid ] = {
12092						uuid: image.uuid,
12093						url: getDataURL( image )
12094					};
12095  
12096				}
12097  
12098				output.image = image.uuid;
12099  
12100			}
12101  
12102			if ( ! isRootObject ) {
12103  
12104				meta.textures[ this.uuid ] = output;
12105  
12106			}
12107  
12108			return output;
12109  
12110		},
12111  
12112		dispose: function () {
12113  
12114			this.dispatchEvent( { type: 'dispose' } );
12115  
12116		},
12117  
vendor: 27,117 bytes, lines 12118-13429
12118		transformUv: function ( uv ) {
12119  
12120			if ( this.mapping !== UVMapping ) return;
12121  
12122			uv.applyMatrix3( this.matrix );
12123  
12124			if ( uv.x < 0 || uv.x > 1 ) {
12125  
12126				switch ( this.wrapS ) {
12127  
12128					case RepeatWrapping:
12129  
12130						uv.x = uv.x - Math.floor( uv.x );
12131						break;
12132  
12133					case ClampToEdgeWrapping:
12134  
12135						uv.x = uv.x < 0 ? 0 : 1;
12136						break;
12137  
12138					case MirroredRepeatWrapping:
12139  
12140						if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
12141  
12142							uv.x = Math.ceil( uv.x ) - uv.x;
12143  
12144						} else {
12145  
12146							uv.x = uv.x - Math.floor( uv.x );
12147  
12148						}
12149						break;
12150  
12151				}
12152  
12153			}
12154  
12155			if ( uv.y < 0 || uv.y > 1 ) {
12156  
12157				switch ( this.wrapT ) {
12158  
12159					case RepeatWrapping:
12160  
12161						uv.y = uv.y - Math.floor( uv.y );
12162						break;
12163  
12164					case ClampToEdgeWrapping:
12165  
12166						uv.y = uv.y < 0 ? 0 : 1;
12167						break;
12168  
12169					case MirroredRepeatWrapping:
12170  
12171						if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
12172  
12173							uv.y = Math.ceil( uv.y ) - uv.y;
12174  
12175						} else {
12176  
12177							uv.y = uv.y - Math.floor( uv.y );
12178  
12179						}
12180						break;
12181  
12182				}
12183  
12184			}
12185  
12186			if ( this.flipY ) {
12187  
12188				uv.y = 1 - uv.y;
12189  
12190			}
12191  
12192		}
12193  
12194	} );
12195  
12196	Object.defineProperty( Texture.prototype, "needsUpdate", {
12197  
12198		set: function ( value ) {
12199  
12200			if ( value === true ) this.version ++;
12201  
12202		}
12203  
12204	} );
12205  
12206	/**
12207	 * @author supereggbert / http://www.paulbrunt.co.uk/
12208	 * @author philogb / http://blog.thejit.org/
12209	 * @author mikael emtinger / http://gomo.se/
12210	 * @author egraether / http://egraether.com/
12211	 * @author WestLangley / http://github.com/WestLangley
12212	 */
12213  
12214	function Vector4( x, y, z, w ) {
12215  
12216		this.x = x || 0;
12217		this.y = y || 0;
12218		this.z = z || 0;
12219		this.w = ( w !== undefined ) ? w : 1;
12220  
12221	}
12222  
12223	Object.assign( Vector4.prototype, {
12224  
12225		isVector4: true,
12226  
12227		set: function ( x, y, z, w ) {
12228  
12229			this.x = x;
12230			this.y = y;
12231			this.z = z;
12232			this.w = w;
12233  
12234			return this;
12235  
12236		},
12237  
12238		setScalar: function ( scalar ) {
12239  
12240			this.x = scalar;
12241			this.y = scalar;
12242			this.z = scalar;
12243			this.w = scalar;
12244  
12245			return this;
12246  
12247		},
12248  
12249		setX: function ( x ) {
12250  
12251			this.x = x;
12252  
12253			return this;
12254  
12255		},
12256  
12257		setY: function ( y ) {
12258  
12259			this.y = y;
12260  
12261			return this;
12262  
12263		},
12264  
12265		setZ: function ( z ) {
12266  
12267			this.z = z;
12268  
12269			return this;
12270  
12271		},
12272  
12273		setW: function ( w ) {
12274  
12275			this.w = w;
12276  
12277			return this;
12278  
12279		},
12280  
12281		setComponent: function ( index, value ) {
12282  
12283			switch ( index ) {
12284  
12285				case 0: this.x = value; break;
12286				case 1: this.y = value; break;
12287				case 2: this.z = value; break;
12288				case 3: this.w = value; break;
12289				default: throw new Error( 'index is out of range: ' + index );
12290  
12291			}
12292  
12293			return this;
12294  
12295		},
12296  
12297		getComponent: function ( index ) {
12298  
12299			switch ( index ) {
12300  
12301				case 0: return this.x;
12302				case 1: return this.y;
12303				case 2: return this.z;
12304				case 3: return this.w;
12305				default: throw new Error( 'index is out of range: ' + index );
12306  
12307			}
12308  
12309		},
12310  
12311		clone: function () {
12312  
12313			return new this.constructor( this.x, this.y, this.z, this.w );
12314  
12315		},
12316  
12317		copy: function ( v ) {
12318  
12319			this.x = v.x;
12320			this.y = v.y;
12321			this.z = v.z;
12322			this.w = ( v.w !== undefined ) ? v.w : 1;
12323  
12324			return this;
12325  
12326		},
12327  
12328		add: function ( v, w ) {
12329  
12330			if ( w !== undefined ) {
12331  
12332				console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
12333				return this.addVectors( v, w );
12334  
12335			}
12336  
12337			this.x += v.x;
12338			this.y += v.y;
12339			this.z += v.z;
12340			this.w += v.w;
12341  
12342			return this;
12343  
12344		},
12345  
12346		addScalar: function ( s ) {
12347  
12348			this.x += s;
12349			this.y += s;
12350			this.z += s;
12351			this.w += s;
12352  
12353			return this;
12354  
12355		},
12356  
12357		addVectors: function ( a, b ) {
12358  
12359			this.x = a.x + b.x;
12360			this.y = a.y + b.y;
12361			this.z = a.z + b.z;
12362			this.w = a.w + b.w;
12363  
12364			return this;
12365  
12366		},
12367  
12368		addScaledVector: function ( v, s ) {
12369  
12370			this.x += v.x * s;
12371			this.y += v.y * s;
12372			this.z += v.z * s;
12373			this.w += v.w * s;
12374  
12375			return this;
12376  
12377		},
12378  
12379		sub: function ( v, w ) {
12380  
12381			if ( w !== undefined ) {
12382  
12383				console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
12384				return this.subVectors( v, w );
12385  
12386			}
12387  
12388			this.x -= v.x;
12389			this.y -= v.y;
12390			this.z -= v.z;
12391			this.w -= v.w;
12392  
12393			return this;
12394  
12395		},
12396  
12397		subScalar: function ( s ) {
12398  
12399			this.x -= s;
12400			this.y -= s;
12401			this.z -= s;
12402			this.w -= s;
12403  
12404			return this;
12405  
12406		},
12407  
12408		subVectors: function ( a, b ) {
12409  
12410			this.x = a.x - b.x;
12411			this.y = a.y - b.y;
12412			this.z = a.z - b.z;
12413			this.w = a.w - b.w;
12414  
12415			return this;
12416  
12417		},
12418  
12419		multiplyScalar: function ( scalar ) {
12420  
12421			this.x *= scalar;
12422			this.y *= scalar;
12423			this.z *= scalar;
12424			this.w *= scalar;
12425  
12426			return this;
12427  
12428		},
12429  
12430		applyMatrix4: function ( m ) {
12431  
12432			var x = this.x, y = this.y, z = this.z, w = this.w;
12433			var e = m.elements;
12434  
12435			this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
12436			this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
12437			this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
12438			this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
12439  
12440			return this;
12441  
12442		},
12443  
12444		divideScalar: function ( scalar ) {
12445  
12446			return this.multiplyScalar( 1 / scalar );
12447  
12448		},
12449  
12450		setAxisAngleFromQuaternion: function ( q ) {
12451  
12452			// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
12453  
12454			// q is assumed to be normalized
12455  
12456			this.w = 2 * Math.acos( q.w );
12457  
12458			var s = Math.sqrt( 1 - q.w * q.w );
12459  
12460			if ( s < 0.0001 ) {
12461  
12462				this.x = 1;
12463				this.y = 0;
12464				this.z = 0;
12465  
12466			} else {
12467  
12468				this.x = q.x / s;
12469				this.y = q.y / s;
12470				this.z = q.z / s;
12471  
12472			}
12473  
12474			return this;
12475  
12476		},
12477  
12478		setAxisAngleFromRotationMatrix: function ( m ) {
12479  
12480			// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
12481  
12482			// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
12483  
12484			var angle, x, y, z,		// variables for result
12485				epsilon = 0.01,		// margin to allow for rounding errors
12486				epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
12487  
12488				te = m.elements,
12489  
12490				m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
12491				m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
12492				m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
12493  
12494			if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
12495				 ( Math.abs( m13 - m31 ) < epsilon ) &&
12496				 ( Math.abs( m23 - m32 ) < epsilon ) ) {
12497  
12498				// singularity found
12499				// first check for identity matrix which must have +1 for all terms
12500				// in leading diagonal and zero in other terms
12501  
12502				if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
12503					 ( Math.abs( m13 + m31 ) < epsilon2 ) &&
12504					 ( Math.abs( m23 + m32 ) < epsilon2 ) &&
12505					 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
12506  
12507					// this singularity is identity matrix so angle = 0
12508  
12509					this.set( 1, 0, 0, 0 );
12510  
12511					return this; // zero angle, arbitrary axis
12512  
12513				}
12514  
12515				// otherwise this singularity is angle = 180
12516  
12517				angle = Math.PI;
12518  
12519				var xx = ( m11 + 1 ) / 2;
12520				var yy = ( m22 + 1 ) / 2;
12521				var zz = ( m33 + 1 ) / 2;
12522				var xy = ( m12 + m21 ) / 4;
12523				var xz = ( m13 + m31 ) / 4;
12524				var yz = ( m23 + m32 ) / 4;
12525  
12526				if ( ( xx > yy ) && ( xx > zz ) ) {
12527  
12528					// m11 is the largest diagonal term
12529  
12530					if ( xx < epsilon ) {
12531  
12532						x = 0;
12533						y = 0.707106781;
12534						z = 0.707106781;
12535  
12536					} else {
12537  
12538						x = Math.sqrt( xx );
12539						y = xy / x;
12540						z = xz / x;
12541  
12542					}
12543  
12544				} else if ( yy > zz ) {
12545  
12546					// m22 is the largest diagonal term
12547  
12548					if ( yy < epsilon ) {
12549  
12550						x = 0.707106781;
12551						y = 0;
12552						z = 0.707106781;
12553  
12554					} else {
12555  
12556						y = Math.sqrt( yy );
12557						x = xy / y;
12558						z = yz / y;
12559  
12560					}
12561  
12562				} else {
12563  
12564					// m33 is the largest diagonal term so base result on this
12565  
12566					if ( zz < epsilon ) {
12567  
12568						x = 0.707106781;
12569						y = 0.707106781;
12570						z = 0;
12571  
12572					} else {
12573  
12574						z = Math.sqrt( zz );
12575						x = xz / z;
12576						y = yz / z;
12577  
12578					}
12579  
12580				}
12581  
12582				this.set( x, y, z, angle );
12583  
12584				return this; // return 180 deg rotation
12585  
12586			}
12587  
12588			// as we have reached here there are no singularities so we can handle normally
12589  
12590			var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
12591							   ( m13 - m31 ) * ( m13 - m31 ) +
12592							   ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
12593  
12594			if ( Math.abs( s ) < 0.001 ) s = 1;
12595  
12596			// prevent divide by zero, should not happen if matrix is orthogonal and should be
12597			// caught by singularity test above, but I've left it in just in case
12598  
12599			this.x = ( m32 - m23 ) / s;
12600			this.y = ( m13 - m31 ) / s;
12601			this.z = ( m21 - m12 ) / s;
12602			this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
12603  
12604			return this;
12605  
12606		},
12607  
12608		min: function ( v ) {
12609  
12610			this.x = Math.min( this.x, v.x );
12611			this.y = Math.min( this.y, v.y );
12612			this.z = Math.min( this.z, v.z );
12613			this.w = Math.min( this.w, v.w );
12614  
12615			return this;
12616  
12617		},
12618  
12619		max: function ( v ) {
12620  
12621			this.x = Math.max( this.x, v.x );
12622			this.y = Math.max( this.y, v.y );
12623			this.z = Math.max( this.z, v.z );
12624			this.w = Math.max( this.w, v.w );
12625  
12626			return this;
12627  
12628		},
12629  
12630		clamp: function ( min, max ) {
12631  
12632			// assumes min < max, componentwise
12633  
12634			this.x = Math.max( min.x, Math.min( max.x, this.x ) );
12635			this.y = Math.max( min.y, Math.min( max.y, this.y ) );
12636			this.z = Math.max( min.z, Math.min( max.z, this.z ) );
12637			this.w = Math.max( min.w, Math.min( max.w, this.w ) );
12638  
12639			return this;
12640  
12641		},
12642  
12643		clampScalar: function () {
12644  
12645			var min, max;
12646  
12647			return function clampScalar( minVal, maxVal ) {
12648  
12649				if ( min === undefined ) {
12650  
12651					min = new Vector4();
12652					max = new Vector4();
12653  
12654				}
12655  
12656				min.set( minVal, minVal, minVal, minVal );
12657				max.set( maxVal, maxVal, maxVal, maxVal );
12658  
12659				return this.clamp( min, max );
12660  
12661			};
12662  
12663		}(),
12664  
12665		clampLength: function ( min, max ) {
12666  
12667			var length = this.length();
12668  
12669			return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
12670  
12671		},
12672  
12673		floor: function () {
12674  
12675			this.x = Math.floor( this.x );
12676			this.y = Math.floor( this.y );
12677			this.z = Math.floor( this.z );
12678			this.w = Math.floor( this.w );
12679  
12680			return this;
12681  
12682		},
12683  
12684		ceil: function () {
12685  
12686			this.x = Math.ceil( this.x );
12687			this.y = Math.ceil( this.y );
12688			this.z = Math.ceil( this.z );
12689			this.w = Math.ceil( this.w );
12690  
12691			return this;
12692  
12693		},
12694  
12695		round: function () {
12696  
12697			this.x = Math.round( this.x );
12698			this.y = Math.round( this.y );
12699			this.z = Math.round( this.z );
12700			this.w = Math.round( this.w );
12701  
12702			return this;
12703  
12704		},
12705  
12706		roundToZero: function () {
12707  
12708			this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
12709			this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
12710			this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
12711			this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
12712  
12713			return this;
12714  
12715		},
12716  
12717		negate: function () {
12718  
12719			this.x = - this.x;
12720			this.y = - this.y;
12721			this.z = - this.z;
12722			this.w = - this.w;
12723  
12724			return this;
12725  
12726		},
12727  
12728		dot: function ( v ) {
12729  
12730			return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
12731  
12732		},
12733  
12734		lengthSq: function () {
12735  
12736			return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
12737  
12738		},
12739  
12740		length: function () {
12741  
12742			return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
12743  
12744		},
12745  
12746		manhattanLength: function () {
12747  
12748			return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
12749  
12750		},
12751  
12752		normalize: function () {
12753  
12754			return this.divideScalar( this.length() || 1 );
12755  
12756		},
12757  
12758		setLength: function ( length ) {
12759  
12760			return this.normalize().multiplyScalar( length );
12761  
12762		},
12763  
12764		lerp: function ( v, alpha ) {
12765  
12766			this.x += ( v.x - this.x ) * alpha;
12767			this.y += ( v.y - this.y ) * alpha;
12768			this.z += ( v.z - this.z ) * alpha;
12769			this.w += ( v.w - this.w ) * alpha;
12770  
12771			return this;
12772  
12773		},
12774  
12775		lerpVectors: function ( v1, v2, alpha ) {
12776  
12777			return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
12778  
12779		},
12780  
12781		equals: function ( v ) {
12782  
12783			return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
12784  
12785		},
12786  
12787		fromArray: function ( array, offset ) {
12788  
12789			if ( offset === undefined ) offset = 0;
12790  
12791			this.x = array[ offset ];
12792			this.y = array[ offset + 1 ];
12793			this.z = array[ offset + 2 ];
12794			this.w = array[ offset + 3 ];
12795  
12796			return this;
12797  
12798		},
12799  
12800		toArray: function ( array, offset ) {
12801  
12802			if ( array === undefined ) array = [];
12803			if ( offset === undefined ) offset = 0;
12804  
12805			array[ offset ] = this.x;
12806			array[ offset + 1 ] = this.y;
12807			array[ offset + 2 ] = this.z;
12808			array[ offset + 3 ] = this.w;
12809  
12810			return array;
12811  
12812		},
12813  
12814		fromBufferAttribute: function ( attribute, index, offset ) {
12815  
12816			if ( offset !== undefined ) {
12817  
12818				console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
12819  
12820			}
12821  
12822			this.x = attribute.getX( index );
12823			this.y = attribute.getY( index );
12824			this.z = attribute.getZ( index );
12825			this.w = attribute.getW( index );
12826  
12827			return this;
12828  
12829		}
12830  
12831	} );
12832  
12833	/**
12834	 * @author szimek / https://github.com/szimek/
12835	 * @author alteredq / http://alteredqualia.com/
12836	 * @author Marius Kintel / https://github.com/kintel
12837	 */
12838  
12839	/*
12840	 In options, we can specify:
12841	 * Texture parameters for an auto-generated target texture
12842	 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
12843	*/
12844	function WebGLRenderTarget( width, height, options ) {
12845  
12846		this.width = width;
12847		this.height = height;
12848  
12849		this.scissor = new Vector4( 0, 0, width, height );
12850		this.scissorTest = false;
12851  
12852		this.viewport = new Vector4( 0, 0, width, height );
12853  
12854		options = options || {};
12855  
12856		if ( options.minFilter === undefined ) options.minFilter = LinearFilter;
12857  
12858		this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
12859  
12860		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : true;
12861  
12862		this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
12863		this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
12864		this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
12865  
12866	}
12867  
12868	WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
12869  
12870		constructor: WebGLRenderTarget,
12871  
12872		isWebGLRenderTarget: true,
12873  
12874		setSize: function ( width, height ) {
12875  
12876			if ( this.width !== width || this.height !== height ) {
12877  
12878				this.width = width;
12879				this.height = height;
12880  
12881				this.dispose();
12882  
12883			}
12884  
12885			this.viewport.set( 0, 0, width, height );
12886			this.scissor.set( 0, 0, width, height );
12887  
12888		},
12889  
12890		clone: function () {
12891  
12892			return new this.constructor().copy( this );
12893  
12894		},
12895  
12896		copy: function ( source ) {
12897  
12898			this.width = source.width;
12899			this.height = source.height;
12900  
12901			this.viewport.copy( source.viewport );
12902  
12903			this.texture = source.texture.clone();
12904  
12905			this.depthBuffer = source.depthBuffer;
12906			this.stencilBuffer = source.stencilBuffer;
12907			this.depthTexture = source.depthTexture;
12908  
12909			return this;
12910  
12911		},
12912  
12913		dispose: function () {
12914  
12915			this.dispatchEvent( { type: 'dispose' } );
12916  
12917		}
12918  
12919	} );
12920  
12921	/**
12922	 * @author alteredq / http://alteredqualia.com
12923	 */
12924  
12925	function WebGLRenderTargetCube( width, height, options ) {
12926  
12927		WebGLRenderTarget.call( this, width, height, options );
12928  
12929		this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
12930		this.activeMipMapLevel = 0;
12931  
12932	}
12933  
12934	WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
12935	WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
12936  
12937	WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
12938  
12939	/**
12940	 * @author alteredq / http://alteredqualia.com/
12941	 */
12942  
12943	function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
12944  
12945		Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
12946  
12947		this.image = { data: data, width: width, height: height };
12948  
12949		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
12950		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
12951  
12952		this.generateMipmaps = false;
12953		this.flipY = false;
12954		this.unpackAlignment = 1;
12955  
12956	}
12957  
12958	DataTexture.prototype = Object.create( Texture.prototype );
12959	DataTexture.prototype.constructor = DataTexture;
12960  
12961	DataTexture.prototype.isDataTexture = true;
12962  
12963	/**
12964	 * @author bhouston / http://clara.io
12965	 * @author WestLangley / http://github.com/WestLangley
12966	 */
12967  
12968	function Box3( min, max ) {
12969  
12970		this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
12971		this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
12972  
12973	}
12974  
12975	Object.assign( Box3.prototype, {
12976  
12977		isBox3: true,
12978  
12979		set: function ( min, max ) {
12980  
12981			this.min.copy( min );
12982			this.max.copy( max );
12983  
12984			return this;
12985  
12986		},
12987  
12988		setFromArray: function ( array ) {
12989  
12990			var minX = + Infinity;
12991			var minY = + Infinity;
12992			var minZ = + Infinity;
12993  
12994			var maxX = - Infinity;
12995			var maxY = - Infinity;
12996			var maxZ = - Infinity;
12997  
12998			for ( var i = 0, l = array.length; i < l; i += 3 ) {
12999  
13000				var x = array[ i ];
13001				var y = array[ i + 1 ];
13002				var z = array[ i + 2 ];
13003  
13004				if ( x < minX ) minX = x;
13005				if ( y < minY ) minY = y;
13006				if ( z < minZ ) minZ = z;
13007  
13008				if ( x > maxX ) maxX = x;
13009				if ( y > maxY ) maxY = y;
13010				if ( z > maxZ ) maxZ = z;
13011  
13012			}
13013  
13014			this.min.set( minX, minY, minZ );
13015			this.max.set( maxX, maxY, maxZ );
13016  
13017			return this;
13018  
13019		},
13020  
13021		setFromBufferAttribute: function ( attribute ) {
13022  
13023			var minX = + Infinity;
13024			var minY = + Infinity;
13025			var minZ = + Infinity;
13026  
13027			var maxX = - Infinity;
13028			var maxY = - Infinity;
13029			var maxZ = - Infinity;
13030  
13031			for ( var i = 0, l = attribute.count; i < l; i ++ ) {
13032  
13033				var x = attribute.getX( i );
13034				var y = attribute.getY( i );
13035				var z = attribute.getZ( i );
13036  
13037				if ( x < minX ) minX = x;
13038				if ( y < minY ) minY = y;
13039				if ( z < minZ ) minZ = z;
13040  
13041				if ( x > maxX ) maxX = x;
13042				if ( y > maxY ) maxY = y;
13043				if ( z > maxZ ) maxZ = z;
13044  
13045			}
13046  
13047			this.min.set( minX, minY, minZ );
13048			this.max.set( maxX, maxY, maxZ );
13049  
13050			return this;
13051  
13052		},
13053  
13054		setFromPoints: function ( points ) {
13055  
13056			this.makeEmpty();
13057  
13058			for ( var i = 0, il = points.length; i < il; i ++ ) {
13059  
13060				this.expandByPoint( points[ i ] );
13061  
13062			}
13063  
13064			return this;
13065  
13066		},
13067  
13068		setFromCenterAndSize: function () {
13069  
13070			var v1 = new Vector3();
13071  
13072			return function setFromCenterAndSize( center, size ) {
13073  
13074				var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
13075  
13076				this.min.copy( center ).sub( halfSize );
13077				this.max.copy( center ).add( halfSize );
13078  
13079				return this;
13080  
13081			};
13082  
13083		}(),
13084  
13085		setFromObject: function ( object ) {
13086  
13087			this.makeEmpty();
13088  
13089			return this.expandByObject( object );
13090  
13091		},
13092  
13093		clone: function () {
13094  
13095			return new this.constructor().copy( this );
13096  
13097		},
13098  
13099		copy: function ( box ) {
13100  
13101			this.min.copy( box.min );
13102			this.max.copy( box.max );
13103  
13104			return this;
13105  
13106		},
13107  
13108		makeEmpty: function () {
13109  
13110			this.min.x = this.min.y = this.min.z = + Infinity;
13111			this.max.x = this.max.y = this.max.z = - Infinity;
13112  
13113			return this;
13114  
13115		},
13116  
13117		isEmpty: function () {
13118  
13119			// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
13120  
13121			return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
13122  
13123		},
13124  
13125		getCenter: function ( target ) {
13126  
13127			if ( target === undefined ) {
13128  
13129				console.warn( 'THREE.Box3: .getCenter() target is now required' );
13130				target = new Vector3();
13131  
13132			}
13133  
13134			return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
13135  
13136		},
13137  
13138		getSize: function ( target ) {
13139  
13140			if ( target === undefined ) {
13141  
13142				console.warn( 'THREE.Box3: .getSize() target is now required' );
13143				target = new Vector3();
13144  
13145			}
13146  
13147			return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
13148  
13149		},
13150  
13151		expandByPoint: function ( point ) {
13152  
13153			this.min.min( point );
13154			this.max.max( point );
13155  
13156			return this;
13157  
13158		},
13159  
13160		expandByVector: function ( vector ) {
13161  
13162			this.min.sub( vector );
13163			this.max.add( vector );
13164  
13165			return this;
13166  
13167		},
13168  
13169		expandByScalar: function ( scalar ) {
13170  
13171			this.min.addScalar( - scalar );
13172			this.max.addScalar( scalar );
13173  
13174			return this;
13175  
13176		},
13177  
13178		expandByObject: function () {
13179  
13180			// Computes the world-axis-aligned bounding box of an object (including its children),
13181			// accounting for both the object's, and children's, world transforms
13182  
13183			var scope, i, l;
13184  
13185			var v1 = new Vector3();
13186  
13187			function traverse( node ) {
13188  
13189				var geometry = node.geometry;
13190  
13191				if ( geometry !== undefined ) {
13192  
13193					if ( geometry.isGeometry ) {
13194  
13195						var vertices = geometry.vertices;
13196  
13197						for ( i = 0, l = vertices.length; i < l; i ++ ) {
13198  
13199							v1.copy( vertices[ i ] );
13200							v1.applyMatrix4( node.matrixWorld );
13201  
13202							scope.expandByPoint( v1 );
13203  
13204						}
13205  
13206					} else if ( geometry.isBufferGeometry ) {
13207  
13208						var attribute = geometry.attributes.position;
13209  
13210						if ( attribute !== undefined ) {
13211  
13212							for ( i = 0, l = attribute.count; i < l; i ++ ) {
13213  
13214								v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
13215  
13216								scope.expandByPoint( v1 );
13217  
13218							}
13219  
13220						}
13221  
13222					}
13223  
13224				}
13225  
13226			}
13227  
13228			return function expandByObject( object ) {
13229  
13230				scope = this;
13231  
13232				object.updateMatrixWorld( true );
13233  
13234				object.traverse( traverse );
13235  
13236				return this;
13237  
13238			};
13239  
13240		}(),
13241  
13242		containsPoint: function ( point ) {
13243  
13244			return point.x < this.min.x || point.x > this.max.x ||
13245				point.y < this.min.y || point.y > this.max.y ||
13246				point.z < this.min.z || point.z > this.max.z ? false : true;
13247  
13248		},
13249  
13250		containsBox: function ( box ) {
13251  
13252			return this.min.x <= box.min.x && box.max.x <= this.max.x &&
13253				this.min.y <= box.min.y && box.max.y <= this.max.y &&
13254				this.min.z <= box.min.z && box.max.z <= this.max.z;
13255  
13256		},
13257  
13258		getParameter: function ( point, target ) {
13259  
13260			// This can potentially have a divide by zero if the box
13261			// has a size dimension of 0.
13262  
13263			if ( target === undefined ) {
13264  
13265				console.warn( 'THREE.Box3: .getParameter() target is now required' );
13266				target = new Vector3();
13267  
13268			}
13269  
13270			return target.set(
13271				( point.x - this.min.x ) / ( this.max.x - this.min.x ),
13272				( point.y - this.min.y ) / ( this.max.y - this.min.y ),
13273				( point.z - this.min.z ) / ( this.max.z - this.min.z )
13274			);
13275  
13276		},
13277  
13278		intersectsBox: function ( box ) {
13279  
13280			// using 6 splitting planes to rule out intersections.
13281			return box.max.x < this.min.x || box.min.x > this.max.x ||
13282				box.max.y < this.min.y || box.min.y > this.max.y ||
13283				box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
13284  
13285		},
13286  
13287		intersectsSphere: ( function () {
13288  
13289			var closestPoint = new Vector3();
13290  
13291			return function intersectsSphere( sphere ) {
13292  
13293				// Find the point on the AABB closest to the sphere center.
13294				this.clampPoint( sphere.center, closestPoint );
13295  
13296				// If that point is inside the sphere, the AABB and sphere intersect.
13297				return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
13298  
13299			};
13300  
13301		} )(),
13302  
13303		intersectsPlane: function ( plane ) {
13304  
13305			// We compute the minimum and maximum dot product values. If those values
13306			// are on the same side (back or front) of the plane, then there is no intersection.
13307  
13308			var min, max;
13309  
13310			if ( plane.normal.x > 0 ) {
13311  
13312				min = plane.normal.x * this.min.x;
13313				max = plane.normal.x * this.max.x;
13314  
13315			} else {
13316  
13317				min = plane.normal.x * this.max.x;
13318				max = plane.normal.x * this.min.x;
13319  
13320			}
13321  
13322			if ( plane.normal.y > 0 ) {
13323  
13324				min += plane.normal.y * this.min.y;
13325				max += plane.normal.y * this.max.y;
13326  
13327			} else {
13328  
13329				min += plane.normal.y * this.max.y;
13330				max += plane.normal.y * this.min.y;
13331  
13332			}
13333  
13334			if ( plane.normal.z > 0 ) {
13335  
13336				min += plane.normal.z * this.min.z;
13337				max += plane.normal.z * this.max.z;
13338  
13339			} else {
13340  
13341				min += plane.normal.z * this.max.z;
13342				max += plane.normal.z * this.min.z;
13343  
13344			}
13345  
13346			return ( min <= plane.constant && max >= plane.constant );
13347  
13348		},
13349  
13350		intersectsTriangle: ( function () {
13351  
13352			// triangle centered vertices
13353			var v0 = new Vector3();
13354			var v1 = new Vector3();
13355			var v2 = new Vector3();
13356  
13357			// triangle edge vectors
13358			var f0 = new Vector3();
13359			var f1 = new Vector3();
13360			var f2 = new Vector3();
13361  
13362			var testAxis = new Vector3();
13363  
13364			var center = new Vector3();
13365			var extents = new Vector3();
13366  
13367			var triangleNormal = new Vector3();
13368  
13369			function satForAxes( axes ) {
13370  
13371				var i, j;
13372  
13373				for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
13374  
13375					testAxis.fromArray( axes, i );
13376					// project the aabb onto the seperating axis
13377					var r = extents.x * Math.abs( testAxis.x ) + extents.y * Math.abs( testAxis.y ) + extents.z * Math.abs( testAxis.z );
13378					// project all 3 vertices of the triangle onto the seperating axis
13379					var p0 = v0.dot( testAxis );
13380					var p1 = v1.dot( testAxis );
13381					var p2 = v2.dot( testAxis );
13382					// actual test, basically see if either of the most extreme of the triangle points intersects r
13383					if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
13384  
13385						// points of the projected triangle are outside the projected half-length of the aabb
13386						// the axis is seperating and we can exit
13387						return false;
13388  
13389					}
13390  
13391				}
13392  
13393				return true;
13394  
13395			}
13396  
13397			return function intersectsTriangle( triangle ) {
13398  
13399				if ( this.isEmpty() ) {
13400  
13401					return false;
13402  
13403				}
13404  
13405				// compute box center and extents
13406				this.getCenter( center );
13407				extents.subVectors( this.max, center );
13408  
13409				// translate triangle to aabb origin
13410				v0.subVectors( triangle.a, center );
13411				v1.subVectors( triangle.b, center );
13412				v2.subVectors( triangle.c, center );
13413  
13414				// compute edge vectors for triangle
13415				f0.subVectors( v1, v0 );
13416				f1.subVectors( v2, v1 );
13417				f2.subVectors( v0, v2 );
13418  
13419				// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
13420				// 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
13421				// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
13422				var axes = [
13423					0, - f0.z, f0.y, 0, - f1.z, f1.y, 0, - f2.z, f2.y,
13424					f0.z, 0, - f0.x, f1.z, 0, - f1.x, f2.z, 0, - f2.x,
13425					- f0.y, f0.x, 0, - f1.y, f1.x, 0, - f2.y, f2.x, 0
13426				];
13427				if ( ! satForAxes( axes ) ) {
13428  
13429					return false;
13430  
13431				}
13432  
13433				// test 3 face normals from the aabb
13434				axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
13435				if ( ! satForAxes( axes ) ) {
13436  
13437					return false;
13438  
13439				}
13440  
13441				// finally testing the face normal of the triangle
13442				// use already existing triangle edge vectors here
13443				triangleNormal.crossVectors( f0, f1 );
13444				axes = [ triangleNormal.x, triangleNormal.y, triangleNormal.z ];
13445				return satForAxes( axes );
13446  
13447			};
13448  
13449		} )(),
13450  
13451		clampPoint: function ( point, target ) {
13452  
13453			if ( target === undefined ) {
13454  
13455				console.warn( 'THREE.Box3: .clampPoint() target is now required' );
13456				target = new Vector3();
13457  
13458			}
13459  
13460			return target.copy( point ).clamp( this.min, this.max );
13461  
13462		},
13463  
13464		distanceToPoint: function () {
13465  
13466			var v1 = new Vector3();
13467  
13468			return function distanceToPoint( point ) {
13469  
13470				var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
13471				return clampedPoint.sub( point ).length();
13472  
13473			};
13474  
13475		}(),
13476  
13477		getBoundingSphere: function () {
13478  
13479			var v1 = new Vector3();
13480  
13481			return function getBoundingSphere( target ) {
13482  
13483				if ( target === undefined ) {
13484  
13485					console.warn( 'THREE.Box3: .getBoundingSphere() target is now required' );
13486					target = new Sphere();
13487  
13488				}
13489  
13490				this.getCenter( target.center );
13491  
13492				target.radius = this.getSize( v1 ).length() * 0.5;
13493  
13494				return target;
13495  
13496			};
13497  
13498		}(),
13499  
13500		intersect: function ( box ) {
13501  
13502			this.min.max( box.min );
13503			this.max.min( box.max );
13504  
13505			// 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.
13506			if ( this.isEmpty() ) this.makeEmpty();
13507  
13508			return this;
13509  
13510		},
13511  
13512		union: function ( box ) {
13513  
13514			this.min.min( box.min );
13515			this.max.max( box.max );
13516  
13517			return this;
13518  
13519		},
13520  
13521		applyMatrix4: function ( matrix ) {
13522  
13523			// transform of empty box is an empty box.
13524			if ( this.isEmpty( ) ) return this;
13525  
13526			var m = matrix.elements;
13527  
13528			var xax = m[ 0 ] * this.min.x, xay = m[ 1 ] * this.min.x, xaz = m[ 2 ] * this.min.x;
13529			var xbx = m[ 0 ] * this.max.x, xby = m[ 1 ] * this.max.x, xbz = m[ 2 ] * this.max.x;
13530			var yax = m[ 4 ] * this.min.y, yay = m[ 5 ] * this.min.y, yaz = m[ 6 ] * this.min.y;
13531			var ybx = m[ 4 ] * this.max.y, yby = m[ 5 ] * this.max.y, ybz = m[ 6 ] * this.max.y;
13532			var zax = m[ 8 ] * this.min.z, zay = m[ 9 ] * this.min.z, zaz = m[ 10 ] * this.min.z;
13533			var zbx = m[ 8 ] * this.max.z, zby = m[ 9 ] * this.max.z, zbz = m[ 10 ] * this.max.z;
13534  
13535			this.min.x = Math.min( xax, xbx ) + Math.min( yax, ybx ) + Math.min( zax, zbx ) + m[ 12 ];
13536			this.min.y = Math.min( xay, xby ) + Math.min( yay, yby ) + Math.min( zay, zby ) + m[ 13 ];
13537			this.min.z = Math.min( xaz, xbz ) + Math.min( yaz, ybz ) + Math.min( zaz, zbz ) + m[ 14 ];
13538			this.max.x = Math.max( xax, xbx ) + Math.max( yax, ybx ) + Math.max( zax, zbx ) + m[ 12 ];
13539			this.max.y = Math.max( xay, xby ) + Math.max( yay, yby ) + Math.max( zay, zby ) + m[ 13 ];
13540			this.max.z = Math.max( xaz, xbz ) + Math.max( yaz, ybz ) + Math.max( zaz, zbz ) + m[ 14 ];
13541  
13542			return this;
13543  
13544		},
13545  
13546		translate: function ( offset ) {
13547  
13548			this.min.add( offset );
13549			this.max.add( offset );
13550  
13551			return this;
13552  
13553		},
13554  
13555		equals: function ( box ) {
13556  
13557			return box.min.equals( this.min ) && box.max.equals( this.max );
13558  
13559		}
13560  
13561	} );
13562  
13563	/**
13564	 * @author bhouston / http://clara.io
13565	 * @author mrdoob / http://mrdoob.com/
13566	 */
13567  
13568	function Sphere( center, radius ) {
13569  
13570		this.center = ( center !== undefined ) ? center : new Vector3();
13571		this.radius = ( radius !== undefined ) ? radius : 0;
13572  
13573	}
13574  
13575	Object.assign( Sphere.prototype, {
13576  
vendor: 7,519 bytes, lines 13577-13969
13577		set: function ( center, radius ) {
13578  
13579			this.center.copy( center );
13580			this.radius = radius;
13581  
13582			return this;
13583  
13584		},
13585  
13586		setFromPoints: function () {
13587  
13588			var box = new Box3();
13589  
13590			return function setFromPoints( points, optionalCenter ) {
13591  
13592				var center = this.center;
13593  
13594				if ( optionalCenter !== undefined ) {
13595  
13596					center.copy( optionalCenter );
13597  
13598				} else {
13599  
13600					box.setFromPoints( points ).getCenter( center );
13601  
13602				}
13603  
13604				var maxRadiusSq = 0;
13605  
13606				for ( var i = 0, il = points.length; i < il; i ++ ) {
13607  
13608					maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
13609  
13610				}
13611  
13612				this.radius = Math.sqrt( maxRadiusSq );
13613  
13614				return this;
13615  
13616			};
13617  
13618		}(),
13619  
13620		clone: function () {
13621  
13622			return new this.constructor().copy( this );
13623  
13624		},
13625  
13626		copy: function ( sphere ) {
13627  
13628			this.center.copy( sphere.center );
13629			this.radius = sphere.radius;
13630  
13631			return this;
13632  
13633		},
13634  
13635		empty: function () {
13636  
13637			return ( this.radius <= 0 );
13638  
13639		},
13640  
13641		containsPoint: function ( point ) {
13642  
13643			return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
13644  
13645		},
13646  
13647		distanceToPoint: function ( point ) {
13648  
13649			return ( point.distanceTo( this.center ) - this.radius );
13650  
13651		},
13652  
13653		intersectsSphere: function ( sphere ) {
13654  
13655			var radiusSum = this.radius + sphere.radius;
13656  
13657			return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
13658  
13659		},
13660  
13661		intersectsBox: function ( box ) {
13662  
13663			return box.intersectsSphere( this );
13664  
13665		},
13666  
13667		intersectsPlane: function ( plane ) {
13668  
13669			return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
13670  
13671		},
13672  
13673		clampPoint: function ( point, target ) {
13674  
13675			var deltaLengthSq = this.center.distanceToSquared( point );
13676  
13677			if ( target === undefined ) {
13678  
13679				console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
13680				target = new Vector3();
13681  
13682			}
13683  
13684			target.copy( point );
13685  
13686			if ( deltaLengthSq > ( this.radius * this.radius ) ) {
13687  
13688				target.sub( this.center ).normalize();
13689				target.multiplyScalar( this.radius ).add( this.center );
13690  
13691			}
13692  
13693			return target;
13694  
13695		},
13696  
13697		getBoundingBox: function ( target ) {
13698  
13699			if ( target === undefined ) {
13700  
13701				console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
13702				target = new Box3();
13703  
13704			}
13705  
13706			target.set( this.center, this.center );
13707			target.expandByScalar( this.radius );
13708  
13709			return target;
13710  
13711		},
13712  
13713		applyMatrix4: function ( matrix ) {
13714  
13715			this.center.applyMatrix4( matrix );
13716			this.radius = this.radius * matrix.getMaxScaleOnAxis();
13717  
13718			return this;
13719  
13720		},
13721  
13722		translate: function ( offset ) {
13723  
13724			this.center.add( offset );
13725  
13726			return this;
13727  
13728		},
13729  
13730		equals: function ( sphere ) {
13731  
13732			return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
13733  
13734		}
13735  
13736	} );
13737  
13738	/**
13739	 * @author bhouston / http://clara.io
13740	 */
13741  
13742	function Plane( normal, constant ) {
13743  
13744		// normal is assumed to be normalized
13745  
13746		this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
13747		this.constant = ( constant !== undefined ) ? constant : 0;
13748  
13749	}
13750  
13751	Object.assign( Plane.prototype, {
13752  
13753		set: function ( normal, constant ) {
13754  
13755			this.normal.copy( normal );
13756			this.constant = constant;
13757  
13758			return this;
13759  
13760		},
13761  
13762		setComponents: function ( x, y, z, w ) {
13763  
13764			this.normal.set( x, y, z );
13765			this.constant = w;
13766  
13767			return this;
13768  
13769		},
13770  
13771		setFromNormalAndCoplanarPoint: function ( normal, point ) {
13772  
13773			this.normal.copy( normal );
13774			this.constant = - point.dot( this.normal );
13775  
13776			return this;
13777  
13778		},
13779  
13780		setFromCoplanarPoints: function () {
13781  
13782			var v1 = new Vector3();
13783			var v2 = new Vector3();
13784  
13785			return function setFromCoplanarPoints( a, b, c ) {
13786  
13787				var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
13788  
13789				// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
13790  
13791				this.setFromNormalAndCoplanarPoint( normal, a );
13792  
13793				return this;
13794  
13795			};
13796  
13797		}(),
13798  
13799		clone: function () {
13800  
13801			return new this.constructor().copy( this );
13802  
13803		},
13804  
13805		copy: function ( plane ) {
13806  
13807			this.normal.copy( plane.normal );
13808			this.constant = plane.constant;
13809  
13810			return this;
13811  
13812		},
13813  
13814		normalize: function () {
13815  
13816			// Note: will lead to a divide by zero if the plane is invalid.
13817  
13818			var inverseNormalLength = 1.0 / this.normal.length();
13819			this.normal.multiplyScalar( inverseNormalLength );
13820			this.constant *= inverseNormalLength;
13821  
13822			return this;
13823  
13824		},
13825  
13826		negate: function () {
13827  
13828			this.constant *= - 1;
13829			this.normal.negate();
13830  
13831			return this;
13832  
13833		},
13834  
13835		distanceToPoint: function ( point ) {
13836  
13837			return this.normal.dot( point ) + this.constant;
13838  
13839		},
13840  
13841		distanceToSphere: function ( sphere ) {
13842  
13843			return this.distanceToPoint( sphere.center ) - sphere.radius;
13844  
13845		},
13846  
13847		projectPoint: function ( point, target ) {
13848  
13849			if ( target === undefined ) {
13850  
13851				console.warn( 'THREE.Plane: .projectPoint() target is now required' );
13852				target = new Vector3();
13853  
13854			}
13855  
13856			return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
13857  
13858		},
13859  
13860		intersectLine: function () {
13861  
13862			var v1 = new Vector3();
13863  
13864			return function intersectLine( line, target ) {
13865  
13866				if ( target === undefined ) {
13867  
13868					console.warn( 'THREE.Plane: .intersectLine() target is now required' );
13869					target = new Vector3();
13870  
13871				}
13872  
13873				var direction = line.delta( v1 );
13874  
13875				var denominator = this.normal.dot( direction );
13876  
13877				if ( denominator === 0 ) {
13878  
13879					// line is coplanar, return origin
13880					if ( this.distanceToPoint( line.start ) === 0 ) {
13881  
13882						return target.copy( line.start );
13883  
13884					}
13885  
13886					// Unsure if this is the correct method to handle this case.
13887					return undefined;
13888  
13889				}
13890  
13891				var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
13892  
13893				if ( t < 0 || t > 1 ) {
13894  
13895					return undefined;
13896  
13897				}
13898  
13899				return target.copy( direction ).multiplyScalar( t ).add( line.start );
13900  
13901			};
13902  
13903		}(),
13904  
13905		intersectsLine: function ( line ) {
13906  
13907			// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
13908  
13909			var startSign = this.distanceToPoint( line.start );
13910			var endSign = this.distanceToPoint( line.end );
13911  
13912			return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
13913  
13914		},
13915  
13916		intersectsBox: function ( box ) {
13917  
13918			return box.intersectsPlane( this );
13919  
13920		},
13921  
13922		intersectsSphere: function ( sphere ) {
13923  
13924			return sphere.intersectsPlane( this );
13925  
13926		},
13927  
13928		coplanarPoint: function ( target ) {
13929  
13930			if ( target === undefined ) {
13931  
13932				console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
13933				target = new Vector3();
13934  
13935			}
13936  
13937			return target.copy( this.normal ).multiplyScalar( - this.constant );
13938  
13939		},
13940  
13941		applyMatrix4: function () {
13942  
13943			var v1 = new Vector3();
13944			var m1 = new Matrix3();
13945  
13946			return function applyMatrix4( matrix, optionalNormalMatrix ) {
13947  
13948				var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
13949  
13950				var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
13951  
13952				var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
13953  
13954				this.constant = - referencePoint.dot( normal );
13955  
13956				return this;
13957  
13958			};
13959  
13960		}(),
13961  
13962		translate: function ( offset ) {
13963  
13964			this.constant -= offset.dot( this.normal );
13965  
13966			return this;
13967  
13968		},
13969  
vendor: 4,243 bytes, lines 13970-14161
13970		equals: function ( plane ) {
13971  
13972			return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
13973  
13974		}
13975  
13976	} );
13977  
13978	/**
13979	 * @author mrdoob / http://mrdoob.com/
13980	 * @author alteredq / http://alteredqualia.com/
13981	 * @author bhouston / http://clara.io
13982	 */
13983  
13984	function Frustum( p0, p1, p2, p3, p4, p5 ) {
13985  
13986		this.planes = [
13987  
13988			( p0 !== undefined ) ? p0 : new Plane(),
13989			( p1 !== undefined ) ? p1 : new Plane(),
13990			( p2 !== undefined ) ? p2 : new Plane(),
13991			( p3 !== undefined ) ? p3 : new Plane(),
13992			( p4 !== undefined ) ? p4 : new Plane(),
13993			( p5 !== undefined ) ? p5 : new Plane()
13994  
13995		];
13996  
13997	}
13998  
13999	Object.assign( Frustum.prototype, {
14000  
14001		set: function ( p0, p1, p2, p3, p4, p5 ) {
14002  
14003			var planes = this.planes;
14004  
14005			planes[ 0 ].copy( p0 );
14006			planes[ 1 ].copy( p1 );
14007			planes[ 2 ].copy( p2 );
14008			planes[ 3 ].copy( p3 );
14009			planes[ 4 ].copy( p4 );
14010			planes[ 5 ].copy( p5 );
14011  
14012			return this;
14013  
14014		},
14015  
14016		clone: function () {
14017  
14018			return new this.constructor().copy( this );
14019  
14020		},
14021  
14022		copy: function ( frustum ) {
14023  
14024			var planes = this.planes;
14025  
14026			for ( var i = 0; i < 6; i ++ ) {
14027  
14028				planes[ i ].copy( frustum.planes[ i ] );
14029  
14030			}
14031  
14032			return this;
14033  
14034		},
14035  
14036		setFromMatrix: function ( m ) {
14037  
14038			var planes = this.planes;
14039			var me = m.elements;
14040			var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
14041			var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
14042			var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
14043			var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
14044  
14045			planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
14046			planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
14047			planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
14048			planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
14049			planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
14050			planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
14051  
14052			return this;
14053  
14054		},
14055  
14056		intersectsObject: function () {
14057  
14058			var sphere = new Sphere();
14059  
14060			return function intersectsObject( object ) {
14061  
14062				var geometry = object.geometry;
14063  
14064				if ( geometry.boundingSphere === null )
14065					geometry.computeBoundingSphere();
14066  
14067				sphere.copy( geometry.boundingSphere )
14068					.applyMatrix4( object.matrixWorld );
14069  
14070				return this.intersectsSphere( sphere );
14071  
14072			};
14073  
14074		}(),
14075  
14076		intersectsSprite: function () {
14077  
14078			var sphere = new Sphere();
14079  
14080			return function intersectsSprite( sprite ) {
14081  
14082				sphere.center.set( 0, 0, 0 );
14083				sphere.radius = 0.7071067811865476;
14084				sphere.applyMatrix4( sprite.matrixWorld );
14085  
14086				return this.intersectsSphere( sphere );
14087  
14088			};
14089  
14090		}(),
14091  
14092		intersectsSphere: function ( sphere ) {
14093  
14094			var planes = this.planes;
14095			var center = sphere.center;
14096			var negRadius = - sphere.radius;
14097  
14098			for ( var i = 0; i < 6; i ++ ) {
14099  
14100				var distance = planes[ i ].distanceToPoint( center );
14101  
14102				if ( distance < negRadius ) {
14103  
14104					return false;
14105  
14106				}
14107  
14108			}
14109  
14110			return true;
14111  
14112		},
14113  
14114		intersectsBox: function () {
14115  
14116			var p1 = new Vector3(),
14117				p2 = new Vector3();
14118  
14119			return function intersectsBox( box ) {
14120  
14121				var planes = this.planes;
14122  
14123				for ( var i = 0; i < 6; i ++ ) {
14124  
14125					var plane = planes[ i ];
14126  
14127					p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
14128					p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
14129					p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
14130					p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
14131					p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
14132					p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
14133  
14134					var d1 = plane.distanceToPoint( p1 );
14135					var d2 = plane.distanceToPoint( p2 );
14136  
14137					// if both outside plane, no intersection
14138  
14139					if ( d1 < 0 && d2 < 0 ) {
14140  
14141						return false;
14142  
14143					}
14144  
14145				}
14146  
14147				return true;
14148  
14149			};
14150  
14151		}(),
14152  
14153		containsPoint: function ( point ) {
14154  
14155			var planes = this.planes;
14156  
14157			for ( var i = 0; i < 6; i ++ ) {
14158  
14159				if ( planes[ i ].distanceToPoint( point ) < 0 ) {
14160  
14161					return false;
14162  
14163				}
14164  
14165			}
14166  
14167			return true;
14168  
14169		}
14170  
14171	} );
14172  
14173	var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
14174  
14175	var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
14176  
14177	var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
14178  
14179	var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";
14180  
14181	var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
14182  
14183	var begin_vertex = "\nvec3 transformed = vec3( position );\n";
14184  
14185	var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
14186  
14187	var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;
14187\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );
14187\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 GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
14188  
14189	var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}
14189\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";
14190  
14191	var 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";
14192  
14193	var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
14194  
14195	var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
14196  
14197	var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
14198  
14199	var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
14200  
14201	var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
14202  
14203	var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
14204  
14205	var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
14206  
14207	var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";
14208  
14209	var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);
14209\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale =  bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";
14210  
14211	var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
14212  
14213	var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
14214  
14215	var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
14216  
14217	var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
14218  
14219	var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
14220  
14221	var encodings_fragment = "  gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
14222  
14223	var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}
14223\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M      = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM            = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D      = max( maxRange / maxRGB, 1.0 );\n\tD            = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n";
14224  
14225	var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n";
14226  
14227	var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n";
14228  
14229	var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n";
14230  
14231	var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;
14231\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n";
14232  
14233	var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
14234  
14235	var fog_pars_vertex = "#ifdef USE_FOG\n  varying float fogDepth;\n#endif\n";
14236  
14237	var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
14238  
14239	var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n";
14240  
14241	var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";
14242  
14243	var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
14244  
14245	var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
14246  
14247	var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\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\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";
14248  
14249	var lights_pars_begin = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}
14249\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";
14250  
14251	var lights_pars_maps = "#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShinine
14251ssExponent));\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";
14252  
14253	var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
14254  
14255	var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";
14256  
14257	var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
14258  
14259	var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;
14259\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#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
14260  
14261	var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\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#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}
14261\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#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\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#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\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 irradiance = getAmbientLightIrradiance( ambientLightColor );\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";
14262  
14263	var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n";
14264  
14265	var 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, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
14266  
14267	var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
14268  
14269	var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n";
14270  
14271	var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif";
14272  
14273	var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n";
14274  
14275	var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
14276  
14277	var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
14278  
14279	var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
14280  
14281	var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n";
14282  
14283	var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
14284  
14285	var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
14286  
14287	var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
14288  
14289	var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
14290  
14291	var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n";
14292  
14293	var 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#endif\n";
14294  
14295	var normal_fragment_maps = "#ifdef USE_NORMALMAP\n\tnormal = perturbN
14295ormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
14296  
14297	var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\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\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy *= normalScale;\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n";
14298  
14299	var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
14300  
14301	var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
14302  
14303	var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
14304  
14305	var dithering_fragment = "#if defined( DITHERING )\n  gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
14306  
14307	var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n";
14308  
14309	var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
14310  
14311	var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
14312  
14313	var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );
14313\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n";
14314  
14315	var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n";
14316  
14317	var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n";
14318  
14319	var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n";
14320  
14321	var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
14322  
14323	var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n";
14324  
14325	var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n";
14326  
14327	var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;
14327\n\tskinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
14328  
14329	var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
14330  
14331	var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
14332  
14333	var tonemapping_fragment = "#if defined( TONE_MAPPING )\n  gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
14334  
14335	var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
14336  
14337	var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif";
14338  
14339	var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n";
14340  
14341	var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
14342  
14343	var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
14344  
14345	var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
14346  
14347	var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
14348  
14349	var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
14350  
14351	var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n";
14352  
14353	var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}\n";
14354  
14355	var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 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";
14356  
14357	var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n";
14358  
14359	var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n";
14360  
14361	var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n";
14362  
14363	var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
14364  
14365	var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
14366  
14367	var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
14368  
14369	var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n";
14370  
14371	var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
14372  
14373	var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n";
14374  
14375	var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
14376  
14377	var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
14378  
14379	var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
14380  
14381	var meshphong_vert = "#define PHONG\nvarying vec3 vView
14381Position;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
14382  
14383	var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
14384  
14385	var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
14386  
14387	var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n";
14388  
14389	var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n";
14390  
14391	var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
14392  
14393	var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}\n";
14394  
14395	var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <fog_fragment>\n}\n";
14396  
14397	var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
14398  
14399	var ShaderChunk = {
14400		alphamap_fragment: alphamap_fragment,
14401		alphamap_pars_fragment: alphamap_pars_fragment,
14402		alphatest_fragment: alphatest_fragment,
14403		aomap_fragment: aomap_fragment,
14404		aomap_pars_fragment: aomap_pars_fragment,
14405		begin_vertex: begin_vertex,
14406		beginnormal_vertex: beginnormal_vertex,
14407		bsdfs: bsdfs,
14408		bumpmap_pars_fragment: bumpmap_pars_fragment,
14409		clipping_planes_fragment: clipping_planes_fragment,
14410		clipping_planes_pars_fragment: clipping_planes_pars_fragment,
14411		clipping_planes_pars_vertex: clipping_planes_pars_vertex,
14412		clipping_planes_vertex: clipping_planes_vertex,
14413		color_fragment: color_fragment,
14414		color_pars_fragment: color_pars_fragment,
14415		color_pars_vertex: color_pars_vertex,
14416		color_vertex: color_vertex,
14417		common: common,
14418		cube_uv_reflection_fragment: cube_uv_reflection_fragment,
14419		defaultnormal_vertex: defaultnormal_vertex,
14420		displacementmap_pars_vertex: displacementmap_pars_vertex,
14421		displacementmap_vertex: displacementmap_vertex,
14422		emissivemap_fragment: emissivemap_fragment,
14423		emissivemap_pars_fragment: emissivemap_pars_fragment,
14424		encodings_fragment: encodings_fragment,
14425		encodings_pars_fragment: encodings_pars_fragment,
14426		envmap_fragment: envmap_fragment,
14427		envmap_pars_fragment: envmap_pars_fragment,
14428		envmap_pars_vertex: envmap_pars_vertex,
14429		envmap_vertex: envmap_vertex,
14430		fog_vertex: fog_vertex,
14431		fog_pars_vertex: fog_pars_vertex,
14432		fog_fragment: fog_fragment,
14433		fog_pars_fragment: fog_pars_fragment,
14434		gradientmap_pars_fragment: gradientmap_pars_fragment,
14435		lightmap_fragment: lightmap_fragment,
14436		lightmap_pars_fragment: lightmap_pars_fragment,
14437		lights_lambert_vertex: lights_lambert_vertex,
14438		lights_pars_begin: lights_pars_begin,
14439		lights_pars_maps: lights_pars_maps,
14440		lights_phong_fragment: lights_phong_fragment,
14441		lights_phong_pars_fragment: lights_phong_pars_fragment,
14442		lights_physical_fragment: lights_physical_fragment,
14443		lights_physical_pars_fragment: lights_physical_pars_fragment,
14444		lights_fragment_begin: lights_fragment_begin,
14445		lights_fragment_maps: lights_fragment_maps,
14446		lights_fragment_end: lights_fragment_end,
14447		logdepthbuf_fragment: logdepthbuf_fragment,
14448		logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
14449		logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
14450		logdepthbuf_vertex: logdepthbuf_vertex,
14451		map_fragment: map_fragment,
14452		map_pars_fragment: map_pars_fragment,
14453		map_particle_fragment: map_particle_fragment,
14454		map_particle_pars_fragment: map_particle_pars_fragment,
14455		metalnessmap_fragment: metalnessmap_fragment,
14456		metalnessmap_pars_fragment: metalnessmap_pars_fragment,
14457		morphnormal_vertex: morphnormal_vertex,
14458		morphtarget_pars_vertex: morphtarget_pars_vertex,
14459		morphtarget_vertex: morphtarget_vertex,
14460		normal_fragment_begin: normal_fragment_begin,
14461		normal_fragment_maps: normal_fragment_maps,
14462		normalmap_pars_fragment: normalmap_pars_fragment,
14463		packing: packing,
14464		premultiplied_alpha_fragment: premultiplied_alpha_fragment,
14465		project_vertex: project_vertex,
14466		dithering_fragment: dithering_fragment,
14467		dithering_pars_fragment: dithering_pars_fragment,
14468		roughnessmap_fragment: roughnessmap_fragment,
14469		roughnessmap_pars_fragment: roughnessmap_pars_fragment,
14470		shadowmap_pars_fragment: shadowmap_pars_fragment,
14471		shadowmap_pars_vertex: shadowmap_pars_vertex,
14472		shadowmap_vertex: shadowmap_vertex,
14473		shadowmask_pars_fragment: shadowmask_pars_fragment,
14474		skinbase_vertex: skinbase_vertex,
14475		skinning_pars_vertex: skinning_pars_vertex,
14476		skinning_vertex: skinning_vertex,
14477		skinnormal_vertex: skinnormal_vertex,
14478		specularmap_fragment: specularmap_fragment,
14479		specularmap_pars_fragment: specularmap_pars_fragment,
14480		tonemapping_fragment: tonemapping_fragment,
14481		tonemapping_pars_fragment: tonemapping_pars_fragment,
14482		uv_pars_fragment: uv_pars_fragment,
14483		uv_pars_vertex: uv_pars_vertex,
14484		uv_vertex: uv_vertex,
14485		uv2_pars_fragment: uv2_pars_fragment,
14486		uv2_pars_vertex: uv2_pars_vertex,
14487		uv2_vertex: uv2_vertex,
14488		worldpos_vertex: worldpos_vertex,
14489  
14490		cube_frag: cube_frag,
14491		cube_vert: cube_vert,
14492		depth_frag: depth_frag,
14493		depth_vert: depth_vert,
14494		distanceRGBA_frag: distanceRGBA_frag,
14495		distanceRGBA_vert: distanceRGBA_vert,
14496		equirect_frag: equirect_frag,
14497		equirect_vert: equirect_vert,
14498		linedashed_frag: linedashed_frag,
14499		linedashed_vert: linedashed_vert,
14500		meshbasic_frag: meshbasic_frag,
14501		meshbasic_vert: meshbasic_vert,
14502		meshlambert_frag: meshlambert_frag,
14503		meshlambert_vert: meshlambert_vert,
14504		meshphong_frag: meshphong_frag,
14505		meshphong_vert: meshphong_vert,
14506		meshphysical_frag: meshphysical_frag,
14507		meshphysical_vert: meshphysical_vert,
14508		normal_frag: normal_frag,
14509		normal_vert: normal_vert,
14510		points_frag: points_frag,
14511		points_vert: points_vert,
14512		shadow_frag: shadow_frag,
14513		shadow_vert: shadow_vert
14514	};
14515  
14516	/**
14517	 * Uniform Utilities
14518	 */
14519  
14520	var UniformsUtils = {
14521  
14522		merge: function ( uniforms ) {
14523  
14524			var merged = {};
14525  
14526			for ( var u = 0; u < uniforms.length; u ++ ) {
14527  
14528				var tmp = this.clone( uniforms[ u ] );
14529  
14530				for ( var p in tmp ) {
14531  
14532					merged[ p ] = tmp[ p ];
14533  
14534				}
14535  
14536			}
14537  
14538			return merged;
14539  
14540		},
14541  
14542		clone: function ( uniforms_src ) {
14543  
14544			var uniforms_dst = {};
14545  
14546			for ( var u in uniforms_src ) {
14547  
14548				uniforms_dst[ u ] = {};
14549  
14550				for ( var p in uniforms_src[ u ] ) {
14551  
14552					var parameter_src = uniforms_src[ u ][ p ];
14553  
14554					if ( parameter_src && ( parameter_src.isColor ||
14555						parameter_src.isMatrix3 || parameter_src.isMatrix4 ||
14556						parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 ||
14557						parameter_src.isTexture ) ) {
14558  
14559						uniforms_dst[ u ][ p ] = parameter_src.clone();
14560  
14561					} else if ( Array.isArray( parameter_src ) ) {
14562  
14563						uniforms_dst[ u ][ p ] = parameter_src.slice();
14564  
14565					} else {
14566  
14567						uniforms_dst[ u ][ p ] = parameter_src;
14568  
14569					}
14570  
14571				}
14572  
14573			}
14574  
14575			return uniforms_dst;
14576  
14577		}
14578  
14579	};
14580  
14581	/**
14582	 * @author mrdoob / http://mrdoob.com/
14583	 */
14584  
14585	var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
14586		'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
14587		'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
14588		'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
14589		'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
14590		'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
14591		'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
14592		'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
14593		'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
14594		'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
14595		'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
14596		'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
14597		'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
14598		'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
14599		'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
14600		'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
14601		'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
14602		'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
14603		'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
14604		'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
14605		'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
14606		'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
14607		'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
14608		'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
14609  
14610	function Color( r, g, b ) {
14611  
14612		if ( g === undefined && b === undefined ) {
14613  
14614			// r is THREE.Color, hex or string
14615			return this.set( r );
14616  
14617		}
14618  
14619		return this.setRGB( r, g, b );
14620  
14621	}
14622  
14623	Object.assign( Color.prototype, {
14624  
vendor: 12,238 bytes, lines 14625-15307
14625		isColor: true,
14626  
14627		r: 1, g: 1, b: 1,
14628  
14629		set: function ( value ) {
14630  
14631			if ( value && value.isColor ) {
14632  
14633				this.copy( value );
14634  
14635			} else if ( typeof value === 'number' ) {
14636  
14637				this.setHex( value );
14638  
14639			} else if ( typeof value === 'string' ) {
14640  
14641				this.setStyle( value );
14642  
14643			}
14644  
14645			return this;
14646  
14647		},
14648  
14649		setScalar: function ( scalar ) {
14650  
14651			this.r = scalar;
14652			this.g = scalar;
14653			this.b = scalar;
14654  
14655			return this;
14656  
14657		},
14658  
14659		setHex: function ( hex ) {
14660  
14661			hex = Math.floor( hex );
14662  
14663			this.r = ( hex >> 16 & 255 ) / 255;
14664			this.g = ( hex >> 8 & 255 ) / 255;
14665			this.b = ( hex & 255 ) / 255;
14666  
14667			return this;
14668  
14669		},
14670  
14671		setRGB: function ( r, g, b ) {
14672  
14673			this.r = r;
14674			this.g = g;
14675			this.b = b;
14676  
14677			return this;
14678  
14679		},
14680  
14681		setHSL: function () {
14682  
14683			function hue2rgb( p, q, t ) {
14684  
14685				if ( t < 0 ) t += 1;
14686				if ( t > 1 ) t -= 1;
14687				if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
14688				if ( t < 1 / 2 ) return q;
14689				if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
14690				return p;
14691  
14692			}
14693  
14694			return function setHSL( h, s, l ) {
14695  
14696				// h,s,l ranges are in 0.0 - 1.0
14697				h = _Math.euclideanModulo( h, 1 );
14698				s = _Math.clamp( s, 0, 1 );
14699				l = _Math.clamp( l, 0, 1 );
14700  
14701				if ( s === 0 ) {
14702  
14703					this.r = this.g = this.b = l;
14704  
14705				} else {
14706  
14707					var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
14708					var q = ( 2 * l ) - p;
14709  
14710					this.r = hue2rgb( q, p, h + 1 / 3 );
14711					this.g = hue2rgb( q, p, h );
14712					this.b = hue2rgb( q, p, h - 1 / 3 );
14713  
14714				}
14715  
14716				return this;
14717  
14718			};
14719  
14720		}(),
14721  
14722		setStyle: function ( style ) {
14723  
14724			function handleAlpha( string ) {
14725  
14726				if ( string === undefined ) return;
14727  
14728				if ( parseFloat( string ) < 1 ) {
14729  
14730					console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
14731  
14732				}
14733  
14734			}
14735  
14736  
14737			var m;
14738  
14739			if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
14740  
14741				// rgb / hsl
14742  
14743				var color;
14744				var name = m[ 1 ];
14745				var components = m[ 2 ];
14746  
14747				switch ( name ) {
14748  
14749					case 'rgb':
14750					case 'rgba':
14751  
14752						if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
14753  
14754							// rgb(255,0,0) rgba(255,0,0,0.5)
14755							this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
14756							this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
14757							this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
14758  
14759							handleAlpha( color[ 5 ] );
14760  
14761							return this;
14762  
14763						}
14764  
14765						if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
14766  
14767							// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
14768							this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
14769							this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
14770							this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
14771  
14772							handleAlpha( color[ 5 ] );
14773  
14774							return this;
14775  
14776						}
14777  
14778						break;
14779  
14780					case 'hsl':
14781					case 'hsla':
14782  
14783						if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
14784  
14785							// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
14786							var h = parseFloat( color[ 1 ] ) / 360;
14787							var s = parseInt( color[ 2 ], 10 ) / 100;
14788							var l = parseInt( color[ 3 ], 10 ) / 100;
14789  
14790							handleAlpha( color[ 5 ] );
14791  
14792							return this.setHSL( h, s, l );
14793  
14794						}
14795  
14796						break;
14797  
14798				}
14799  
14800			} else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
14801  
14802				// hex color
14803  
14804				var hex = m[ 1 ];
14805				var size = hex.length;
14806  
14807				if ( size === 3 ) {
14808  
14809					// #ff0
14810					this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
14811					this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
14812					this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
14813  
14814					return this;
14815  
14816				} else if ( size === 6 ) {
14817  
14818					// #ff0000
14819					this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
14820					this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
14821					this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
14822  
14823					return this;
14824  
14825				}
14826  
14827			}
14828  
14829			if ( style && style.length > 0 ) {
14830  
14831				// color keywords
14832				var hex = ColorKeywords[ style ];
14833  
14834				if ( hex !== undefined ) {
14835  
14836					// red
14837					this.setHex( hex );
14838  
14839				} else {
14840  
14841					// unknown color
14842					console.warn( 'THREE.Color: Unknown color ' + style );
14843  
14844				}
14845  
14846			}
14847  
14848			return this;
14849  
14850		},
14851  
14852		clone: function () {
14853  
14854			return new this.constructor( this.r, this.g, this.b );
14855  
14856		},
14857  
14858		copy: function ( color ) {
14859  
14860			this.r = color.r;
14861			this.g = color.g;
14862			this.b = color.b;
14863  
14864			return this;
14865  
14866		},
14867  
14868		copyGammaToLinear: function ( color, gammaFactor ) {
14869  
14870			if ( gammaFactor === undefined ) gammaFactor = 2.0;
14871  
14872			this.r = Math.pow( color.r, gammaFactor );
14873			this.g = Math.pow( color.g, gammaFactor );
14874			this.b = Math.pow( color.b, gammaFactor );
14875  
14876			return this;
14877  
14878		},
14879  
14880		copyLinearToGamma: function ( color, gammaFactor ) {
14881  
14882			if ( gammaFactor === undefined ) gammaFactor = 2.0;
14883  
14884			var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
14885  
14886			this.r = Math.pow( color.r, safeInverse );
14887			this.g = Math.pow( color.g, safeInverse );
14888			this.b = Math.pow( color.b, safeInverse );
14889  
14890			return this;
14891  
14892		},
14893  
14894		convertGammaToLinear: function ( gammaFactor ) {
14895  
14896			this.copyGammaToLinear( this, gammaFactor );
14897  
14898			return this;
14899  
14900		},
14901  
14902		convertLinearToGamma: function ( gammaFactor ) {
14903  
14904			this.copyLinearToGamma( this, gammaFactor );
14905  
14906			return this;
14907  
14908		},
14909  
14910		getHex: function () {
14911  
14912			return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
14913  
14914		},
14915  
14916		getHexString: function () {
14917  
14918			return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
14919  
14920		},
14921  
14922		getHSL: function ( target ) {
14923  
14924			// h,s,l ranges are in 0.0 - 1.0
14925  
14926			if ( target === undefined ) {
14927  
14928				console.warn( 'THREE.Color: .getHSL() target is now required' );
14929				target = { h: 0, s: 0, l: 0 };
14930  
14931			}
14932  
14933			var r = this.r, g = this.g, b = this.b;
14934  
14935			var max = Math.max( r, g, b );
14936			var min = Math.min( r, g, b );
14937  
14938			var hue, saturation;
14939			var lightness = ( min + max ) / 2.0;
14940  
14941			if ( min === max ) {
14942  
14943				hue = 0;
14944				saturation = 0;
14945  
14946			} else {
14947  
14948				var delta = max - min;
14949  
14950				saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
14951  
14952				switch ( max ) {
14953  
14954					case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
14955					case g: hue = ( b - r ) / delta + 2; break;
14956					case b: hue = ( r - g ) / delta + 4; break;
14957  
14958				}
14959  
14960				hue /= 6;
14961  
14962			}
14963  
14964			target.h = hue;
14965			target.s = saturation;
14966			target.l = lightness;
14967  
14968			return target;
14969  
14970		},
14971  
14972		getStyle: function () {
14973  
14974			return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
14975  
14976		},
14977  
14978		offsetHSL: function () {
14979  
14980			var hsl = {};
14981  
14982			return function ( h, s, l ) {
14983  
14984				this.getHSL( hsl );
14985  
14986				hsl.h += h; hsl.s += s; hsl.l += l;
14987  
14988				this.setHSL( hsl.h, hsl.s, hsl.l );
14989  
14990				return this;
14991  
14992			};
14993  
14994		}(),
14995  
14996		add: function ( color ) {
14997  
14998			this.r += color.r;
14999			this.g += color.g;
15000			this.b += color.b;
15001  
15002			return this;
15003  
15004		},
15005  
15006		addColors: function ( color1, color2 ) {
15007  
15008			this.r = color1.r + color2.r;
15009			this.g = color1.g + color2.g;
15010			this.b = color1.b + color2.b;
15011  
15012			return this;
15013  
15014		},
15015  
15016		addScalar: function ( s ) {
15017  
15018			this.r += s;
15019			this.g += s;
15020			this.b += s;
15021  
15022			return this;
15023  
15024		},
15025  
15026		sub: function ( color ) {
15027  
15028			this.r = Math.max( 0, this.r - color.r );
15029			this.g = Math.max( 0, this.g - color.g );
15030			this.b = Math.max( 0, this.b - color.b );
15031  
15032			return this;
15033  
15034		},
15035  
15036		multiply: function ( color ) {
15037  
15038			this.r *= color.r;
15039			this.g *= color.g;
15040			this.b *= color.b;
15041  
15042			return this;
15043  
15044		},
15045  
15046		multiplyScalar: function ( s ) {
15047  
15048			this.r *= s;
15049			this.g *= s;
15050			this.b *= s;
15051  
15052			return this;
15053  
15054		},
15055  
15056		lerp: function ( color, alpha ) {
15057  
15058			this.r += ( color.r - this.r ) * alpha;
15059			this.g += ( color.g - this.g ) * alpha;
15060			this.b += ( color.b - this.b ) * alpha;
15061  
15062			return this;
15063  
15064		},
15065  
15066		equals: function ( c ) {
15067  
15068			return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
15069  
15070		},
15071  
15072		fromArray: function ( array, offset ) {
15073  
15074			if ( offset === undefined ) offset = 0;
15075  
15076			this.r = array[ offset ];
15077			this.g = array[ offset + 1 ];
15078			this.b = array[ offset + 2 ];
15079  
15080			return this;
15081  
15082		},
15083  
15084		toArray: function ( array, offset ) {
15085  
15086			if ( array === undefined ) array = [];
15087			if ( offset === undefined ) offset = 0;
15088  
15089			array[ offset ] = this.r;
15090			array[ offset + 1 ] = this.g;
15091			array[ offset + 2 ] = this.b;
15092  
15093			return array;
15094  
15095		},
15096  
15097		toJSON: function () {
15098  
15099			return this.getHex();
15100  
15101		}
15102  
15103	} );
15104  
15105	/**
15106	 * Uniforms library for shared webgl shaders
15107	 */
15108  
15109	var UniformsLib = {
15110  
15111		common: {
15112  
15113			diffuse: { value: new Color( 0xeeeeee ) },
15114			opacity: { value: 1.0 },
15115  
15116			map: { value: null },
15117			uvTransform: { value: new Matrix3() },
15118  
15119			alphaMap: { value: null },
15120  
15121		},
15122  
15123		specularmap: {
15124  
15125			specularMap: { value: null },
15126  
15127		},
15128  
15129		envmap: {
15130  
15131			envMap: { value: null },
15132			flipEnvMap: { value: - 1 },
15133			reflectivity: { value: 1.0 },
15134			refractionRatio: { value: 0.98 },
15135			maxMipLevel: { value: 0 }
15136  
15137		},
15138  
15139		aomap: {
15140  
15141			aoMap: { value: null },
15142			aoMapIntensity: { value: 1 }
15143  
15144		},
15145  
15146		lightmap: {
15147  
15148			lightMap: { value: null },
15149			lightMapIntensity: { value: 1 }
15150  
15151		},
15152  
15153		emissivemap: {
15154  
15155			emissiveMap: { value: null }
15156  
15157		},
15158  
15159		bumpmap: {
15160  
15161			bumpMap: { value: null },
15162			bumpScale: { value: 1 }
15163  
15164		},
15165  
15166		normalmap: {
15167  
15168			normalMap: { value: null },
15169			normalScale: { value: new Vector2( 1, 1 ) }
15170  
15171		},
15172  
15173		displacementmap: {
15174  
15175			displacementMap: { value: null },
15176			displacementScale: { value: 1 },
15177			displacementBias: { value: 0 }
15178  
15179		},
15180  
15181		roughnessmap: {
15182  
15183			roughnessMap: { value: null }
15184  
15185		},
15186  
15187		metalnessmap: {
15188  
15189			metalnessMap: { value: null }
15190  
15191		},
15192  
15193		gradientmap: {
15194  
15195			gradientMap: { value: null }
15196  
15197		},
15198  
15199		fog: {
15200  
15201			fogDensity: { value: 0.00025 },
15202			fogNear: { value: 1 },
15203			fogFar: { value: 2000 },
15204			fogColor: { value: new Color( 0xffffff ) }
15205  
15206		},
15207  
15208		lights: {
15209  
15210			ambientLightColor: { value: [] },
15211  
15212			directionalLights: { value: [], properties: {
15213				direction: {},
15214				color: {},
15215  
15216				shadow: {},
15217				shadowBias: {},
15218				shadowRadius: {},
15219				shadowMapSize: {}
15220			} },
15221  
15222			directionalShadowMap: { value: [] },
15223			directionalShadowMatrix: { value: [] },
15224  
15225			spotLights: { value: [], properties: {
15226				color: {},
15227				position: {},
15228				direction: {},
15229				distance: {},
15230				coneCos: {},
15231				penumbraCos: {},
15232				decay: {},
15233  
15234				shadow: {},
15235				shadowBias: {},
15236				shadowRadius: {},
15237				shadowMapSize: {}
15238			} },
15239  
15240			spotShadowMap: { value: [] },
15241			spotShadowMatrix: { value: [] },
15242  
15243			pointLights: { value: [], properties: {
15244				color: {},
15245				position: {},
15246				decay: {},
15247				distance: {},
15248  
15249				shadow: {},
15250				shadowBias: {},
15251				shadowRadius: {},
15252				shadowMapSize: {},
15253				shadowCameraNear: {},
15254				shadowCameraFar: {}
15255			} },
15256  
15257			pointShadowMap: { value: [] },
15258			pointShadowMatrix: { value: [] },
15259  
15260			hemisphereLights: { value: [], properties: {
15261				direction: {},
15262				skyColor: {},
15263				groundColor: {}
15264			} },
15265  
15266			// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
15267			rectAreaLights: { value: [], properties: {
15268				color: {},
15269				position: {},
15270				width: {},
15271				height: {}
15272			} }
15273  
15274		},
15275  
15276		points: {
15277  
15278			diffuse: { value: new Color( 0xeeeeee ) },
15279			opacity: { value: 1.0 },
15280			size: { value: 1.0 },
15281			scale: { value: 1.0 },
15282			map: { value: null },
15283			uvTransform: { value: new Matrix3() }
15284  
15285		}
15286  
15287	};
15288  
15289	/**
15290	 * @author alteredq / http://alteredqualia.com/
15291	 * @author mrdoob / http://mrdoob.com/
15292	 * @author mikael emtinger / http://gomo.se/
15293	 */
15294  
15295	var ShaderLib = {
15296  
15297		basic: {
15298  
15299			uniforms: UniformsUtils.merge( [
15300				UniformsLib.common,
15301				UniformsLib.specularmap,
15302				UniformsLib.envmap,
15303				UniformsLib.aomap,
15304				UniformsLib.lightmap,
15305				UniformsLib.fog
15306			] ),
15307  
15308			vertexShader: ShaderChunk.meshbasic_vert,
15309			fragmentShader: ShaderChunk.meshbasic_frag
15310  
15311		},
15312  
15313		lambert: {
15314  
15315			uniforms: UniformsUtils.merge( [
15316				UniformsLib.common,
15317				UniformsLib.specularmap,
15318				UniformsLib.envmap,
15319				UniformsLib.aomap,
15320				UniformsLib.lightmap,
15321				UniformsLib.emissivemap,
15322				UniformsLib.fog,
15323				UniformsLib.lights,
15324				{
15325					emissive: { value: new Color( 0x000000 ) }
15326				}
15327			] ),
15328  
15329			vertexShader: ShaderChunk.meshlambert_vert,
15330			fragmentShader: ShaderChunk.meshlambert_frag
15331  
15332		},
15333  
15334		phong: {
15335  
15336			uniforms: UniformsUtils.merge( [
15337				UniformsLib.common,
15338				UniformsLib.specularmap,
15339				UniformsLib.envmap,
15340				UniformsLib.aomap,
15341				UniformsLib.lightmap,
15342				UniformsLib.emissivemap,
15343				UniformsLib.bumpmap,
15344				UniformsLib.normalmap,
15345				UniformsLib.displacementmap,
15346				UniformsLib.gradientmap,
15347				UniformsLib.fog,
15348				UniformsLib.lights,
15349				{
15350					emissive: { value: new Color( 0x000000 ) },
15351					specular: { value: new Color( 0x111111 ) },
15352					shininess: { value: 30 }
15353				}
15354			] ),
15355  
15356			vertexShader: ShaderChunk.meshphong_vert,
15357			fragmentShader: ShaderChunk.meshphong_frag
15358  
15359		},
15360  
15361		standard: {
15362  
15363			uniforms: UniformsUtils.merge( [
15364				UniformsLib.common,
15365				UniformsLib.envmap,
15366				UniformsLib.aomap,
15367				UniformsLib.lightmap,
15368				UniformsLib.emissivemap,
15369				UniformsLib.bumpmap,
15370				UniformsLib.normalmap,
15371				UniformsLib.displacementmap,
15372				UniformsLib.roughnessmap,
15373				UniformsLib.metalnessmap,
15374				UniformsLib.fog,
15375				UniformsLib.lights,
15376				{
15377					emissive: { value: new Color( 0x000000 ) },
15378					roughness: { value: 0.5 },
15379					metalness: { value: 0.5 },
15380					envMapIntensity: { value: 1 } // temporary
15381				}
15382			] ),
15383  
15384			vertexShader: ShaderChunk.meshphysical_vert,
15385			fragmentShader: ShaderChunk.meshphysical_frag
15386  
15387		},
15388  
15389		points: {
15390  
15391			uniforms: UniformsUtils.merge( [
15392				UniformsLib.points,
15393				UniformsLib.fog
15394			] ),
15395  
vendor: 2,046 bytes, lines 15396-15502
15396			vertexShader: ShaderChunk.points_vert,
15397			fragmentShader: ShaderChunk.points_frag
15398  
15399		},
15400  
15401		dashed: {
15402  
15403			uniforms: UniformsUtils.merge( [
15404				UniformsLib.common,
15405				UniformsLib.fog,
15406				{
15407					scale: { value: 1 },
15408					dashSize: { value: 1 },
15409					totalSize: { value: 2 }
15410				}
15411			] ),
15412  
15413			vertexShader: ShaderChunk.linedashed_vert,
15414			fragmentShader: ShaderChunk.linedashed_frag
15415  
15416		},
15417  
15418		depth: {
15419  
15420			uniforms: UniformsUtils.merge( [
15421				UniformsLib.common,
15422				UniformsLib.displacementmap
15423			] ),
15424  
15425			vertexShader: ShaderChunk.depth_vert,
15426			fragmentShader: ShaderChunk.depth_frag
15427  
15428		},
15429  
15430		normal: {
15431  
15432			uniforms: UniformsUtils.merge( [
15433				UniformsLib.common,
15434				UniformsLib.bumpmap,
15435				UniformsLib.normalmap,
15436				UniformsLib.displacementmap,
15437				{
15438					opacity: { value: 1.0 }
15439				}
15440			] ),
15441  
15442			vertexShader: ShaderChunk.normal_vert,
15443			fragmentShader: ShaderChunk.normal_frag
15444  
15445		},
15446  
15447		/* -------------------------------------------------------------------------
15448		//	Cube map shader
15449		 ------------------------------------------------------------------------- */
15450  
15451		cube: {
15452  
15453			uniforms: {
15454				tCube: { value: null },
15455				tFlip: { value: - 1 },
15456				opacity: { value: 1.0 }
15457			},
15458  
15459			vertexShader: ShaderChunk.cube_vert,
15460			fragmentShader: ShaderChunk.cube_frag
15461  
15462		},
15463  
15464		equirect: {
15465  
15466			uniforms: {
15467				tEquirect: { value: null },
15468			},
15469  
15470			vertexShader: ShaderChunk.equirect_vert,
15471			fragmentShader: ShaderChunk.equirect_frag
15472  
15473		},
15474  
15475		distanceRGBA: {
15476  
15477			uniforms: UniformsUtils.merge( [
15478				UniformsLib.common,
15479				UniformsLib.displacementmap,
15480				{
15481					referencePosition: { value: new Vector3() },
15482					nearDistance: { value: 1 },
15483					farDistance: { value: 1000 }
15484				}
15485			] ),
15486  
15487			vertexShader: ShaderChunk.distanceRGBA_vert,
15488			fragmentShader: ShaderChunk.distanceRGBA_frag
15489  
15490		},
15491  
15492		shadow: {
15493  
15494			uniforms: UniformsUtils.merge( [
15495				UniformsLib.lights,
15496				UniformsLib.fog,
15497				{
15498					color: { value: new Color( 0x00000 ) },
15499					opacity: { value: 1.0 }
15500				},
15501			] ),
15502  
15503			vertexShader: ShaderChunk.shadow_vert,
15504			fragmentShader: ShaderChunk.shadow_frag
15505  
15506		}
15507  
15508	};
15509  
15510	ShaderLib.physical = {
15511  
15512		uniforms: UniformsUtils.merge( [
15513			ShaderLib.standard.uniforms,
15514			{
15515				clearCoat: { value: 0 },
15516				clearCoatRoughness: { value: 0 }
15517			}
15518		] ),
15519  
15520		vertexShader: ShaderChunk.meshphysical_vert,
15521		fragmentShader: ShaderChunk.meshphysical_frag
15522  
15523	};
15524  
15525	/**
15526	 * @author mrdoob / http://mrdoob.com/
15527	 */
15528  
15529	function WebGLAnimation() {
15530  
15531		var context = null;
15532		var isAnimating = false;
15533		var animationLoop = null;
15534  
15535		function onAnimationFrame( time, frame ) {
15536  
15537			if ( isAnimating === false ) return;
15538  
15539			animationLoop( time, frame );
15540  
15541			context.requestAnimationFrame( onAnimationFrame );
15542  
15543		}
15544  
15545		return {
15546  
15547			start: function () {
15548  
15549				if ( isAnimating === true ) return;
15550				if ( animationLoop === null ) return;
15551  
15552				context.requestAnimationFrame( onAnimationFrame );
15553  
15554				isAnimating = true;
15555  
15556			},
15557  
15558			stop: function () {
15559  
15560				isAnimating = false;
15561  
15562			},
15563  
15564			setAnimationLoop: function ( callback ) {
15565  
15566				animationLoop = callback;
15567  
15568			},
15569  
15570			setContext: function ( value ) {
15571  
15572				context = value;
15573  
15574			}
15575  
15576		};
15577  
15578	}
15579  
15580	/**
15581	 * @author mrdoob / http://mrdoob.com/
15582	 */
15583  
15584	function WebGLAttributes( gl ) {
15585  
15586		var buffers = new WeakMap();
15587  
15588		function createBuffer( attribute, bufferType ) {
15589  
15590			var array = attribute.array;
15591			var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
15592  
15593			var buffer = gl.createBuffer();
15594  
15595			gl.bindBuffer( bufferType, buffer );
15596			gl.bufferData( bufferType, array, usage );
15597  
15598			attribute.onUploadCallback();
15599  
15600			var type = gl.FLOAT;
15601  
15602			if ( array instanceof Float32Array ) {
15603  
15604				type = gl.FLOAT;
15605  
15606			} else if ( array instanceof Float64Array ) {
15607  
15608				console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
15609  
15610			} else if ( array instanceof Uint16Array ) {
15611  
15612				type = gl.UNSIGNED_SHORT;
15613  
15614			} else if ( array instanceof Int16Array ) {
15615  
15616				type = gl.SHORT;
15617  
15618			} else if ( array instanceof Uint32Array ) {
15619  
15620				type = gl.UNSIGNED_INT;
15621  
15622			} else if ( array instanceof Int32Array ) {
15623  
15624				type = gl.INT;
15625  
15626			} else if ( array instanceof Int8Array ) {
15627  
15628				type = gl.BYTE;
15629  
15630			} else if ( array instanceof Uint8Array ) {
15631  
15632				type = gl.UNSIGNED_BYTE;
15633  
15634			}
15635  
15636			return {
15637				buffer: buffer,
15638				type: type,
15639				bytesPerElement: array.BYTES_PER_ELEMENT,
15640				version: attribute.version
15641			};
15642  
15643		}
15644  
15645		function updateBuffer( buffer, attribute, bufferType ) {
15646  
15647			var array = attribute.array;
15648			var updateRange = attribute.updateRange;
15649  
15650			gl.bindBuffer( bufferType, buffer );
15651  
15652			if ( attribute.dynamic === false ) {
15653  
15654				gl.bufferData( bufferType, array, gl.STATIC_DRAW );
15655  
15656			} else if ( updateRange.count === - 1 ) {
15657  
15658				// Not using update ranges
15659  
15660				gl.bufferSubData( bufferType, 0, array );
15661  
15662			} else if ( updateRange.count === 0 ) {
15663  
15664				console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
15665  
15666			} else {
15667  
15668				gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
15669					array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
15670  
15671				updateRange.count = - 1; // reset range
15672  
15673			}
15674  
15675		}
15676  
15677		//
15678  
15679		function get( attribute ) {
15680  
15681			if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15682  
15683			return buffers.get( attribute );
15684  
15685		}
15686  
15687		function remove( attribute ) {
15688  
15689			if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15690  
15691			var data = buffers.get( attribute );
15692  
15693			if ( data ) {
15694  
15695				gl.deleteBuffer( data.buffer );
15696  
15697				buffers.delete( attribute );
15698  
15699			}
15700  
15701		}
15702  
15703		function update( attribute, bufferType ) {
15704  
15705			if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15706  
15707			var data = buffers.get( attribute );
15708  
15709			if ( data === undefined ) {
15710  
15711				buffers.set( attribute, createBuffer( attribute, bufferType ) );
15712  
15713			} else if ( data.version < attribute.version ) {
15714  
15715				updateBuffer( data.buffer, attribute, bufferType );
15716  
15717				data.version = attribute.version;
15718  
15719			}
15720  
15721		}
15722  
15723		return {
15724  
15725			get: get,
15726			remove: remove,
15727			update: update
15728  
15729		};
15730  
15731	}
15732  
15733	/**
15734	 * @author mrdoob / http://mrdoob.com/
15735	 * @author WestLangley / http://github.com/WestLangley
15736	 * @author bhouston / http://clara.io
15737	 */
15738  
15739	function Euler( x, y, z, order ) {
15740  
15741		this._x = x || 0;
15742		this._y = y || 0;
15743		this._z = z || 0;
15744		this._order = order || Euler.DefaultOrder;
15745  
15746	}
15747  
15748	Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
15749  
15750	Euler.DefaultOrder = 'XYZ';
15751  
15752	Object.defineProperties( Euler.prototype, {
15753  
vendor: 11,152 bytes, lines 15754-16403
15754		x: {
15755  
15756			get: function () {
15757  
15758				return this._x;
15759  
15760			},
15761  
15762			set: function ( value ) {
15763  
15764				this._x = value;
15765				this.onChangeCallback();
15766  
15767			}
15768  
15769		},
15770  
15771		y: {
15772  
15773			get: function () {
15774  
15775				return this._y;
15776  
15777			},
15778  
15779			set: function ( value ) {
15780  
15781				this._y = value;
15782				this.onChangeCallback();
15783  
15784			}
15785  
15786		},
15787  
15788		z: {
15789  
15790			get: function () {
15791  
15792				return this._z;
15793  
15794			},
15795  
15796			set: function ( value ) {
15797  
15798				this._z = value;
15799				this.onChangeCallback();
15800  
15801			}
15802  
15803		},
15804  
15805		order: {
15806  
15807			get: function () {
15808  
15809				return this._order;
15810  
15811			},
15812  
15813			set: function ( value ) {
15814  
15815				this._order = value;
15816				this.onChangeCallback();
15817  
15818			}
15819  
15820		}
15821  
15822	} );
15823  
15824	Object.assign( Euler.prototype, {
15825  
15826		isEuler: true,
15827  
15828		set: function ( x, y, z, order ) {
15829  
15830			this._x = x;
15831			this._y = y;
15832			this._z = z;
15833			this._order = order || this._order;
15834  
15835			this.onChangeCallback();
15836  
15837			return this;
15838  
15839		},
15840  
15841		clone: function () {
15842  
15843			return new this.constructor( this._x, this._y, this._z, this._order );
15844  
15845		},
15846  
15847		copy: function ( euler ) {
15848  
15849			this._x = euler._x;
15850			this._y = euler._y;
15851			this._z = euler._z;
15852			this._order = euler._order;
15853  
15854			this.onChangeCallback();
15855  
15856			return this;
15857  
15858		},
15859  
15860		setFromRotationMatrix: function ( m, order, update ) {
15861  
15862			var clamp = _Math.clamp;
15863  
15864			// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
15865  
15866			var te = m.elements;
15867			var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
15868			var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
15869			var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
15870  
15871			order = order || this._order;
15872  
15873			if ( order === 'XYZ' ) {
15874  
15875				this._y = Math.asin( clamp( m13, - 1, 1 ) );
15876  
15877				if ( Math.abs( m13 ) < 0.99999 ) {
15878  
15879					this._x = Math.atan2( - m23, m33 );
15880					this._z = Math.atan2( - m12, m11 );
15881  
15882				} else {
15883  
15884					this._x = Math.atan2( m32, m22 );
15885					this._z = 0;
15886  
15887				}
15888  
15889			} else if ( order === 'YXZ' ) {
15890  
15891				this._x = Math.asin( - clamp( m23, - 1, 1 ) );
15892  
15893				if ( Math.abs( m23 ) < 0.99999 ) {
15894  
15895					this._y = Math.atan2( m13, m33 );
15896					this._z = Math.atan2( m21, m22 );
15897  
15898				} else {
15899  
15900					this._y = Math.atan2( - m31, m11 );
15901					this._z = 0;
15902  
15903				}
15904  
15905			} else if ( order === 'ZXY' ) {
15906  
15907				this._x = Math.asin( clamp( m32, - 1, 1 ) );
15908  
15909				if ( Math.abs( m32 ) < 0.99999 ) {
15910  
15911					this._y = Math.atan2( - m31, m33 );
15912					this._z = Math.atan2( - m12, m22 );
15913  
15914				} else {
15915  
15916					this._y = 0;
15917					this._z = Math.atan2( m21, m11 );
15918  
15919				}
15920  
15921			} else if ( order === 'ZYX' ) {
15922  
15923				this._y = Math.asin( - clamp( m31, - 1, 1 ) );
15924  
15925				if ( Math.abs( m31 ) < 0.99999 ) {
15926  
15927					this._x = Math.atan2( m32, m33 );
15928					this._z = Math.atan2( m21, m11 );
15929  
15930				} else {
15931  
15932					this._x = 0;
15933					this._z = Math.atan2( - m12, m22 );
15934  
15935				}
15936  
15937			} else if ( order === 'YZX' ) {
15938  
15939				this._z = Math.asin( clamp( m21, - 1, 1 ) );
15940  
15941				if ( Math.abs( m21 ) < 0.99999 ) {
15942  
15943					this._x = Math.atan2( - m23, m22 );
15944					this._y = Math.atan2( - m31, m11 );
15945  
15946				} else {
15947  
15948					this._x = 0;
15949					this._y = Math.atan2( m13, m33 );
15950  
15951				}
15952  
15953			} else if ( order === 'XZY' ) {
15954  
15955				this._z = Math.asin( - clamp( m12, - 1, 1 ) );
15956  
15957				if ( Math.abs( m12 ) < 0.99999 ) {
15958  
15959					this._x = Math.atan2( m32, m22 );
15960					this._y = Math.atan2( m13, m11 );
15961  
15962				} else {
15963  
15964					this._x = Math.atan2( - m23, m33 );
15965					this._y = 0;
15966  
15967				}
15968  
15969			} else {
15970  
15971				console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
15972  
15973			}
15974  
15975			this._order = order;
15976  
15977			if ( update !== false ) this.onChangeCallback();
15978  
15979			return this;
15980  
15981		},
15982  
15983		setFromQuaternion: function () {
15984  
15985			var matrix = new Matrix4();
15986  
15987			return function setFromQuaternion( q, order, update ) {
15988  
15989				matrix.makeRotationFromQuaternion( q );
15990  
15991				return this.setFromRotationMatrix( matrix, order, update );
15992  
15993			};
15994  
15995		}(),
15996  
15997		setFromVector3: function ( v, order ) {
15998  
15999			return this.set( v.x, v.y, v.z, order || this._order );
16000  
16001		},
16002  
16003		reorder: function () {
16004  
16005			// WARNING: this discards revolution information -bhouston
16006  
16007			var q = new Quaternion();
16008  
16009			return function reorder( newOrder ) {
16010  
16011				q.setFromEuler( this );
16012  
16013				return this.setFromQuaternion( q, newOrder );
16014  
16015			};
16016  
16017		}(),
16018  
16019		equals: function ( euler ) {
16020  
16021			return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
16022  
16023		},
16024  
16025		fromArray: function ( array ) {
16026  
16027			this._x = array[ 0 ];
16028			this._y = array[ 1 ];
16029			this._z = array[ 2 ];
16030			if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
16031  
16032			this.onChangeCallback();
16033  
16034			return this;
16035  
16036		},
16037  
16038		toArray: function ( array, offset ) {
16039  
16040			if ( array === undefined ) array = [];
16041			if ( offset === undefined ) offset = 0;
16042  
16043			array[ offset ] = this._x;
16044			array[ offset + 1 ] = this._y;
16045			array[ offset + 2 ] = this._z;
16046			array[ offset + 3 ] = this._order;
16047  
16048			return array;
16049  
16050		},
16051  
16052		toVector3: function ( optionalResult ) {
16053  
16054			if ( optionalResult ) {
16055  
16056				return optionalResult.set( this._x, this._y, this._z );
16057  
16058			} else {
16059  
16060				return new Vector3( this._x, this._y, this._z );
16061  
16062			}
16063  
16064		},
16065  
16066		onChange: function ( callback ) {
16067  
16068			this.onChangeCallback = callback;
16069  
16070			return this;
16071  
16072		},
16073  
16074		onChangeCallback: function () {}
16075  
16076	} );
16077  
16078	/**
16079	 * @author mrdoob / http://mrdoob.com/
16080	 */
16081  
16082	function Layers() {
16083  
16084		this.mask = 1 | 0;
16085  
16086	}
16087  
16088	Object.assign( Layers.prototype, {
16089  
16090		set: function ( channel ) {
16091  
16092			this.mask = 1 << channel | 0;
16093  
16094		},
16095  
16096		enable: function ( channel ) {
16097  
16098			this.mask |= 1 << channel | 0;
16099  
16100		},
16101  
16102		toggle: function ( channel ) {
16103  
16104			this.mask ^= 1 << channel | 0;
16105  
16106		},
16107  
16108		disable: function ( channel ) {
16109  
16110			this.mask &= ~ ( 1 << channel | 0 );
16111  
16112		},
16113  
16114		test: function ( layers ) {
16115  
16116			return ( this.mask & layers.mask ) !== 0;
16117  
16118		}
16119  
16120	} );
16121  
16122	/**
16123	 * @author mrdoob / http://mrdoob.com/
16124	 * @author mikael emtinger / http://gomo.se/
16125	 * @author alteredq / http://alteredqualia.com/
16126	 * @author WestLangley / http://github.com/WestLangley
16127	 * @author elephantatwork / www.elephantatwork.ch
16128	 */
16129  
16130	var object3DId = 0;
16131  
16132	function Object3D() {
16133  
16134		Object.defineProperty( this, 'id', { value: object3DId ++ } );
16135  
16136		this.uuid = _Math.generateUUID();
16137  
16138		this.name = '';
16139		this.type = 'Object3D';
16140  
16141		this.parent = null;
16142		this.children = [];
16143  
16144		this.up = Object3D.DefaultUp.clone();
16145  
16146		var position = new Vector3();
16147		var rotation = new Euler();
16148		var quaternion = new Quaternion();
16149		var scale = new Vector3( 1, 1, 1 );
16150  
16151		function onRotationChange() {
16152  
16153			quaternion.setFromEuler( rotation, false );
16154  
16155		}
16156  
16157		function onQuaternionChange() {
16158  
16159			rotation.setFromQuaternion( quaternion, undefined, false );
16160  
16161		}
16162  
16163		rotation.onChange( onRotationChange );
16164		quaternion.onChange( onQuaternionChange );
16165  
16166		Object.defineProperties( this, {
16167			position: {
16168				enumerable: true,
16169				value: position
16170			},
16171			rotation: {
16172				enumerable: true,
16173				value: rotation
16174			},
16175			quaternion: {
16176				enumerable: true,
16177				value: quaternion
16178			},
16179			scale: {
16180				enumerable: true,
16181				value: scale
16182			},
16183			modelViewMatrix: {
16184				value: new Matrix4()
16185			},
16186			normalMatrix: {
16187				value: new Matrix3()
16188			}
16189		} );
16190  
16191		this.matrix = new Matrix4();
16192		this.matrixWorld = new Matrix4();
16193  
16194		this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
16195		this.matrixWorldNeedsUpdate = false;
16196  
16197		this.layers = new Layers();
16198		this.visible = true;
16199  
16200		this.castShadow = false;
16201		this.receiveShadow = false;
16202  
16203		this.frustumCulled = true;
16204		this.renderOrder = 0;
16205  
16206		this.userData = {};
16207  
16208	}
16209  
16210	Object3D.DefaultUp = new Vector3( 0, 1, 0 );
16211	Object3D.DefaultMatrixAutoUpdate = true;
16212  
16213	Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
16214  
16215		constructor: Object3D,
16216  
16217		isObject3D: true,
16218  
16219		onBeforeRender: function () {},
16220		onAfterRender: function () {},
16221  
16222		applyMatrix: function ( matrix ) {
16223  
16224			this.matrix.multiplyMatrices( matrix, this.matrix );
16225  
16226			this.matrix.decompose( this.position, this.quaternion, this.scale );
16227  
16228		},
16229  
16230		applyQuaternion: function ( q ) {
16231  
16232			this.quaternion.premultiply( q );
16233  
16234			return this;
16235  
16236		},
16237  
16238		setRotationFromAxisAngle: function ( axis, angle ) {
16239  
16240			// assumes axis is normalized
16241  
16242			this.quaternion.setFromAxisAngle( axis, angle );
16243  
16244		},
16245  
16246		setRotationFromEuler: function ( euler ) {
16247  
16248			this.quaternion.setFromEuler( euler, true );
16249  
16250		},
16251  
16252		setRotationFromMatrix: function ( m ) {
16253  
16254			// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
16255  
16256			this.quaternion.setFromRotationMatrix( m );
16257  
16258		},
16259  
16260		setRotationFromQuaternion: function ( q ) {
16261  
16262			// assumes q is normalized
16263  
16264			this.quaternion.copy( q );
16265  
16266		},
16267  
16268		rotateOnAxis: function () {
16269  
16270			// rotate object on axis in object space
16271			// axis is assumed to be normalized
16272  
16273			var q1 = new Quaternion();
16274  
16275			return function rotateOnAxis( axis, angle ) {
16276  
16277				q1.setFromAxisAngle( axis, angle );
16278  
16279				this.quaternion.multiply( q1 );
16280  
16281				return this;
16282  
16283			};
16284  
16285		}(),
16286  
16287		rotateOnWorldAxis: function () {
16288  
16289			// rotate object on axis in world space
16290			// axis is assumed to be normalized
16291			// method assumes no rotated parent
16292  
16293			var q1 = new Quaternion();
16294  
16295			return function rotateOnWorldAxis( axis, angle ) {
16296  
16297				q1.setFromAxisAngle( axis, angle );
16298  
16299				this.quaternion.premultiply( q1 );
16300  
16301				return this;
16302  
16303			};
16304  
16305		}(),
16306  
16307		rotateX: function () {
16308  
16309			var v1 = new Vector3( 1, 0, 0 );
16310  
16311			return function rotateX( angle ) {
16312  
16313				return this.rotateOnAxis( v1, angle );
16314  
16315			};
16316  
16317		}(),
16318  
16319		rotateY: function () {
16320  
16321			var v1 = new Vector3( 0, 1, 0 );
16322  
16323			return function rotateY( angle ) {
16324  
16325				return this.rotateOnAxis( v1, angle );
16326  
16327			};
16328  
16329		}(),
16330  
16331		rotateZ: function () {
16332  
16333			var v1 = new Vector3( 0, 0, 1 );
16334  
16335			return function rotateZ( angle ) {
16336  
16337				return this.rotateOnAxis( v1, angle );
16338  
16339			};
16340  
16341		}(),
16342  
16343		translateOnAxis: function () {
16344  
16345			// translate object by distance along axis in object space
16346			// axis is assumed to be normalized
16347  
16348			var v1 = new Vector3();
16349  
16350			return function translateOnAxis( axis, distance ) {
16351  
16352				v1.copy( axis ).applyQuaternion( this.quaternion );
16353  
16354				this.position.add( v1.multiplyScalar( distance ) );
16355  
16356				return this;
16357  
16358			};
16359  
16360		}(),
16361  
16362		translateX: function () {
16363  
16364			var v1 = new Vector3( 1, 0, 0 );
16365  
16366			return function translateX( distance ) {
16367  
16368				return this.translateOnAxis( v1, distance );
16369  
16370			};
16371  
16372		}(),
16373  
16374		translateY: function () {
16375  
16376			var v1 = new Vector3( 0, 1, 0 );
16377  
16378			return function translateY( distance ) {
16379  
16380				return this.translateOnAxis( v1, distance );
16381  
16382			};
16383  
16384		}(),
16385  
16386		translateZ: function () {
16387  
16388			var v1 = new Vector3( 0, 0, 1 );
16389  
16390			return function translateZ( distance ) {
16391  
16392				return this.translateOnAxis( v1, distance );
16393  
16394			};
16395  
16396		}(),
16397  
16398		localToWorld: function ( vector ) {
16399  
16400			return vector.applyMatrix4( this.matrixWorld );
16401  
16402		},
16403  
16404		worldToLocal: function () {
16405  
16406			var m1 = new Matrix4();
16407  
16408			return function worldToLocal( vector ) {
16409  
16410				return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
16411  
16412			};
16413  
16414		}(),
16415  
16416		lookAt: function () {
16417  
16418			// This method does not support objects with rotated and/or translated parent(s)
16419  
16420			var m1 = new Matrix4();
16421			var vector = new Vector3();
16422  
16423			return function lookAt( x, y, z ) {
16424  
16425				if ( x.isVector3 ) {
16426  
16427					vector.copy( x );
16428  
16429				} else {
16430  
16431					vector.set( x, y, z );
16432  
16433				}
16434  
16435				if ( this.isCamera ) {
16436  
16437					m1.lookAt( this.position, vector, this.up );
16438  
16439				} else {
16440  
16441					m1.lookAt( vector, this.position, this.up );
16442  
16443				}
16444  
16445				this.quaternion.setFromRotationMatrix( m1 );
16446  
16447			};
16448  
16449		}(),
16450  
16451		add: function ( object ) {
16452  
16453			if ( arguments.length > 1 ) {
16454  
16455				for ( var i = 0; i < arguments.length; i ++ ) {
16456  
16457					this.add( arguments[ i ] );
16458  
16459				}
16460  
16461				return this;
16462  
16463			}
16464  
16465			if ( object === this ) {
16466  
16467				console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
16468				return this;
16469  
16470			}
16471  
16472			if ( ( object && object.isObject3D ) ) {
16473  
16474				if ( object.parent !== null ) {
16475  
16476					object.parent.remove( object );
16477  
16478				}
16479  
16480				object.parent = this;
16481				object.dispatchEvent( { type: 'added' } );
16482  
16483				this.children.push( object );
16484  
16485			} else {
16486  
16487				console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
16488  
16489			}
16490  
16491			return this;
16492  
16493		},
16494  
16495		remove: function ( object ) {
16496  
16497			if ( arguments.length > 1 ) {
16498  
16499				for ( var i = 0; i < arguments.length; i ++ ) {
16500  
16501					this.remove( arguments[ i ] );
16502  
16503				}
16504  
16505				return this;
16506  
16507			}
16508  
16509			var index = this.children.indexOf( object );
16510  
16511			if ( index !== - 1 ) {
16512  
16513				object.parent = null;
16514  
16515				object.dispatchEvent( { type: 'removed' } );
16516  
16517				this.children.splice( index, 1 );
16518  
16519			}
16520  
16521			return this;
16522  
16523		},
16524  
16525		getObjectById: function ( id ) {
16526  
16527			return this.getObjectByProperty( 'id', id );
16528  
16529		},
16530  
16531		getObjectByName: function ( name ) {
16532  
16533			return this.getObjectByProperty( 'name', name );
16534  
16535		},
16536  
16537		getObjectByProperty: function ( name, value ) {
16538  
16539			if ( this[ name ] === value ) return this;
16540  
16541			for ( var i = 0, l = this.children.length; i < l; i ++ ) {
16542  
16543				var child = this.children[ i ];
16544				var object = child.getObjectByProperty( name, value );
16545  
16546				if ( object !== undefined ) {
16547  
16548					return object;
16549  
16550				}
16551  
16552			}
16553  
16554			return undefined;
16555  
16556		},
16557  
16558		getWorldPosition: function ( target ) {
16559  
16560			if ( target === undefined ) {
16561  
16562				console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
16563				target = new Vector3();
16564  
16565			}
16566  
16567			this.updateMatrixWorld( true );
16568  
16569			return target.setFromMatrixPosition( this.matrixWorld );
16570  
16571		},
16572  
16573		getWorldQuaternion: function () {
16574  
16575			var position = new Vector3();
16576			var scale = new Vector3();
16577  
16578			return function getWorldQuaternion( target ) {
16579  
16580				if ( target === undefined ) {
16581  
16582					console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
16583					target = new Quaternion();
16584  
16585				}
16586  
16587				this.updateMatrixWorld( true );
16588  
16589				this.matrixWorld.decompose( position, target, scale );
16590  
16591				return target;
16592  
16593			};
16594  
16595		}(),
16596  
16597		getWorldScale: function () {
16598  
16599			var position = new Vector3();
16600			var quaternion = new Quaternion();
16601  
16602			return function getWorldScale( target ) {
16603  
16604				if ( target === undefined ) {
16605  
16606					console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
16607					target = new Vector3();
16608  
16609				}
16610  
16611				this.updateMatrixWorld( true );
16612  
16613				this.matrixWorld.decompose( position, quaternion, target );
16614  
16615				return target;
16616  
16617			};
16618  
16619		}(),
16620  
16621		getWorldDirection: function () {
16622  
16623			var quaternion = new Quaternion();
16624  
16625			return function getWorldDirection( target ) {
16626  
16627				if ( target === undefined ) {
16628  
16629					console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
16630					target = new Vector3();
16631  
16632				}
16633  
16634				this.getWorldQuaternion( quaternion );
16635  
16636				return target.set( 0, 0, 1 ).applyQuaternion( quaternion );
16637  
16638			};
16639  
16640		}(),
16641  
16642		raycast: function () {},
16643  
16644		traverse: function ( callback ) {
16645  
16646			callback( this );
16647  
16648			var children = this.children;
16649  
16650			for ( var i = 0, l = children.length; i < l; i ++ ) {
16651  
16652				children[ i ].traverse( callback );
16653  
16654			}
16655  
16656		},
16657  
vendor: 6,804 bytes, lines 16658-16982
16658		traverseVisible: function ( callback ) {
16659  
16660			if ( this.visible === false ) return;
16661  
16662			callback( this );
16663  
16664			var children = this.children;
16665  
16666			for ( var i = 0, l = children.length; i < l; i ++ ) {
16667  
16668				children[ i ].traverseVisible( callback );
16669  
16670			}
16671  
16672		},
16673  
16674		traverseAncestors: function ( callback ) {
16675  
16676			var parent = this.parent;
16677  
16678			if ( parent !== null ) {
16679  
16680				callback( parent );
16681  
16682				parent.traverseAncestors( callback );
16683  
16684			}
16685  
16686		},
16687  
16688		updateMatrix: function () {
16689  
16690			this.matrix.compose( this.position, this.quaternion, this.scale );
16691  
16692			this.matrixWorldNeedsUpdate = true;
16693  
16694		},
16695  
16696		updateMatrixWorld: function ( force ) {
16697  
16698			if ( this.matrixAutoUpdate ) this.updateMatrix();
16699  
16700			if ( this.matrixWorldNeedsUpdate || force ) {
16701  
16702				if ( this.parent === null ) {
16703  
16704					this.matrixWorld.copy( this.matrix );
16705  
16706				} else {
16707  
16708					this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
16709  
16710				}
16711  
16712				this.matrixWorldNeedsUpdate = false;
16713  
16714				force = true;
16715  
16716			}
16717  
16718			// update children
16719  
16720			var children = this.children;
16721  
16722			for ( var i = 0, l = children.length; i < l; i ++ ) {
16723  
16724				children[ i ].updateMatrixWorld( force );
16725  
16726			}
16727  
16728		},
16729  
16730		toJSON: function ( meta ) {
16731  
16732			// meta is a string when called from JSON.stringify
16733			var isRootObject = ( meta === undefined || typeof meta === 'string' );
16734  
16735			var output = {};
16736  
16737			// meta is a hash used to collect geometries, materials.
16738			// not providing it implies that this is the root object
16739			// being serialized.
16740			if ( isRootObject ) {
16741  
16742				// initialize meta obj
16743				meta = {
16744					geometries: {},
16745					materials: {},
16746					textures: {},
16747					images: {},
16748					shapes: {}
16749				};
16750  
16751				output.metadata = {
16752					version: 4.5,
16753					type: 'Object',
16754					generator: 'Object3D.toJSON'
16755				};
16756  
16757			}
16758  
16759			// standard Object3D serialization
16760  
16761			var object = {};
16762  
16763			object.uuid = this.uuid;
16764			object.type = this.type;
16765  
16766			if ( this.name !== '' ) object.name = this.name;
16767			if ( this.castShadow === true ) object.castShadow = true;
16768			if ( this.receiveShadow === true ) object.receiveShadow = true;
16769			if ( this.visible === false ) object.visible = false;
16770			if ( this.frustumCulled === false ) object.frustumCulled = false;
16771			if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
16772			if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
16773  
16774			object.matrix = this.matrix.toArray();
16775  
16776			if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
16777  
16778			//
16779  
16780			function serialize( library, element ) {
16781  
16782				if ( library[ element.uuid ] === undefined ) {
16783  
16784					library[ element.uuid ] = element.toJSON( meta );
16785  
16786				}
16787  
16788				return element.uuid;
16789  
16790			}
16791  
16792			if ( this.geometry !== undefined ) {
16793  
16794				object.geometry = serialize( meta.geometries, this.geometry );
16795  
16796				var parameters = this.geometry.parameters;
16797  
16798				if ( parameters !== undefined && parameters.shapes !== undefined ) {
16799  
16800					var shapes = parameters.shapes;
16801  
16802					if ( Array.isArray( shapes ) ) {
16803  
16804						for ( var i = 0, l = shapes.length; i < l; i ++ ) {
16805  
16806							var shape = shapes[ i ];
16807  
16808							serialize( meta.shapes, shape );
16809  
16810						}
16811  
16812					} else {
16813  
16814						serialize( meta.shapes, shapes );
16815  
16816					}
16817  
16818				}
16819  
16820			}
16821  
16822			if ( this.material !== undefined ) {
16823  
16824				if ( Array.isArray( this.material ) ) {
16825  
16826					var uuids = [];
16827  
16828					for ( var i = 0, l = this.material.length; i < l; i ++ ) {
16829  
16830						uuids.push( serialize( meta.materials, this.material[ i ] ) );
16831  
16832					}
16833  
16834					object.material = uuids;
16835  
16836				} else {
16837  
16838					object.material = serialize( meta.materials, this.material );
16839  
16840				}
16841  
16842			}
16843  
16844			//
16845  
16846			if ( this.children.length > 0 ) {
16847  
16848				object.children = [];
16849  
16850				for ( var i = 0; i < this.children.length; i ++ ) {
16851  
16852					object.children.push( this.children[ i ].toJSON( meta ).object );
16853  
16854				}
16855  
16856			}
16857  
16858			if ( isRootObject ) {
16859  
16860				var geometries = extractFromCache( meta.geometries );
16861				var materials = extractFromCache( meta.materials );
16862				var textures = extractFromCache( meta.textures );
16863				var images = extractFromCache( meta.images );
16864				var shapes = extractFromCache( meta.shapes );
16865  
16866				if ( geometries.length > 0 ) output.geometries = geometries;
16867				if ( materials.length > 0 ) output.materials = materials;
16868				if ( textures.length > 0 ) output.textures = textures;
16869				if ( images.length > 0 ) output.images = images;
16870				if ( shapes.length > 0 ) output.shapes = shapes;
16871  
16872			}
16873  
16874			output.object = object;
16875  
16876			return output;
16877  
16878			// extract data from the cache hash
16879			// remove metadata on each item
16880			// and return as array
16881			function extractFromCache( cache ) {
16882  
16883				var values = [];
16884				for ( var key in cache ) {
16885  
16886					var data = cache[ key ];
16887					delete data.metadata;
16888					values.push( data );
16889  
16890				}
16891				return values;
16892  
16893			}
16894  
16895		},
16896  
16897		clone: function ( recursive ) {
16898  
16899			return new this.constructor().copy( this, recursive );
16900  
16901		},
16902  
16903		copy: function ( source, recursive ) {
16904  
16905			if ( recursive === undefined ) recursive = true;
16906  
16907			this.name = source.name;
16908  
16909			this.up.copy( source.up );
16910  
16911			this.position.copy( source.position );
16912			this.quaternion.copy( source.quaternion );
16913			this.scale.copy( source.scale );
16914  
16915			this.matrix.copy( source.matrix );
16916			this.matrixWorld.copy( source.matrixWorld );
16917  
16918			this.matrixAutoUpdate = source.matrixAutoUpdate;
16919			this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
16920  
16921			this.layers.mask = source.layers.mask;
16922			this.visible = source.visible;
16923  
16924			this.castShadow = source.castShadow;
16925			this.receiveShadow = source.receiveShadow;
16926  
16927			this.frustumCulled = source.frustumCulled;
16928			this.renderOrder = source.renderOrder;
16929  
16930			this.userData = JSON.parse( JSON.stringify( source.userData ) );
16931  
16932			if ( recursive === true ) {
16933  
16934				for ( var i = 0; i < source.children.length; i ++ ) {
16935  
16936					var child = source.children[ i ];
16937					this.add( child.clone() );
16938  
16939				}
16940  
16941			}
16942  
16943			return this;
16944  
16945		}
16946  
16947	} );
16948  
16949	/**
16950	 * @author mrdoob / http://mrdoob.com/
16951	 * @author mikael emtinger / http://gomo.se/
16952	 * @author WestLangley / http://github.com/WestLangley
16953	*/
16954  
16955	function Camera() {
16956  
16957		Object3D.call( this );
16958  
16959		this.type = 'Camera';
16960  
16961		this.matrixWorldInverse = new Matrix4();
16962		this.projectionMatrix = new Matrix4();
16963  
16964	}
16965  
16966	Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
16967  
16968		constructor: Camera,
16969  
16970		isCamera: true,
16971  
16972		copy: function ( source, recursive ) {
16973  
16974			Object3D.prototype.copy.call( this, source, recursive );
16975  
16976			this.matrixWorldInverse.copy( source.matrixWorldInverse );
16977			this.projectionMatrix.copy( source.projectionMatrix );
16978  
16979			return this;
16980  
16981		},
16982  
16983		getWorldDirection: function () {
16984  
16985			var quaternion = new Quaternion();
16986  
16987			return function getWorldDirection( target ) {
16988  
16989				if ( target === undefined ) {
16990  
16991					console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
16992					target = new Vector3();
16993  
16994				}
16995  
16996				this.getWorldQuaternion( quaternion );
16997  
16998				return target.set( 0, 0, - 1 ).applyQuaternion( quaternion );
16999  
17000			};
17001  
17002		}(),
17003  
17004		updateMatrixWorld: function ( force ) {
17005  
17006			Object3D.prototype.updateMatrixWorld.call( this, force );
17007  
17008			this.matrixWorldInverse.getInverse( this.matrixWorld );
17009  
17010		},
17011  
17012		clone: function () {
17013  
17014			return new this.constructor().copy( this );
17015  
17016		}
17017  
17018	} );
17019  
17020	/**
17021	 * @author alteredq / http://alteredqualia.com/
17022	 * @author arose / http://github.com/arose
17023	 */
17024  
17025	function OrthographicCamera( left, right, top, bottom, near, far ) {
17026  
17027		Camera.call( this );
17028  
17029		this.type = 'OrthographicCamera';
17030  
17031		this.zoom = 1;
17032		this.view = null;
17033  
17034		this.left = left;
17035		this.right = right;
17036		this.top = top;
17037		this.bottom = bottom;
17038  
17039		this.near = ( near !== undefined ) ? near : 0.1;
17040		this.far = ( far !== undefined ) ? far : 2000;
17041  
17042		this.updateProjectionMatrix();
17043  
17044	}
17045  
17046	OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
17047  
17048		constructor: OrthographicCamera,
17049  
17050		isOrthographicCamera: true,
17051  
17052		copy: function ( source, recursive ) {
17053  
17054			Camera.prototype.copy.call( this, source, recursive );
17055  
17056			this.left = source.left;
17057			this.right = source.right;
17058			this.top = source.top;
17059			this.bottom = source.bottom;
17060			this.near = source.near;
17061			this.far = source.far;
17062  
17063			this.zoom = source.zoom;
17064			this.view = source.view === null ? null : Object.assign( {}, source.view );
17065  
17066			return this;
17067  
17068		},
17069  
17070		setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
17071  
17072			if ( this.view === null ) {
17073  
17074				this.view = {
17075					enabled: true,
17076					fullWidth: 1,
17077					fullHeight: 1,
17078					offsetX: 0,
17079					offsetY: 0,
17080					width: 1,
17081					height: 1
17082				};
17083  
17084			}
17085  
17086			this.view.enabled = true;
17087			this.view.fullWidth = fullWidth;
17088			this.view.fullHeight = fullHeight;
17089			this.view.offsetX = x;
17090			this.view.offsetY = y;
17091			this.view.width = width;
17092			this.view.height = height;
17093  
17094			this.updateProjectionMatrix();
17095  
17096		},
17097  
17098		clearViewOffset: function () {
17099  
17100			if ( this.view !== null ) {
17101  
17102				this.view.enabled = false;
17103  
17104			}
17105  
17106			this.updateProjectionMatrix();
17107  
17108		},
17109  
17110		updateProjectionMatrix: function () {
17111  
17112			var dx = ( this.right - this.left ) / ( 2 * this.zoom );
17113			var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
17114			var cx = ( this.right + this.left ) / 2;
17115			var cy = ( this.top + this.bottom ) / 2;
17116  
17117			var left = cx - dx;
17118			var right = cx + dx;
17119			var top = cy + dy;
17120			var bottom = cy - dy;
17121  
17122			if ( this.view !== null && this.view.enabled ) {
17123  
17124				var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
17125				var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
17126				var scaleW = ( this.right - this.left ) / this.view.width;
17127				var scaleH = ( this.top - this.bottom ) / this.view.height;
17128  
17129				left += scaleW * ( this.view.offsetX / zoomW );
17130				right = left + scaleW * ( this.view.width / zoomW );
17131				top -= scaleH * ( this.view.offsetY / zoomH );
17132				bottom = top - scaleH * ( this.view.height / zoomH );
17133  
17134			}
17135  
17136			this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
17137  
17138		},
17139  
17140		toJSON: function ( meta ) {
17141  
17142			var data = Object3D.prototype.toJSON.call( this, meta );
17143  
17144			data.object.zoom = this.zoom;
17145			data.object.left = this.left;
17146			data.object.right = this.right;
17147			data.object.top = this.top;
17148			data.object.bottom = this.bottom;
17149			data.object.near = this.near;
17150			data.object.far = this.far;
17151  
17152			if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
17153  
17154			return data;
17155  
17156		}
17157  
17158	} );
17159  
17160	/**
17161	 * @author mrdoob / http://mrdoob.com/
17162	 * @author alteredq / http://alteredqualia.com/
17163	 */
17164  
17165	function Face3( a, b, c, normal, color, materialIndex ) {
17166  
17167		this.a = a;
17168		this.b = b;
17169		this.c = c;
17170  
17171		this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
17172		this.vertexNormals = Array.isArray( normal ) ? normal : [];
17173  
17174		this.color = ( color && color.isColor ) ? color : new Color();
17175		this.vertexColors = Array.isArray( color ) ? color : [];
17176  
17177		this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
17178  
17179	}
17180  
17181	Object.assign( Face3.prototype, {
17182  
17183		clone: function () {
17184  
17185			return new this.constructor().copy( this );
17186  
17187		},
17188  
17189		copy: function ( source ) {
17190  
17191			this.a = source.a;
17192			this.b = source.b;
17193			this.c = source.c;
17194  
17195			this.normal.copy( source.normal );
17196			this.color.copy( source.color );
17197  
17198			this.materialIndex = source.materialIndex;
17199  
17200			for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
17201  
17202				this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
17203  
17204			}
17205  
17206			for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
17207  
17208				this.vertexColors[ i ] = source.vertexColors[ i ].clone();
17209  
17210			}
17211  
17212			return this;
17213  
17214		}
17215  
17216	} );
17217  
17218	/**
17219	 * @author mrdoob / http://mrdoob.com/
17220	 * @author kile / http://kile.stravaganza.org/
17221	 * @author alteredq / http://alteredqualia.com/
17222	 * @author mikael emtinger / http://gomo.se/
17223	 * @author zz85 / http://www.lab4games.net/zz85/blog
17224	 * @author bhouston / http://clara.io
17225	 */
17226  
17227	var geometryId = 0; // Geometry uses even numbers as Id
17228  
17229	function Geometry() {
17230  
17231		Object.defineProperty( this, 'id', { value: geometryId += 2 } );
17232  
17233		this.uuid = _Math.generateUUID();
17234  
17235		this.name = '';
17236		this.type = 'Geometry';
17237  
17238		this.vertices = [];
17239		this.colors = [];
17240		this.faces = [];
17241		this.faceVertexUvs = [[]];
17242  
17243		this.morphTargets = [];
17244		this.morphNormals = [];
17245  
17246		this.skinWeights = [];
17247		this.skinIndices = [];
17248  
17249		this.lineDistances = [];
17250  
17251		this.boundingBox = null;
17252		this.boundingSphere = null;
17253  
17254		// update flags
17255  
17256		this.elementsNeedUpdate = false;
17257		this.verticesNeedUpdate = false;
17258		this.uvsNeedUpdate = false;
17259		this.normalsNeedUpdate = false;
17260		this.colorsNeedUpdate = false;
17261		this.lineDistancesNeedUpdate = false;
17262		this.groupsNeedUpdate = false;
17263  
17264	}
17265  
17266	Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
17267  
17268		constructor: Geometry,
17269  
17270		isGeometry: true,
17271  
17272		applyMatrix: function ( matrix ) {
17273  
17274			var normalMatrix = new Matrix3().getNormalMatrix( matrix );
17275  
17276			for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
17277  
17278				var vertex = this.vertices[ i ];
17279				vertex.applyMatrix4( matrix );
17280  
17281			}
17282  
17283			for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
17284  
17285				var face = this.faces[ i ];
17286				face.normal.applyMatrix3( normalMatrix ).normalize();
17287  
17288				for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
17289  
17290					face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
17291  
17292				}
17293  
17294			}
17295  
17296			if ( this.boundingBox !== null ) {
17297  
17298				this.computeBoundingBox();
17299  
17300			}
17301  
17302			if ( this.boundingSphere !== null ) {
17303  
17304				this.computeBoundingSphere();
17305  
17306			}
17307  
17308			this.verticesNeedUpdate = true;
17309			this.normalsNeedUpdate = true;
17310  
17311			return this;
17312  
17313		},
17314  
17315		rotateX: function () {
17316  
17317			// rotate geometry around world x-axis
17318  
17319			var m1 = new Matrix4();
17320  
17321			return function rotateX( angle ) {
17322  
17323				m1.makeRotationX( angle );
17324  
17325				this.applyMatrix( m1 );
17326  
17327				return this;
17328  
17329			};
17330  
17331		}(),
17332  
17333		rotateY: function () {
17334  
17335			// rotate geometry around world y-axis
17336  
17337			var m1 = new Matrix4();
17338  
17339			return function rotateY( angle ) {
17340  
17341				m1.makeRotationY( angle );
17342  
17343				this.applyMatrix( m1 );
17344  
17345				return this;
17346  
17347			};
17348  
17349		}(),
17350  
17351		rotateZ: function () {
17352  
17353			// rotate geometry around world z-axis
17354  
17355			var m1 = new Matrix4();
17356  
17357			return function rotateZ( angle ) {
17358  
17359				m1.makeRotationZ( angle );
17360  
17361				this.applyMatrix( m1 );
17362  
17363				return this;
17364  
17365			};
17366  
17367		}(),
17368  
17369		translate: function () {
17370  
17371			// translate geometry
17372  
17373			var m1 = new Matrix4();
17374  
17375			return function translate( x, y, z ) {
17376  
17377				m1.makeTranslation( x, y, z );
17378  
17379				this.applyMatrix( m1 );
17380  
17381				return this;
17382  
17383			};
17384  
17385		}(),
17386  
17387		scale: function () {
17388  
17389			// scale geometry
17390  
17391			var m1 = new Matrix4();
17392  
17393			return function scale( x, y, z ) {
17394  
17395				m1.makeScale( x, y, z );
17396  
17397				this.applyMatrix( m1 );
17398  
17399				return this;
17400  
17401			};
17402  
17403		}(),
17404  
17405		lookAt: function () {
17406  
17407			var obj = new Object3D();
17408  
17409			return function lookAt( vector ) {
17410  
17411				obj.lookAt( vector );
17412  
17413				obj.updateMatrix();
17414  
17415				this.applyMatrix( obj.matrix );
17416  
17417			};
17418  
17419		}(),
17420  
17421		fromBufferGeometry: function ( geometry ) {
17422  
17423			var scope = this;
17424  
17425			var indices = geometry.index !== null ? geometry.index.array : undefined;
17426			var attributes = geometry.attributes;
17427  
17428			var positions = attributes.position.array;
17429			var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
17430			var colors = attributes.color !== undefined ? attributes.color.array : undefined;
17431			var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
17432			var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
17433  
17434			if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
17435  
17436			var tempNormals = [];
17437			var tempUVs = [];
17438			var tempUVs2 = [];
17439  
17440			for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
17441  
17442				scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
17443  
17444				if ( normals !== undefined ) {
17445  
17446					tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
17447  
17448				}
17449  
17450				if ( colors !== undefined ) {
17451  
17452					scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
17453  
17454				}
17455  
17456				if ( uvs !== undefined ) {
17457  
17458					tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) );
17459  
17460				}
17461  
17462				if ( uvs2 !== undefined ) {
17463  
17464					tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
17465  
17466				}
17467  
17468			}
17469  
17470			function addFace( a, b, c, materialIndex ) {
17471  
17472				var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].
vendor: 54,468 bytes, lines 17472-20120
17472clone(), tempNormals[ c ].clone() ] : [];
17473				var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
17474  
17475				var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
17476  
17477				scope.faces.push( face );
17478  
17479				if ( uvs !== undefined ) {
17480  
17481					scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
17482  
17483				}
17484  
17485				if ( uvs2 !== undefined ) {
17486  
17487					scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
17488  
17489				}
17490  
17491			}
17492  
17493			var groups = geometry.groups;
17494  
17495			if ( groups.length > 0 ) {
17496  
17497				for ( var i = 0; i < groups.length; i ++ ) {
17498  
17499					var group = groups[ i ];
17500  
17501					var start = group.start;
17502					var count = group.count;
17503  
17504					for ( var j = start, jl = start + count; j < jl; j += 3 ) {
17505  
17506						if ( indices !== undefined ) {
17507  
17508							addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
17509  
17510						} else {
17511  
17512							addFace( j, j + 1, j + 2, group.materialIndex );
17513  
17514						}
17515  
17516					}
17517  
17518				}
17519  
17520			} else {
17521  
17522				if ( indices !== undefined ) {
17523  
17524					for ( var i = 0; i < indices.length; i += 3 ) {
17525  
17526						addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
17527  
17528					}
17529  
17530				} else {
17531  
17532					for ( var i = 0; i < positions.length / 3; i += 3 ) {
17533  
17534						addFace( i, i + 1, i + 2 );
17535  
17536					}
17537  
17538				}
17539  
17540			}
17541  
17542			this.computeFaceNormals();
17543  
17544			if ( geometry.boundingBox !== null ) {
17545  
17546				this.boundingBox = geometry.boundingBox.clone();
17547  
17548			}
17549  
17550			if ( geometry.boundingSphere !== null ) {
17551  
17552				this.boundingSphere = geometry.boundingSphere.clone();
17553  
17554			}
17555  
17556			return this;
17557  
17558		},
17559  
17560		center: function () {
17561  
17562			var offset = new Vector3();
17563  
17564			return function center() {
17565  
17566				this.computeBoundingBox();
17567  
17568				this.boundingBox.getCenter( offset ).negate();
17569  
17570				this.translate( offset.x, offset.y, offset.z );
17571  
17572				return this;
17573  
17574			};
17575  
17576		}(),
17577  
17578		normalize: function () {
17579  
17580			this.computeBoundingSphere();
17581  
17582			var center = this.boundingSphere.center;
17583			var radius = this.boundingSphere.radius;
17584  
17585			var s = radius === 0 ? 1 : 1.0 / radius;
17586  
17587			var matrix = new Matrix4();
17588			matrix.set(
17589				s, 0, 0, - s * center.x,
17590				0, s, 0, - s * center.y,
17591				0, 0, s, - s * center.z,
17592				0, 0, 0, 1
17593			);
17594  
17595			this.applyMatrix( matrix );
17596  
17597			return this;
17598  
17599		},
17600  
17601		computeFaceNormals: function () {
17602  
17603			var cb = new Vector3(), ab = new Vector3();
17604  
17605			for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
17606  
17607				var face = this.faces[ f ];
17608  
17609				var vA = this.vertices[ face.a ];
17610				var vB = this.vertices[ face.b ];
17611				var vC = this.vertices[ face.c ];
17612  
17613				cb.subVectors( vC, vB );
17614				ab.subVectors( vA, vB );
17615				cb.cross( ab );
17616  
17617				cb.normalize();
17618  
17619				face.normal.copy( cb );
17620  
17621			}
17622  
17623		},
17624  
17625		computeVertexNormals: function ( areaWeighted ) {
17626  
17627			if ( areaWeighted === undefined ) areaWeighted = true;
17628  
17629			var v, vl, f, fl, face, vertices;
17630  
17631			vertices = new Array( this.vertices.length );
17632  
17633			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
17634  
17635				vertices[ v ] = new Vector3();
17636  
17637			}
17638  
17639			if ( areaWeighted ) {
17640  
17641				// vertex normals weighted by triangle areas
17642				// http://www.iquilezles.org/www/articles/normals/normals.htm
17643  
17644				var vA, vB, vC;
17645				var cb = new Vector3(), ab = new Vector3();
17646  
17647				for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17648  
17649					face = this.faces[ f ];
17650  
17651					vA = this.vertices[ face.a ];
17652					vB = this.vertices[ face.b ];
17653					vC = this.vertices[ face.c ];
17654  
17655					cb.subVectors( vC, vB );
17656					ab.subVectors( vA, vB );
17657					cb.cross( ab );
17658  
17659					vertices[ face.a ].add( cb );
17660					vertices[ face.b ].add( cb );
17661					vertices[ face.c ].add( cb );
17662  
17663				}
17664  
17665			} else {
17666  
17667				this.computeFaceNormals();
17668  
17669				for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17670  
17671					face = this.faces[ f ];
17672  
17673					vertices[ face.a ].add( face.normal );
17674					vertices[ face.b ].add( face.normal );
17675					vertices[ face.c ].add( face.normal );
17676  
17677				}
17678  
17679			}
17680  
17681			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
17682  
17683				vertices[ v ].normalize();
17684  
17685			}
17686  
17687			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17688  
17689				face = this.faces[ f ];
17690  
17691				var vertexNormals = face.vertexNormals;
17692  
17693				if ( vertexNormals.length === 3 ) {
17694  
17695					vertexNormals[ 0 ].copy( vertices[ face.a ] );
17696					vertexNormals[ 1 ].copy( vertices[ face.b ] );
17697					vertexNormals[ 2 ].copy( vertices[ face.c ] );
17698  
17699				} else {
17700  
17701					vertexNormals[ 0 ] = vertices[ face.a ].clone();
17702					vertexNormals[ 1 ] = vertices[ face.b ].clone();
17703					vertexNormals[ 2 ] = vertices[ face.c ].clone();
17704  
17705				}
17706  
17707			}
17708  
17709			if ( this.faces.length > 0 ) {
17710  
17711				this.normalsNeedUpdate = true;
17712  
17713			}
17714  
17715		},
17716  
17717		computeFlatVertexNormals: function () {
17718  
17719			var f, fl, face;
17720  
17721			this.computeFaceNormals();
17722  
17723			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17724  
17725				face = this.faces[ f ];
17726  
17727				var vertexNormals = face.vertexNormals;
17728  
17729				if ( vertexNormals.length === 3 ) {
17730  
17731					vertexNormals[ 0 ].copy( face.normal );
17732					vertexNormals[ 1 ].copy( face.normal );
17733					vertexNormals[ 2 ].copy( face.normal );
17734  
17735				} else {
17736  
17737					vertexNormals[ 0 ] = face.normal.clone();
17738					vertexNormals[ 1 ] = face.normal.clone();
17739					vertexNormals[ 2 ] = face.normal.clone();
17740  
17741				}
17742  
17743			}
17744  
17745			if ( this.faces.length > 0 ) {
17746  
17747				this.normalsNeedUpdate = true;
17748  
17749			}
17750  
17751		},
17752  
17753		computeMorphNormals: function () {
17754  
17755			var i, il, f, fl, face;
17756  
17757			// save original normals
17758			// - create temp variables on first access
17759			//   otherwise just copy (for faster repeated calls)
17760  
17761			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17762  
17763				face = this.faces[ f ];
17764  
17765				if ( ! face.__originalFaceNormal ) {
17766  
17767					face.__originalFaceNormal = face.normal.clone();
17768  
17769				} else {
17770  
17771					face.__originalFaceNormal.copy( face.normal );
17772  
17773				}
17774  
17775				if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
17776  
17777				for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
17778  
17779					if ( ! face.__originalVertexNormals[ i ] ) {
17780  
17781						face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
17782  
17783					} else {
17784  
17785						face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
17786  
17787					}
17788  
17789				}
17790  
17791			}
17792  
17793			// use temp geometry to compute face and vertex normals for each morph
17794  
17795			var tmpGeo = new Geometry();
17796			tmpGeo.faces = this.faces;
17797  
17798			for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
17799  
17800				// create on first access
17801  
17802				if ( ! this.morphNormals[ i ] ) {
17803  
17804					this.morphNormals[ i ] = {};
17805					this.morphNormals[ i ].faceNormals = [];
17806					this.morphNormals[ i ].vertexNormals = [];
17807  
17808					var dstNormalsFace = this.morphNormals[ i ].faceNormals;
17809					var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
17810  
17811					var faceNormal, vertexNormals;
17812  
17813					for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17814  
17815						faceNormal = new Vector3();
17816						vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
17817  
17818						dstNormalsFace.push( faceNormal );
17819						dstNormalsVertex.push( vertexNormals );
17820  
17821					}
17822  
17823				}
17824  
17825				var morphNormals = this.morphNormals[ i ];
17826  
17827				// set vertices to morph target
17828  
17829				tmpGeo.vertices = this.morphTargets[ i ].vertices;
17830  
17831				// compute morph normals
17832  
17833				tmpGeo.computeFaceNormals();
17834				tmpGeo.computeVertexNormals();
17835  
17836				// store morph normals
17837  
17838				var faceNormal, vertexNormals;
17839  
17840				for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17841  
17842					face = this.faces[ f ];
17843  
17844					faceNormal = morphNormals.faceNormals[ f ];
17845					vertexNormals = morphNormals.vertexNormals[ f ];
17846  
17847					faceNormal.copy( face.normal );
17848  
17849					vertexNormals.a.copy( face.vertexNormals[ 0 ] );
17850					vertexNormals.b.copy( face.vertexNormals[ 1 ] );
17851					vertexNormals.c.copy( face.vertexNormals[ 2 ] );
17852  
17853				}
17854  
17855			}
17856  
17857			// restore original normals
17858  
17859			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
17860  
17861				face = this.faces[ f ];
17862  
17863				face.normal = face.__originalFaceNormal;
17864				face.vertexNormals = face.__originalVertexNormals;
17865  
17866			}
17867  
17868		},
17869  
17870		computeBoundingBox: function () {
17871  
17872			if ( this.boundingBox === null ) {
17873  
17874				this.boundingBox = new Box3();
17875  
17876			}
17877  
17878			this.boundingBox.setFromPoints( this.vertices );
17879  
17880		},
17881  
17882		computeBoundingSphere: function () {
17883  
17884			if ( this.boundingSphere === null ) {
17885  
17886				this.boundingSphere = new Sphere();
17887  
17888			}
17889  
17890			this.boundingSphere.setFromPoints( this.vertices );
17891  
17892		},
17893  
17894		merge: function ( geometry, matrix, materialIndexOffset ) {
17895  
17896			if ( ! ( geometry && geometry.isGeometry ) ) {
17897  
17898				console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
17899				return;
17900  
17901			}
17902  
17903			var normalMatrix,
17904				vertexOffset = this.vertices.length,
17905				vertices1 = this.vertices,
17906				vertices2 = geometry.vertices,
17907				faces1 = this.faces,
17908				faces2 = geometry.faces,
17909				uvs1 = this.faceVertexUvs[ 0 ],
17910				uvs2 = geometry.faceVertexUvs[ 0 ],
17911				colors1 = this.colors,
17912				colors2 = geometry.colors;
17913  
17914			if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
17915  
17916			if ( matrix !== undefined ) {
17917  
17918				normalMatrix = new Matrix3().getNormalMatrix( matrix );
17919  
17920			}
17921  
17922			// vertices
17923  
17924			for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
17925  
17926				var vertex = vertices2[ i ];
17927  
17928				var vertexCopy = vertex.clone();
17929  
17930				if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
17931  
17932				vertices1.push( vertexCopy );
17933  
17934			}
17935  
17936			// colors
17937  
17938			for ( var i = 0, il = colors2.length; i < il; i ++ ) {
17939  
17940				colors1.push( colors2[ i ].clone() );
17941  
17942			}
17943  
17944			// faces
17945  
17946			for ( i = 0, il = faces2.length; i < il; i ++ ) {
17947  
17948				var face = faces2[ i ], faceCopy, normal, color,
17949					faceVertexNormals = face.vertexNormals,
17950					faceVertexColors = face.vertexColors;
17951  
17952				faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
17953				faceCopy.normal.copy( face.normal );
17954  
17955				if ( normalMatrix !== undefined ) {
17956  
17957					faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
17958  
17959				}
17960  
17961				for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
17962  
17963					normal = faceVertexNormals[ j ].clone();
17964  
17965					if ( normalMatrix !== undefined ) {
17966  
17967						normal.applyMatrix3( normalMatrix ).normalize();
17968  
17969					}
17970  
17971					faceCopy.vertexNormals.push( normal );
17972  
17973				}
17974  
17975				faceCopy.color.copy( face.color );
17976  
17977				for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
17978  
17979					color = faceVertexColors[ j ];
17980					faceCopy.vertexColors.push( color.clone() );
17981  
17982				}
17983  
17984				faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
17985  
17986				faces1.push( faceCopy );
17987  
17988			}
17989  
17990			// uvs
17991  
17992			for ( i = 0, il = uvs2.length; i < il; i ++ ) {
17993  
17994				var uv = uvs2[ i ], uvCopy = [];
17995  
17996				if ( uv === undefined ) {
17997  
17998					continue;
17999  
18000				}
18001  
18002				for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
18003  
18004					uvCopy.push( uv[ j ].clone() );
18005  
18006				}
18007  
18008				uvs1.push( uvCopy );
18009  
18010			}
18011  
18012		},
18013  
18014		mergeMesh: function ( mesh ) {
18015  
18016			if ( ! ( mesh && mesh.isMesh ) ) {
18017  
18018				console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
18019				return;
18020  
18021			}
18022  
18023			if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
18024  
18025			this.merge( mesh.geometry, mesh.matrix );
18026  
18027		},
18028  
18029		/*
18030		 * Checks for duplicate vertices with hashmap.
18031		 * Duplicated vertices are removed
18032		 * and faces' vertices are updated.
18033		 */
18034  
18035		mergeVertices: function () {
18036  
18037			var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
18038			var unique = [], changes = [];
18039  
18040			var v, key;
18041			var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
18042			var precision = Math.pow( 10, precisionPoints );
18043			var i, il, face;
18044			var indices, j, jl;
18045  
18046			for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
18047  
18048				v = this.vertices[ i ];
18049				key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
18050  
18051				if ( verticesMap[ key ] === undefined ) {
18052  
18053					verticesMap[ key ] = i;
18054					unique.push( this.vertices[ i ] );
18055					changes[ i ] = unique.length - 1;
18056  
18057				} else {
18058  
18059					//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
18060					changes[ i ] = changes[ verticesMap[ key ] ];
18061  
18062				}
18063  
18064			}
18065  
18066  
18067			// if faces are completely degenerate after merging vertices, we
18068			// have to remove them from the geometry.
18069			var faceIndicesToRemove = [];
18070  
18071			for ( i = 0, il = this.faces.length; i < il; i ++ ) {
18072  
18073				face = this.faces[ i ];
18074  
18075				face.a = changes[ face.a ];
18076				face.b = changes[ face.b ];
18077				face.c = changes[ face.c ];
18078  
18079				indices = [ face.a, face.b, face.c ];
18080  
18081				// if any duplicate vertices are found in a Face3
18082				// we have to remove the face as nothing can be saved
18083				for ( var n = 0; n < 3; n ++ ) {
18084  
18085					if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
18086  
18087						faceIndicesToRemove.push( i );
18088						break;
18089  
18090					}
18091  
18092				}
18093  
18094			}
18095  
18096			for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
18097  
18098				var idx = faceIndicesToRemove[ i ];
18099  
18100				this.faces.splice( idx, 1 );
18101  
18102				for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
18103  
18104					this.faceVertexUvs[ j ].splice( idx, 1 );
18105  
18106				}
18107  
18108			}
18109  
18110			// Use unique set of vertices
18111  
18112			var diff = this.vertices.length - unique.length;
18113			this.vertices = unique;
18114			return diff;
18115  
18116		},
18117  
18118		setFromPoints: function ( points ) {
18119  
18120			this.vertices = [];
18121  
18122			for ( var i = 0, l = points.length; i < l; i ++ ) {
18123  
18124				var point = points[ i ];
18125				this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
18126  
18127			}
18128  
18129			return this;
18130  
18131		},
18132  
18133		sortFacesByMaterialIndex: function () {
18134  
18135			var faces = this.faces;
18136			var length = faces.length;
18137  
18138			// tag faces
18139  
18140			for ( var i = 0; i < length; i ++ ) {
18141  
18142				faces[ i ]._id = i;
18143  
18144			}
18145  
18146			// sort faces
18147  
18148			function materialIndexSort( a, b ) {
18149  
18150				return a.materialIndex - b.materialIndex;
18151  
18152			}
18153  
18154			faces.sort( materialIndexSort );
18155  
18156			// sort uvs
18157  
18158			var uvs1 = this.faceVertexUvs[ 0 ];
18159			var uvs2 = this.faceVertexUvs[ 1 ];
18160  
18161			var newUvs1, newUvs2;
18162  
18163			if ( uvs1 && uvs1.length === length ) newUvs1 = [];
18164			if ( uvs2 && uvs2.length === length ) newUvs2 = [];
18165  
18166			for ( var i = 0; i < length; i ++ ) {
18167  
18168				var id = faces[ i ]._id;
18169  
18170				if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
18171				if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
18172  
18173			}
18174  
18175			if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
18176			if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
18177  
18178		},
18179  
18180		toJSON: function () {
18181  
18182			var data = {
18183				metadata: {
18184					version: 4.5,
18185					type: 'Geometry',
18186					generator: 'Geometry.toJSON'
18187				}
18188			};
18189  
18190			// standard Geometry serialization
18191  
18192			data.uuid = this.uuid;
18193			data.type = this.type;
18194			if ( this.name !== '' ) data.name = this.name;
18195  
18196			if ( this.parameters !== undefined ) {
18197  
18198				var parameters = this.parameters;
18199  
18200				for ( var key in parameters ) {
18201  
18202					if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
18203  
18204				}
18205  
18206				return data;
18207  
18208			}
18209  
18210			var vertices = [];
18211  
18212			for ( var i = 0; i < this.vertices.length; i ++ ) {
18213  
18214				var vertex = this.vertices[ i ];
18215				vertices.push( vertex.x, vertex.y, vertex.z );
18216  
18217			}
18218  
18219			var faces = [];
18220			var normals = [];
18221			var normalsHash = {};
18222			var colors = [];
18223			var colorsHash = {};
18224			var uvs = [];
18225			var uvsHash = {};
18226  
18227			for ( var i = 0; i < this.faces.length; i ++ ) {
18228  
18229				var face = this.faces[ i ];
18230  
18231				var hasMaterial = true;
18232				var hasFaceUv = false; // deprecated
18233				var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
18234				var hasFaceNormal = face.normal.length() > 0;
18235				var hasFaceVertexNormal = face.vertexNormals.length > 0;
18236				var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
18237				var hasFaceVertexColor = face.vertexColors.length > 0;
18238  
18239				var faceType = 0;
18240  
18241				faceType = setBit( faceType, 0, 0 ); // isQuad
18242				faceType = setBit( faceType, 1, hasMaterial );
18243				faceType = setBit( faceType, 2, hasFaceUv );
18244				faceType = setBit( faceType, 3, hasFaceVertexUv );
18245				faceType = setBit( faceType, 4, hasFaceNormal );
18246				faceType = setBit( faceType, 5, hasFaceVertexNormal );
18247				faceType = setBit( faceType, 6, hasFaceColor );
18248				faceType = setBit( faceType, 7, hasFaceVertexColor );
18249  
18250				faces.push( faceType );
18251				faces.push( face.a, face.b, face.c );
18252				faces.push( face.materialIndex );
18253  
18254				if ( hasFaceVertexUv ) {
18255  
18256					var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
18257  
18258					faces.push(
18259						getUvIndex( faceVertexUvs[ 0 ] ),
18260						getUvIndex( faceVertexUvs[ 1 ] ),
18261						getUvIndex( faceVertexUvs[ 2 ] )
18262					);
18263  
18264				}
18265  
18266				if ( hasFaceNormal ) {
18267  
18268					faces.push( getNormalIndex( face.normal ) );
18269  
18270				}
18271  
18272				if ( hasFaceVertexNormal ) {
18273  
18274					var vertexNormals = face.vertexNormals;
18275  
18276					faces.push(
18277						getNormalIndex( vertexNormals[ 0 ] ),
18278						getNormalIndex( vertexNormals[ 1 ] ),
18279						getNormalIndex( vertexNormals[ 2 ] )
18280					);
18281  
18282				}
18283  
18284				if ( hasFaceColor ) {
18285  
18286					faces.push( getColorIndex( face.color ) );
18287  
18288				}
18289  
18290				if ( hasFaceVertexColor ) {
18291  
18292					var vertexColors = face.vertexColors;
18293  
18294					faces.push(
18295						getColorIndex( vertexColors[ 0 ] ),
18296						getColorIndex( vertexColors[ 1 ] ),
18297						getColorIndex( vertexColors[ 2 ] )
18298					);
18299  
18300				}
18301  
18302			}
18303  
18304			function setBit( value, position, enabled ) {
18305  
18306				return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
18307  
18308			}
18309  
18310			function getNormalIndex( normal ) {
18311  
18312				var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
18313  
18314				if ( normalsHash[ hash ] !== undefined ) {
18315  
18316					return normalsHash[ hash ];
18317  
18318				}
18319  
18320				normalsHash[ hash ] = normals.length / 3;
18321				normals.push( normal.x, normal.y, normal.z );
18322  
18323				return normalsHash[ hash ];
18324  
18325			}
18326  
18327			function getColorIndex( color ) {
18328  
18329				var hash = color.r.toString() + color.g.toString() + color.b.toString();
18330  
18331				if ( colorsHash[ hash ] !== undefined ) {
18332  
18333					return colorsHash[ hash ];
18334  
18335				}
18336  
18337				colorsHash[ hash ] = colors.length;
18338				colors.push( color.getHex() );
18339  
18340				return colorsHash[ hash ];
18341  
18342			}
18343  
18344			function getUvIndex( uv ) {
18345  
18346				var hash = uv.x.toString() + uv.y.toString();
18347  
18348				if ( uvsHash[ hash ] !== undefined ) {
18349  
18350					return uvsHash[ hash ];
18351  
18352				}
18353  
18354				uvsHash[ hash ] = uvs.length / 2;
18355				uvs.push( uv.x, uv.y );
18356  
18357				return uvsHash[ hash ];
18358  
18359			}
18360  
18361			data.data = {};
18362  
18363			data.data.vertices = vertices;
18364			data.data.normals = normals;
18365			if ( colors.length > 0 ) data.data.colors = colors;
18366			if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
18367			data.data.faces = faces;
18368  
18369			return data;
18370  
18371		},
18372  
18373		clone: function () {
18374  
18375			/*
18376			 // Handle primitives
18377  
18378			 var parameters = this.parameters;
18379  
18380			 if ( parameters !== undefined ) {
18381  
18382			 var values = [];
18383  
18384			 for ( var key in parameters ) {
18385  
18386			 values.push( parameters[ key ] );
18387  
18388			 }
18389  
18390			 var geometry = Object.create( this.constructor.prototype );
18391			 this.constructor.apply( geometry, values );
18392			 return geometry;
18393  
18394			 }
18395  
18396			 return new this.constructor().copy( this );
18397			 */
18398  
18399			return new Geometry().copy( this );
18400  
18401		},
18402  
18403		copy: function ( source ) {
18404  
18405			var i, il, j, jl, k, kl;
18406  
18407			// reset
18408  
18409			this.vertices = [];
18410			this.colors = [];
18411			this.faces = [];
18412			this.faceVertexUvs = [[]];
18413			this.morphTargets = [];
18414			this.morphNormals = [];
18415			this.skinWeights = [];
18416			this.skinIndices = [];
18417			this.lineDistances = [];
18418			this.boundingBox = null;
18419			this.boundingSphere = null;
18420  
18421			// name
18422  
18423			this.name = source.name;
18424  
18425			// vertices
18426  
18427			var vertices = source.vertices;
18428  
18429			for ( i = 0, il = vertices.length; i < il; i ++ ) {
18430  
18431				this.vertices.push( vertices[ i ].clone() );
18432  
18433			}
18434  
18435			// colors
18436  
18437			var colors = source.colors;
18438  
18439			for ( i = 0, il = colors.length; i < il; i ++ ) {
18440  
18441				this.colors.push( colors[ i ].clone() );
18442  
18443			}
18444  
18445			// faces
18446  
18447			var faces = source.faces;
18448  
18449			for ( i = 0, il = faces.length; i < il; i ++ ) {
18450  
18451				this.faces.push( faces[ i ].clone() );
18452  
18453			}
18454  
18455			// face vertex uvs
18456  
18457			for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
18458  
18459				var faceVertexUvs = source.faceVertexUvs[ i ];
18460  
18461				if ( this.faceVertexUvs[ i ] === undefined ) {
18462  
18463					this.faceVertexUvs[ i ] = [];
18464  
18465				}
18466  
18467				for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
18468  
18469					var uvs = faceVertexUvs[ j ], uvsCopy = [];
18470  
18471					for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
18472  
18473						var uv = uvs[ k ];
18474  
18475						uvsCopy.push( uv.clone() );
18476  
18477					}
18478  
18479					this.faceVertexUvs[ i ].push( uvsCopy );
18480  
18481				}
18482  
18483			}
18484  
18485			// morph targets
18486  
18487			var morphTargets = source.morphTargets;
18488  
18489			for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
18490  
18491				var morphTarget = {};
18492				morphTarget.name = morphTargets[ i ].name;
18493  
18494				// vertices
18495  
18496				if ( morphTargets[ i ].vertices !== undefined ) {
18497  
18498					morphTarget.vertices = [];
18499  
18500					for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
18501  
18502						morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
18503  
18504					}
18505  
18506				}
18507  
18508				// normals
18509  
18510				if ( morphTargets[ i ].normals !== undefined ) {
18511  
18512					morphTarget.normals = [];
18513  
18514					for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
18515  
18516						morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
18517  
18518					}
18519  
18520				}
18521  
18522				this.morphTargets.push( morphTarget );
18523  
18524			}
18525  
18526			// morph normals
18527  
18528			var morphNormals = source.morphNormals;
18529  
18530			for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
18531  
18532				var morphNormal = {};
18533  
18534				// vertex normals
18535  
18536				if ( morphNormals[ i ].vertexNormals !== undefined ) {
18537  
18538					morphNormal.vertexNormals = [];
18539  
18540					for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
18541  
18542						var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
18543						var destVertexNormal = {};
18544  
18545						destVertexNormal.a = srcVertexNormal.a.clone();
18546						destVertexNormal.b = srcVertexNormal.b.clone();
18547						destVertexNormal.c = srcVertexNormal.c.clone();
18548  
18549						morphNormal.vertexNormals.push( destVertexNormal );
18550  
18551					}
18552  
18553				}
18554  
18555				// face normals
18556  
18557				if ( morphNormals[ i ].faceNormals !== undefined ) {
18558  
18559					morphNormal.faceNormals = [];
18560  
18561					for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
18562  
18563						morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
18564  
18565					}
18566  
18567				}
18568  
18569				this.morphNormals.push( morphNormal );
18570  
18571			}
18572  
18573			// skin weights
18574  
18575			var skinWeights = source.skinWeights;
18576  
18577			for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
18578  
18579				this.skinWeights.push( skinWeights[ i ].clone() );
18580  
18581			}
18582  
18583			// skin indices
18584  
18585			var skinIndices = source.skinIndices;
18586  
18587			for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
18588  
18589				this.skinIndices.push( skinIndices[ i ].clone() );
18590  
18591			}
18592  
18593			// line distances
18594  
18595			var lineDistances = source.lineDistances;
18596  
18597			for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
18598  
18599				this.lineDistances.push( lineDistances[ i ] );
18600  
18601			}
18602  
18603			// bounding box
18604  
18605			var boundingBox = source.boundingBox;
18606  
18607			if ( boundingBox !== null ) {
18608  
18609				this.boundingBox = boundingBox.clone();
18610  
18611			}
18612  
18613			// bounding sphere
18614  
18615			var boundingSphere = source.boundingSphere;
18616  
18617			if ( boundingSphere !== null ) {
18618  
18619				this.boundingSphere = boundingSphere.clone();
18620  
18621			}
18622  
18623			// update flags
18624  
18625			this.elementsNeedUpdate = source.elementsNeedUpdate;
18626			this.verticesNeedUpdate = source.verticesNeedUpdate;
18627			this.uvsNeedUpdate = source.uvsNeedUpdate;
18628			this.normalsNeedUpdate = source.normalsNeedUpdate;
18629			this.colorsNeedUpdate = source.colorsNeedUpdate;
18630			this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
18631			this.groupsNeedUpdate = source.groupsNeedUpdate;
18632  
18633			return this;
18634  
18635		},
18636  
18637		dispose: function () {
18638  
18639			this.dispatchEvent( { type: 'dispose' } );
18640  
18641		}
18642  
18643	} );
18644  
18645	/**
18646	 * @author mrdoob / http://mrdoob.com/
18647	 */
18648  
18649	function BufferAttribute( array, itemSize, normalized ) {
18650  
18651		if ( Array.isArray( array ) ) {
18652  
18653			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
18654  
18655		}
18656  
18657		this.name = '';
18658  
18659		this.array = array;
18660		this.itemSize = itemSize;
18661		this.count = array !== undefined ? array.length / itemSize : 0;
18662		this.normalized = normalized === true;
18663  
18664		this.dynamic = false;
18665		this.updateRange = { offset: 0, count: - 1 };
18666  
18667		this.version = 0;
18668  
18669	}
18670  
18671	Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
18672  
18673		set: function ( value ) {
18674  
18675			if ( value === true ) this.version ++;
18676  
18677		}
18678  
18679	} );
18680  
18681	Object.assign( BufferAttribute.prototype, {
18682  
18683		isBufferAttribute: true,
18684  
18685		onUploadCallback: function () {},
18686  
18687		setArray: function ( array ) {
18688  
18689			if ( Array.isArray( array ) ) {
18690  
18691				throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
18692  
18693			}
18694  
18695			this.count = array !== undefined ? array.length / this.itemSize : 0;
18696			this.array = array;
18697  
18698			return this;
18699  
18700		},
18701  
18702		setDynamic: function ( value ) {
18703  
18704			this.dynamic = value;
18705  
18706			return this;
18707  
18708		},
18709  
18710		copy: function ( source ) {
18711  
18712			this.name = source.name;
18713			this.array = new source.array.constructor( source.array );
18714			this.itemSize = source.itemSize;
18715			this.count = source.count;
18716			this.normalized = source.normalized;
18717  
18718			this.dynamic = source.dynamic;
18719  
18720			return this;
18721  
18722		},
18723  
18724		copyAt: function ( index1, attribute, index2 ) {
18725  
18726			index1 *= this.itemSize;
18727			index2 *= attribute.itemSize;
18728  
18729			for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
18730  
18731				this.array[ index1 + i ] = attribute.array[ index2 + i ];
18732  
18733			}
18734  
18735			return this;
18736  
18737		},
18738  
18739		copyArray: function ( array ) {
18740  
18741			this.array.set( array );
18742  
18743			return this;
18744  
18745		},
18746  
18747		copyColorsArray: function ( colors ) {
18748  
18749			var array = this.array, offset = 0;
18750  
18751			for ( var i = 0, l = colors.length; i < l; i ++ ) {
18752  
18753				var color = colors[ i ];
18754  
18755				if ( color === undefined ) {
18756  
18757					console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
18758					color = new Color();
18759  
18760				}
18761  
18762				array[ offset ++ ] = color.r;
18763				array[ offset ++ ] = color.g;
18764				array[ offset ++ ] = color.b;
18765  
18766			}
18767  
18768			return this;
18769  
18770		},
18771  
18772		copyVector2sArray: function ( vectors ) {
18773  
18774			var array = this.array, offset = 0;
18775  
18776			for ( var i = 0, l = vectors.length; i < l; i ++ ) {
18777  
18778				var vector = vectors[ i ];
18779  
18780				if ( vector === undefined ) {
18781  
18782					console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
18783					vector = new Vector2();
18784  
18785				}
18786  
18787				array[ offset ++ ] = vector.x;
18788				array[ offset ++ ] = vector.y;
18789  
18790			}
18791  
18792			return this;
18793  
18794		},
18795  
18796		copyVector3sArray: function ( vectors ) {
18797  
18798			var array = this.array, offset = 0;
18799  
18800			for ( var i = 0, l = vectors.length; i < l; i ++ ) {
18801  
18802				var vector = vectors[ i ];
18803  
18804				if ( vector === undefined ) {
18805  
18806					console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
18807					vector = new Vector3();
18808  
18809				}
18810  
18811				array[ offset ++ ] = vector.x;
18812				array[ offset ++ ] = vector.y;
18813				array[ offset ++ ] = vector.z;
18814  
18815			}
18816  
18817			return this;
18818  
18819		},
18820  
18821		copyVector4sArray: function ( vectors ) {
18822  
18823			var array = this.array, offset = 0;
18824  
18825			for ( var i = 0, l = vectors.length; i < l; i ++ ) {
18826  
18827				var vector = vectors[ i ];
18828  
18829				if ( vector === undefined ) {
18830  
18831					console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
18832					vector = new Vector4();
18833  
18834				}
18835  
18836				array[ offset ++ ] = vector.x;
18837				array[ offset ++ ] = vector.y;
18838				array[ offset ++ ] = vector.z;
18839				array[ offset ++ ] = vector.w;
18840  
18841			}
18842  
18843			return this;
18844  
18845		},
18846  
18847		set: function ( value, offset ) {
18848  
18849			if ( offset === undefined ) offset = 0;
18850  
18851			this.array.set( value, offset );
18852  
18853			return this;
18854  
18855		},
18856  
18857		getX: function ( index ) {
18858  
18859			return this.array[ index * this.itemSize ];
18860  
18861		},
18862  
18863		setX: function ( index, x ) {
18864  
18865			this.array[ index * this.itemSize ] = x;
18866  
18867			return this;
18868  
18869		},
18870  
18871		getY: function ( index ) {
18872  
18873			return this.array[ index * this.itemSize + 1 ];
18874  
18875		},
18876  
18877		setY: function ( index, y ) {
18878  
18879			this.array[ index * this.itemSize + 1 ] = y;
18880  
18881			return this;
18882  
18883		},
18884  
18885		getZ: function ( index ) {
18886  
18887			return this.array[ index * this.itemSize + 2 ];
18888  
18889		},
18890  
18891		setZ: function ( index, z ) {
18892  
18893			this.array[ index * this.itemSize + 2 ] = z;
18894  
18895			return this;
18896  
18897		},
18898  
18899		getW: function ( index ) {
18900  
18901			return this.array[ index * this.itemSize + 3 ];
18902  
18903		},
18904  
18905		setW: function ( index, w ) {
18906  
18907			this.array[ index * this.itemSize + 3 ] = w;
18908  
18909			return this;
18910  
18911		},
18912  
18913		setXY: function ( index, x, y ) {
18914  
18915			index *= this.itemSize;
18916  
18917			this.array[ index + 0 ] = x;
18918			this.array[ index + 1 ] = y;
18919  
18920			return this;
18921  
18922		},
18923  
18924		setXYZ: function ( index, x, y, z ) {
18925  
18926			index *= this.itemSize;
18927  
18928			this.array[ index + 0 ] = x;
18929			this.array[ index + 1 ] = y;
18930			this.array[ index + 2 ] = z;
18931  
18932			return this;
18933  
18934		},
18935  
18936		setXYZW: function ( index, x, y, z, w ) {
18937  
18938			index *= this.itemSize;
18939  
18940			this.array[ index + 0 ] = x;
18941			this.array[ index + 1 ] = y;
18942			this.array[ index + 2 ] = z;
18943			this.array[ index + 3 ] = w;
18944  
18945			return this;
18946  
18947		},
18948  
18949		onUpload: function ( callback ) {
18950  
18951			this.onUploadCallback = callback;
18952  
18953			return this;
18954  
18955		},
18956  
18957		clone: function () {
18958  
18959			return new this.constructor( this.array, this.itemSize ).copy( this );
18960  
18961		}
18962  
18963	} );
18964  
18965	//
18966  
18967	function Int8BufferAttribute( array, itemSize, normalized ) {
18968  
18969		BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
18970  
18971	}
18972  
18973	Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
18974	Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
18975  
18976  
18977	function Uint8BufferAttribute( array, itemSize, normalized ) {
18978  
18979		BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
18980  
18981	}
18982  
18983	Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
18984	Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
18985  
18986  
18987	function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
18988  
18989		BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
18990  
18991	}
18992  
18993	Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
18994	Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
18995  
18996  
18997	function Int16BufferAttribute( array, itemSize, normalized ) {
18998  
18999		BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
19000  
19001	}
19002  
19003	Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19004	Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
19005  
19006  
19007	function Uint16BufferAttribute( array, itemSize, normalized ) {
19008  
19009		BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
19010  
19011	}
19012  
19013	Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19014	Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
19015  
19016  
19017	function Int32BufferAttribute( array, itemSize, normalized ) {
19018  
19019		BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
19020  
19021	}
19022  
19023	Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19024	Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
19025  
19026  
19027	function Uint32BufferAttribute( array, itemSize, normalized ) {
19028  
19029		BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
19030  
19031	}
19032  
19033	Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19034	Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
19035  
19036  
19037	function Float32BufferAttribute( array, itemSize, normalized ) {
19038  
19039		BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
19040  
19041	}
19042  
19043	Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19044	Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
19045  
19046  
19047	function Float64BufferAttribute( array, itemSize, normalized ) {
19048  
19049		BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
19050  
19051	}
19052  
19053	Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
19054	Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
19055  
19056	/**
19057	 * @author mrdoob / http://mrdoob.com/
19058	 */
19059  
19060	function DirectGeometry() {
19061  
19062		this.vertices = [];
19063		this.normals = [];
19064		this.colors = [];
19065		this.uvs = [];
19066		this.uvs2 = [];
19067  
19068		this.groups = [];
19069  
19070		this.morphTargets = {};
19071  
19072		this.skinWeights = [];
19073		this.skinIndices = [];
19074  
19075		// this.lineDistances = [];
19076  
19077		this.boundingBox = null;
19078		this.boundingSphere = null;
19079  
19080		// update flags
19081  
19082		this.verticesNeedUpdate = false;
19083		this.normalsNeedUpdate = false;
19084		this.colorsNeedUpdate = false;
19085		this.uvsNeedUpdate = false;
19086		this.groupsNeedUpdate = false;
19087  
19088	}
19089  
19090	Object.assign( DirectGeometry.prototype, {
19091  
19092		computeGroups: function ( geometry ) {
19093  
19094			var group;
19095			var groups = [];
19096			var materialIndex = undefined;
19097  
19098			var faces = geometry.faces;
19099  
19100			for ( var i = 0; i < faces.length; i ++ ) {
19101  
19102				var face = faces[ i ];
19103  
19104				// materials
19105  
19106				if ( face.materialIndex !== materialIndex ) {
19107  
19108					materialIndex = face.materialIndex;
19109  
19110					if ( group !== undefined ) {
19111  
19112						group.count = ( i * 3 ) - group.start;
19113						groups.push( group );
19114  
19115					}
19116  
19117					group = {
19118						start: i * 3,
19119						materialIndex: materialIndex
19120					};
19121  
19122				}
19123  
19124			}
19125  
19126			if ( group !== undefined ) {
19127  
19128				group.count = ( i * 3 ) - group.start;
19129				groups.push( group );
19130  
19131			}
19132  
19133			this.groups = groups;
19134  
19135		},
19136  
19137		fromGeometry: function ( geometry ) {
19138  
19139			var faces = geometry.faces;
19140			var vertices = geometry.vertices;
19141			var faceVertexUvs = geometry.faceVertexUvs;
19142  
19143			var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
19144			var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
19145  
19146			// morphs
19147  
19148			var morphTargets = geometry.morphTargets;
19149			var morphTargetsLength = morphTargets.length;
19150  
19151			var morphTargetsPosition;
19152  
19153			if ( morphTargetsLength > 0 ) {
19154  
19155				morphTargetsPosition = [];
19156  
19157				for ( var i = 0; i < morphTargetsLength; i ++ ) {
19158  
19159					morphTargetsPosition[ i ] = [];
19160  
19161				}
19162  
19163				this.morphTargets.position = morphTargetsPosition;
19164  
19165			}
19166  
19167			var morphNormals = geometry.morphNormals;
19168			var morphNormalsLength = morphNormals.length;
19169  
19170			var morphTargetsNormal;
19171  
19172			if ( morphNormalsLength > 0 ) {
19173  
19174				morphTargetsNormal = [];
19175  
19176				for ( var i = 0; i < morphNormalsLength; i ++ ) {
19177  
19178					morphTargetsNormal[ i ] = [];
19179  
19180				}
19181  
19182				this.morphTargets.normal = morphTargetsNormal;
19183  
19184			}
19185  
19186			// skins
19187  
19188			var skinIndices = geometry.skinIndices;
19189			var skinWeights = geometry.skinWeights;
19190  
19191			var hasSkinIndices = skinIndices.length === vertices.length;
19192			var hasSkinWeights = skinWeights.length === vertices.length;
19193  
19194			//
19195  
19196			if ( faces.length === 0 ) {
19197  
19198				console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
19199  
19200			}
19201  
19202			for ( var i = 0; i < faces.length; i ++ ) {
19203  
19204				var face = faces[ i ];
19205  
19206				this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
19207  
19208				var vertexNormals = face.vertexNormals;
19209  
19210				if ( vertexNormals.length === 3 ) {
19211  
19212					this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
19213  
19214				} else {
19215  
19216					var normal = face.normal;
19217  
19218					this.normals.push( normal, normal, normal );
19219  
19220				}
19221  
19222				var vertexColors = face.vertexColors;
19223  
19224				if ( vertexColors.length === 3 ) {
19225  
19226					this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
19227  
19228				} else {
19229  
19230					var color = face.color;
19231  
19232					this.colors.push( color, color, color );
19233  
19234				}
19235  
19236				if ( hasFaceVertexUv === true ) {
19237  
19238					var vertexUvs = faceVertexUvs[ 0 ][ i ];
19239  
19240					if ( vertexUvs !== undefined ) {
19241  
19242						this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
19243  
19244					} else {
19245  
19246						console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
19247  
19248						this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
19249  
19250					}
19251  
19252				}
19253  
19254				if ( hasFaceVertexUv2 === true ) {
19255  
19256					var vertexUvs = faceVertexUvs[ 1 ][ i ];
19257  
19258					if ( vertexUvs !== undefined ) {
19259  
19260						this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
19261  
19262					} else {
19263  
19264						console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
19265  
19266						this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
19267  
19268					}
19269  
19270				}
19271  
19272				// morphs
19273  
19274				for ( var j = 0; j < morphTargetsLength; j ++ ) {
19275  
19276					var morphTarget = morphTargets[ j ].vertices;
19277  
19278					morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
19279  
19280				}
19281  
19282				for ( var j = 0; j < morphNormalsLength; j ++ ) {
19283  
19284					var morphNormal = morphNormals[ j ].vertexNormals[ i ];
19285  
19286					morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
19287  
19288				}
19289  
19290				// skins
19291  
19292				if ( hasSkinIndices ) {
19293  
19294					this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
19295  
19296				}
19297  
19298				if ( hasSkinWeights ) {
19299  
19300					this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
19301  
19302				}
19303  
19304			}
19305  
19306			this.computeGroups( geometry );
19307  
19308			this.verticesNeedUpdate = geometry.verticesNeedUpdate;
19309			this.normalsNeedUpdate = geometry.normalsNeedUpdate;
19310			this.colorsNeedUpdate = geometry.colorsNeedUpdate;
19311			this.uvsNeedUpdate = geometry.uvsNeedUpdate;
19312			this.groupsNeedUpdate = geometry.groupsNeedUpdate;
19313  
19314			return this;
19315  
19316		}
19317  
19318	} );
19319  
19320	/**
19321	 * @author mrdoob / http://mrdoob.com/
19322	 */
19323  
19324	function arrayMax( array ) {
19325  
19326		if ( array.length === 0 ) return - Infinity;
19327  
19328		var max = array[ 0 ];
19329  
19330		for ( var i = 1, l = array.length; i < l; ++ i ) {
19331  
19332			if ( array[ i ] > max ) max = array[ i ];
19333  
19334		}
19335  
19336		return max;
19337  
19338	}
19339  
19340	/**
19341	 * @author alteredq / http://alteredqualia.com/
19342	 * @author mrdoob / http://mrdoob.com/
19343	 */
19344  
19345	var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
19346  
19347	function BufferGeometry() {
19348  
19349		Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
19350  
19351		this.uuid = _Math.generateUUID();
19352  
19353		this.name = '';
19354		this.type = 'BufferGeometry';
19355  
19356		this.index = null;
19357		this.attributes = {};
19358  
19359		this.morphAttributes = {};
19360  
19361		this.groups = [];
19362  
19363		this.boundingBox = null;
19364		this.boundingSphere = null;
19365  
19366		this.drawRange = { start: 0, count: Infinity };
19367  
19368		this.userData = {};
19369  
19370	}
19371  
19372	BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
19373  
19374		constructor: BufferGeometry,
19375  
19376		isBufferGeometry: true,
19377  
19378		getIndex: function () {
19379  
19380			return this.index;
19381  
19382		},
19383  
19384		setIndex: function ( index ) {
19385  
19386			if ( Array.isArray( index ) ) {
19387  
19388				this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
19389  
19390			} else {
19391  
19392				this.index = index;
19393  
19394			}
19395  
19396		},
19397  
19398		addAttribute: function ( name, attribute ) {
19399  
19400			if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
19401  
19402				console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
19403  
19404				return this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
19405  
19406			}
19407  
19408			if ( name === 'index' ) {
19409  
19410				console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
19411				this.setIndex( attribute );
19412  
19413				return this;
19414  
19415			}
19416  
19417			this.attributes[ name ] = attribute;
19418  
19419			return this;
19420  
19421		},
19422  
19423		getAttribute: function ( name ) {
19424  
19425			return this.attributes[ name ];
19426  
19427		},
19428  
19429		removeAttribute: function ( name ) {
19430  
19431			delete this.attributes[ name ];
19432  
19433			return this;
19434  
19435		},
19436  
19437		addGroup: function ( start, count, materialIndex ) {
19438  
19439			this.groups.push( {
19440  
19441				start: start,
19442				count: count,
19443				materialIndex: materialIndex !== undefined ? materialIndex : 0
19444  
19445			} );
19446  
19447		},
19448  
19449		clearGroups: function () {
19450  
19451			this.groups = [];
19452  
19453		},
19454  
19455		setDrawRange: function ( start, count ) {
19456  
19457			this.drawRange.start = start;
19458			this.drawRange.count = count;
19459  
19460		},
19461  
19462		applyMatrix: function ( matrix ) {
19463  
19464			var position = this.attributes.position;
19465  
19466			if ( position !== undefined ) {
19467  
19468				matrix.applyToBufferAttribute( position );
19469				position.needsUpdate = true;
19470  
19471			}
19472  
19473			var normal = this.attributes.normal;
19474  
19475			if ( normal !== undefined ) {
19476  
19477				var normalMatrix = new Matrix3().getNormalMatrix( matrix );
19478  
19479				normalMatrix.applyToBufferAttribute( normal );
19480				normal.needsUpdate = true;
19481  
19482			}
19483  
19484			if ( this.boundingBox !== null ) {
19485  
19486				this.computeBoundingBox();
19487  
19488			}
19489  
19490			if ( this.boundingSphere !== null ) {
19491  
19492				this.computeBoundingSphere();
19493  
19494			}
19495  
19496			return this;
19497  
19498		},
19499  
19500		rotateX: function () {
19501  
19502			// rotate geometry around world x-axis
19503  
19504			var m1 = new Matrix4();
19505  
19506			return function rotateX( angle ) {
19507  
19508				m1.makeRotationX( angle );
19509  
19510				this.applyMatrix( m1 );
19511  
19512				return this;
19513  
19514			};
19515  
19516		}(),
19517  
19518		rotateY: function () {
19519  
19520			// rotate geometry around world y-axis
19521  
19522			var m1 = new Matrix4();
19523  
19524			return function rotateY( angle ) {
19525  
19526				m1.makeRotationY( angle );
19527  
19528				this.applyMatrix( m1 );
19529  
19530				return this;
19531  
19532			};
19533  
19534		}(),
19535  
19536		rotateZ: function () {
19537  
19538			// rotate geometry around world z-axis
19539  
19540			var m1 = new Matrix4();
19541  
19542			return function rotateZ( angle ) {
19543  
19544				m1.makeRotationZ( angle );
19545  
19546				this.applyMatrix( m1 );
19547  
19548				return this;
19549  
19550			};
19551  
19552		}(),
19553  
19554		translate: function () {
19555  
19556			// translate geometry
19557  
19558			var m1 = new Matrix4();
19559  
19560			return function translate( x, y, z ) {
19561  
19562				m1.makeTranslation( x, y, z );
19563  
19564				this.applyMatrix( m1 );
19565  
19566				return this;
19567  
19568			};
19569  
19570		}(),
19571  
19572		scale: function () {
19573  
19574			// scale geometry
19575  
19576			var m1 = new Matrix4();
19577  
19578			return function scale( x, y, z ) {
19579  
19580				m1.makeScale( x, y, z );
19581  
19582				this.applyMatrix( m1 );
19583  
19584				return this;
19585  
19586			};
19587  
19588		}(),
19589  
19590		lookAt: function () {
19591  
19592			var obj = new Object3D();
19593  
19594			return function lookAt( vector ) {
19595  
19596				obj.lookAt( vector );
19597  
19598				obj.updateMatrix();
19599  
19600				this.applyMatrix( obj.matrix );
19601  
19602			};
19603  
19604		}(),
19605  
19606		center: function () {
19607  
19608			var offset = new Vector3();
19609  
19610			return function center() {
19611  
19612				this.computeBoundingBox();
19613  
19614				this.boundingBox.getCenter( offset ).negate();
19615  
19616				this.translate( offset.x, offset.y, offset.z );
19617  
19618				return this;
19619  
19620			};
19621  
19622		}(),
19623  
19624		setFromObject: function ( object ) {
19625  
19626			// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
19627  
19628			var geometry = object.geometry;
19629  
19630			if ( object.isPoints || object.isLine ) {
19631  
19632				var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
19633				var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
19634  
19635				this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
19636				this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
19637  
19638				if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
19639  
19640					var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
19641  
19642					this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
19643  
19644				}
19645  
19646				if ( geometry.boundingSphere !== null ) {
19647  
19648					this.boundingSphere = geometry.boundingSphere.clone();
19649  
19650				}
19651  
19652				if ( geometry.boundingBox !== null ) {
19653  
19654					this.boundingBox = geometry.boundingBox.clone();
19655  
19656				}
19657  
19658			} else if ( object.isMesh ) {
19659  
19660				if ( geometry && geometry.isGeometry ) {
19661  
19662					this.fromGeometry( geometry );
19663  
19664				}
19665  
19666			}
19667  
19668			return this;
19669  
19670		},
19671  
19672		setFromPoints: function ( points ) {
19673  
19674			var position = [];
19675  
19676			for ( var i = 0, l = points.length; i < l; i ++ ) {
19677  
19678				var point = points[ i ];
19679				position.push( point.x, point.y, point.z || 0 );
19680  
19681			}
19682  
19683			this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
19684  
19685			return this;
19686  
19687		},
19688  
19689		updateFromObject: function ( object ) {
19690  
19691			var geometry = object.geometry;
19692  
19693			if ( object.isMesh ) {
19694  
19695				var direct = geometry.__directGeometry;
19696  
19697				if ( geometry.elementsNeedUpdate === true ) {
19698  
19699					direct = undefined;
19700					geometry.elementsNeedUpdate = false;
19701  
19702				}
19703  
19704				if ( direct === undefined ) {
19705  
19706					return this.fromGeometry( geometry );
19707  
19708				}
19709  
19710				direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
19711				direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
19712				direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
19713				direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
19714				direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
19715  
19716				geometry.verticesNeedUpdate = false;
19717				geometry.normalsNeedUpdate = false;
19718				geometry.colorsNeedUpdate = false;
19719				geometry.uvsNeedUpdate = false;
19720				geometry.groupsNeedUpdate = false;
19721  
19722				geometry = direct;
19723  
19724			}
19725  
19726			var attribute;
19727  
19728			if ( geometry.verticesNeedUpdate === true ) {
19729  
19730				attribute = this.attributes.position;
19731  
19732				if ( attribute !== undefined ) {
19733  
19734					attribute.copyVector3sArray( geometry.vertices );
19735					attribute.needsUpdate = true;
19736  
19737				}
19738  
19739				geometry.verticesNeedUpdate = false;
19740  
19741			}
19742  
19743			if ( geometry.normalsNeedUpdate === true ) {
19744  
19745				attribute = this.attributes.normal;
19746  
19747				if ( attribute !== undefined ) {
19748  
19749					attribute.copyVector3sArray( geometry.normals );
19750					attribute.needsUpdate = true;
19751  
19752				}
19753  
19754				geometry.normalsNeedUpdate = false;
19755  
19756			}
19757  
19758			if ( geometry.colorsNeedUpdate === true ) {
19759  
19760				attribute = this.attributes.color;
19761  
19762				if ( attribute !== undefined ) {
19763  
19764					attribute.copyColorsArray( geometry.colors );
19765					attribute.needsUpdate = true;
19766  
19767				}
19768  
19769				geometry.colorsNeedUpdate = false;
19770  
19771			}
19772  
19773			if ( geometry.uvsNeedUpdate ) {
19774  
19775				attribute = this.attributes.uv;
19776  
19777				if ( attribute !== undefined ) {
19778  
19779					attribute.copyVector2sArray( geometry.uvs );
19780					attribute.needsUpdate = true;
19781  
19782				}
19783  
19784				geometry.uvsNeedUpdate = false;
19785  
19786			}
19787  
19788			if ( geometry.lineDistancesNeedUpdate ) {
19789  
19790				attribute = this.attributes.lineDistance;
19791  
19792				if ( attribute !== undefined ) {
19793  
19794					attribute.copyArray( geometry.lineDistances );
19795					attribute.needsUpdate = true;
19796  
19797				}
19798  
19799				geometry.lineDistancesNeedUpdate = false;
19800  
19801			}
19802  
19803			if ( geometry.groupsNeedUpdate ) {
19804  
19805				geometry.computeGroups( object.geometry );
19806				this.groups = geometry.groups;
19807  
19808				geometry.groupsNeedUpdate = false;
19809  
19810			}
19811  
19812			return this;
19813  
19814		},
19815  
19816		fromGeometry: function ( geometry ) {
19817  
19818			geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
19819  
19820			return this.fromDirectGeometry( geometry.__directGeometry );
19821  
19822		},
19823  
19824		fromDirectGeometry: function ( geometry ) {
19825  
19826			var positions = new Float32Array( geometry.vertices.length * 3 );
19827			this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
19828  
19829			if ( geometry.normals.length > 0 ) {
19830  
19831				var normals = new Float32Array( geometry.normals.length * 3 );
19832				this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
19833  
19834			}
19835  
19836			if ( geometry.colors.length > 0 ) {
19837  
19838				var colors = new Float32Array( geometry.colors.length * 3 );
19839				this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
19840  
19841			}
19842  
19843			if ( geometry.uvs.length > 0 ) {
19844  
19845				var uvs = new Float32Array( geometry.uvs.length * 2 );
19846				this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
19847  
19848			}
19849  
19850			if ( geometry.uvs2.length > 0 ) {
19851  
19852				var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
19853				this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
19854  
19855			}
19856  
19857			// groups
19858  
19859			this.groups = geometry.groups;
19860  
19861			// morphs
19862  
19863			for ( var name in geometry.morphTargets ) {
19864  
19865				var array = [];
19866				var morphTargets = geometry.morphTargets[ name ];
19867  
19868				for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
19869  
19870					var morphTarget = morphTargets[ i ];
19871  
19872					var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
19873  
19874					array.push( attribute.copyVector3sArray( morphTarget ) );
19875  
19876				}
19877  
19878				this.morphAttributes[ name ] = array;
19879  
19880			}
19881  
19882			// skinning
19883  
19884			if ( geometry.skinIndices.length > 0 ) {
19885  
19886				var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
19887				this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
19888  
19889			}
19890  
19891			if ( geometry.skinWeights.length > 0 ) {
19892  
19893				var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
19894				this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
19895  
19896			}
19897  
19898			//
19899  
19900			if ( geometry.boundingSphere !== null ) {
19901  
19902				this.boundingSphere = geometry.boundingSphere.clone();
19903  
19904			}
19905  
19906			if ( geometry.boundingBox !== null ) {
19907  
19908				this.boundingBox = geometry.boundingBox.clone();
19909  
19910			}
19911  
19912			return this;
19913  
19914		},
19915  
19916		computeBoundingBox: function () {
19917  
19918			if ( this.boundingBox === null ) {
19919  
19920				this.boundingBox = new Box3();
19921  
19922			}
19923  
19924			var position = this.attributes.position;
19925  
19926			if ( position !== undefined ) {
19927  
19928				this.boundingBox.setFromBufferAttribute( position );
19929  
19930			} else {
19931  
19932				this.boundingBox.makeEmpty();
19933  
19934			}
19935  
19936			if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
19937  
19938				console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
19939  
19940			}
19941  
19942		},
19943  
19944		computeBoundingSphere: function () {
19945  
19946			var box = new Box3();
19947			var vector = new Vector3();
19948  
19949			return function computeBoundingSphere() {
19950  
19951				if ( this.boundingSphere === null ) {
19952  
19953					this.boundingSphere = new Sphere();
19954  
19955				}
19956  
19957				var position = this.attributes.position;
19958  
19959				if ( position ) {
19960  
19961					var center = this.boundingSphere.center;
19962  
19963					box.setFromBufferAttribute( position );
19964					box.getCenter( center );
19965  
19966					// hoping to find a boundingSphere with a radius smaller than the
19967					// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
19968  
19969					var maxRadiusSq = 0;
19970  
19971					for ( var i = 0, il = position.count; i < il; i ++ ) {
19972  
19973						vector.x = position.getX( i );
19974						vector.y = position.getY( i );
19975						vector.z = position.getZ( i );
19976						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
19977  
19978					}
19979  
19980					this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
19981  
19982					if ( isNaN( this.boundingSphere.radius ) ) {
19983  
19984						console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
19985  
19986					}
19987  
19988				}
19989  
19990			};
19991  
19992		}(),
19993  
19994		computeFaceNormals: function () {
19995  
19996			// backwards compatibility
19997  
19998		},
19999  
20000		computeVertexNormals: function () {
20001  
20002			var index = this.index;
20003			var attributes = this.attributes;
20004			var groups = this.groups;
20005  
20006			if ( attributes.position ) {
20007  
20008				var positions = attributes.position.array;
20009  
20010				if ( attributes.normal === undefined ) {
20011  
20012					this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
20013  
20014				} else {
20015  
20016					// reset existing normals to zero
20017  
20018					var array = attributes.normal.array;
20019  
20020					for ( var i = 0, il = array.length; i < il; i ++ ) {
20021  
20022						array[ i ] = 0;
20023  
20024					}
20025  
20026				}
20027  
20028				var normals = attributes.normal.array;
20029  
20030				var vA, vB, vC;
20031				var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
20032				var cb = new Vector3(), ab = new Vector3();
20033  
20034				// indexed elements
20035  
20036				if ( index ) {
20037  
20038					var indices = index.array;
20039  
20040					if ( groups.length === 0 ) {
20041  
20042						this.addGroup( 0, indices.length );
20043  
20044					}
20045  
20046					for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
20047  
20048						var group = groups[ j ];
20049  
20050						var start = group.start;
20051						var count = group.count;
20052  
20053						for ( var i = start, il = start + count; i < il; i += 3 ) {
20054  
20055							vA = indices[ i + 0 ] * 3;
20056							vB = indices[ i + 1 ] * 3;
20057							vC = indices[ i + 2 ] * 3;
20058  
20059							pA.fromArray( positions, vA );
20060							pB.fromArray( positions, vB );
20061							pC.fromArray( positions, vC );
20062  
20063							cb.subVectors( pC, pB );
20064							ab.subVectors( pA, pB );
20065							cb.cross( ab );
20066  
20067							normals[ vA ] += cb.x;
20068							normals[ vA + 1 ] += cb.y;
20069							normals[ vA + 2 ] += cb.z;
20070  
20071							normals[ vB ] += cb.x;
20072							normals[ vB + 1 ] += cb.y;
20073							normals[ vB + 2 ] += cb.z;
20074  
20075							normals[ vC ] += cb.x;
20076							normals[ vC + 1 ] += cb.y;
20077							normals[ vC + 2 ] += cb.z;
20078  
20079						}
20080  
20081					}
20082  
20083				} else {
20084  
20085					// non-indexed elements (unconnected triangle soup)
20086  
20087					for ( var i = 0, il = positions.length; i < il; i += 9 ) {
20088  
20089						pA.fromArray( positions, i );
20090						pB.fromArray( positions, i + 3 );
20091						pC.fromArray( positions, i + 6 );
20092  
20093						cb.subVectors( pC, pB );
20094						ab.subVectors( pA, pB );
20095						cb.cross( ab );
20096  
20097						normals[ i ] = cb.x;
20098						normals[ i + 1 ] = cb.y;
20099						normals[ i + 2 ] = cb.z;
20100  
20101						normals[ i + 3 ] = cb.x;
20102						normals[ i + 4 ] = cb.y;
20103						normals[ i + 5 ] = cb.z;
20104  
20105						normals[ i + 6 ] = cb.x;
20106						normals[ i + 7 ] = cb.y;
20107						normals[ i + 8 ] = cb.z;
20108  
20109					}
20110  
20111				}
20112  
20113				this.normalizeNormals();
20114  
20115				attributes.normal.needsUpdate = true;
20116  
20117			}
20118  
20119		},
20120  
20121		merge: function ( geometry, offset ) {
20122  
20123			if ( ! ( geometry && geometry.isBufferGeometry ) ) {
20124  
20125				console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
20126				return;
20127  
20128			}
20129  
20130			if ( offset === undefined ) {
20131  
20132				offset = 0;
20133  
20134				console.warn(
20135					'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
20136					+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
20137				);
20138  
20139			}
20140  
20141			var attributes = this.attributes;
20142  
20143			for ( var key in attributes ) {
20144  
20145				if ( geometry.attributes[ key ] === undefined ) continue;
20146  
20147				var attribute1 = attributes[ key ];
20148				var attributeArray1 = attribute1.array;
20149  
20150				var attribute2 = geometry.attributes[ key ];
20151				var attributeArray2 = attribute2.array;
20152  
20153				var attributeSize = attribute2.itemSize;
20154  
20155				for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
20156  
20157					attributeArray1[ j ] = attributeArray2[ i ];
20158  
20159				}
20160  
20161			}
20162  
20163			return this;
20164  
20165		},
20166  
20167		normalizeNormals: function () {
20168  
20169			var vector = new Vector3();
20170  
20171			return function normalizeNormals() {
20172  
20173				var normals = this.attributes.normal;
20174  
20175				for ( var i = 0, il = normals.count; i < il; i ++ ) {
20176  
20177					vector.x = normals.getX( i );
20178					vector.y = normals.getY( i );
20179					vector.z = normals.getZ( i );
20180  
20181					vector.normalize();
20182  
20183					normals.setXYZ( i, vector.x, vector.y, vector.z );
20184  
20185				}
20186  
20187			};
20188  
20189		}(),
20190  
20191		toNonIndexed: function () {
20192  
20193			if ( this.index === null ) {
20194  
20195				console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
20196				return this;
20197  
20198			}
20199  
20200			var geometry2 = new BufferGeometry();
20201  
20202			var indices = this.index.array;
20203			var attributes = this.attributes;
20204  
20205			for ( var name in attributes ) {
20206  
20207				var attribute = attributes[ name ];
20208  
20209				var array = attribute.array;
20210				var itemSize = attribute.itemSize;
20211  
20212				var array2 = new array.constructor( indices.length * itemSize );
20213  
20214				var index = 0, index2 = 0;
20215  
20216				for ( var i = 0, l = indices.length; i < l; i ++ ) {
20217  
20218					index = indices[ i ] * itemSize;
20219  
20220					for ( var j = 0; j < itemSize; j ++ ) {
20221  
20222						array2[ index2 ++ ] = array[ index ++ ];
20223  
20224					}
20225  
20226				}
20227  
20228				geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
20229  
20230			}
20231  
20232			var groups = this.groups;
20233  
20234			for ( var i = 0, l = groups.length; i < l; i ++ ) {
20235  
20236				var group = groups[ i ];
20237				geometry2.addGroup( group.start, group.count, group.materialIndex );
20238  
20239			}
20240  
20241			return geometry2;
20242  
20243		},
20244  
20245		toJSON: function () {
20246  
20247			var data = {
20248				metadata: {
20249					version: 4.5,
20250					type: 'BufferGeometry',
20251					generator: 'BufferGeometry.toJSON'
20252				}
20253			};
20254  
20255			// standard BufferGeometry serialization
20256  
20257			data.uuid = this.uuid;
20258			data.type = this.type;
20259			if ( this.name !== '' ) data.name = this.name;
20260			if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
20261  
20262			if ( this.parameters !== undefined ) {
20263  
20264				var parameters = this.parameters;
20265  
20266				for ( var key in parameters ) {
20267  
20268					if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
20269  
20270				}
20271  
20272				return data;
20273  
20274			}
20275  
20276			data.data = { attributes: {} };
20277  
20278			var index = this.index;
20279  
20280			if ( index !== null ) {
20281  
20282				var array = Array.prototype.slice.call( index.array );
20283  
20284				data.data.index = {
20285					type: index.array.constructor.name,
20286					array: array
20287				};
20288  
20289			}
20290  
20291			var attributes = this.attributes;
20292  
20293			for ( var key in attributes ) {
20294  
20295				var attribute = attributes[ key ];
20296  
20297				var array = Array.prototype.slice.call( attribute.array );
20298  
20299				data.data.attributes[ key ] = {
20300					itemSize: attribute.itemSize,
20301					type: attribute.array.constructor.name,
20302					array: array,
20303					normalized: attribute.normalized
20304				};
20305  
20306			}
20307  
20308			var groups = this.groups;
20309  
20310			if ( groups.length > 0 ) {
20311  
20312				data.data.groups = JSON.parse( JSON.stringify( groups ) );
20313  
20314			}
20315  
20316			var boundingSphere = this.boundingSphere;
20317  
20318			if ( boundingSphere !== null ) {
20319  
20320				data.data.boundingSphere = {
20321					center: boundingSphere.center.toArray(),
20322					radius: boundingSphere.radius
20323				};
20324  
20325			}
20326  
20327			return data;
20328  
20329		},
20330  
vendor: 30,494 bytes, lines 20331-21606
20331		clone: function () {
20332  
20333			/*
20334			 // Handle primitives
20335  
20336			 var parameters = this.parameters;
20337  
20338			 if ( parameters !== undefined ) {
20339  
20340			 var values = [];
20341  
20342			 for ( var key in parameters ) {
20343  
20344			 values.push( parameters[ key ] );
20345  
20346			 }
20347  
20348			 var geometry = Object.create( this.constructor.prototype );
20349			 this.constructor.apply( geometry, values );
20350			 return geometry;
20351  
20352			 }
20353  
20354			 return new this.constructor().copy( this );
20355			 */
20356  
20357			return new BufferGeometry().copy( this );
20358  
20359		},
20360  
20361		copy: function ( source ) {
20362  
20363			var name, i, l;
20364  
20365			// reset
20366  
20367			this.index = null;
20368			this.attributes = {};
20369			this.morphAttributes = {};
20370			this.groups = [];
20371			this.boundingBox = null;
20372			this.boundingSphere = null;
20373  
20374			// name
20375  
20376			this.name = source.name;
20377  
20378			// index
20379  
20380			var index = source.index;
20381  
20382			if ( index !== null ) {
20383  
20384				this.setIndex( index.clone() );
20385  
20386			}
20387  
20388			// attributes
20389  
20390			var attributes = source.attributes;
20391  
20392			for ( name in attributes ) {
20393  
20394				var attribute = attributes[ name ];
20395				this.addAttribute( name, attribute.clone() );
20396  
20397			}
20398  
20399			// morph attributes
20400  
20401			var morphAttributes = source.morphAttributes;
20402  
20403			for ( name in morphAttributes ) {
20404  
20405				var array = [];
20406				var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
20407  
20408				for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
20409  
20410					array.push( morphAttribute[ i ].clone() );
20411  
20412				}
20413  
20414				this.morphAttributes[ name ] = array;
20415  
20416			}
20417  
20418			// groups
20419  
20420			var groups = source.groups;
20421  
20422			for ( i = 0, l = groups.length; i < l; i ++ ) {
20423  
20424				var group = groups[ i ];
20425				this.addGroup( group.start, group.count, group.materialIndex );
20426  
20427			}
20428  
20429			// bounding box
20430  
20431			var boundingBox = source.boundingBox;
20432  
20433			if ( boundingBox !== null ) {
20434  
20435				this.boundingBox = boundingBox.clone();
20436  
20437			}
20438  
20439			// bounding sphere
20440  
20441			var boundingSphere = source.boundingSphere;
20442  
20443			if ( boundingSphere !== null ) {
20444  
20445				this.boundingSphere = boundingSphere.clone();
20446  
20447			}
20448  
20449			// draw range
20450  
20451			this.drawRange.start = source.drawRange.start;
20452			this.drawRange.count = source.drawRange.count;
20453  
20454			// user data
20455  
20456			this.userData = source.userData;
20457  
20458			return this;
20459  
20460		},
20461  
20462		dispose: function () {
20463  
20464			this.dispatchEvent( { type: 'dispose' } );
20465  
20466		}
20467  
20468	} );
20469  
20470	/**
20471	 * @author mrdoob / http://mrdoob.com/
20472	 * @author Mugen87 / https://github.com/Mugen87
20473	 */
20474  
20475	// BoxGeometry
20476  
20477	function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
20478  
20479		Geometry.call( this );
20480  
20481		this.type = 'BoxGeometry';
20482  
20483		this.parameters = {
20484			width: width,
20485			height: height,
20486			depth: depth,
20487			widthSegments: widthSegments,
20488			heightSegments: heightSegments,
20489			depthSegments: depthSegments
20490		};
20491  
20492		this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
20493		this.mergeVertices();
20494  
20495	}
20496  
20497	BoxGeometry.prototype = Object.create( Geometry.prototype );
20498	BoxGeometry.prototype.constructor = BoxGeometry;
20499  
20500	// BoxBufferGeometry
20501  
20502	function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
20503  
20504		BufferGeometry.call( this );
20505  
20506		this.type = 'BoxBufferGeometry';
20507  
20508		this.parameters = {
20509			width: width,
20510			height: height,
20511			depth: depth,
20512			widthSegments: widthSegments,
20513			heightSegments: heightSegments,
20514			depthSegments: depthSegments
20515		};
20516  
20517		var scope = this;
20518  
20519		width = width || 1;
20520		height = height || 1;
20521		depth = depth || 1;
20522  
20523		// segments
20524  
20525		widthSegments = Math.floor( widthSegments ) || 1;
20526		heightSegments = Math.floor( heightSegments ) || 1;
20527		depthSegments = Math.floor( depthSegments ) || 1;
20528  
20529		// buffers
20530  
20531		var indices = [];
20532		var vertices = [];
20533		var normals = [];
20534		var uvs = [];
20535  
20536		// helper variables
20537  
20538		var numberOfVertices = 0;
20539		var groupStart = 0;
20540  
20541		// build each side of the box geometry
20542  
20543		buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
20544		buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
20545		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
20546		buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
20547		buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
20548		buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
20549  
20550		// build geometry
20551  
20552		this.setIndex( indices );
20553		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
20554		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
20555		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
20556  
20557		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
20558  
20559			var segmentWidth = width / gridX;
20560			var segmentHeight = height / gridY;
20561  
20562			var widthHalf = width / 2;
20563			var heightHalf = height / 2;
20564			var depthHalf = depth / 2;
20565  
20566			var gridX1 = gridX + 1;
20567			var gridY1 = gridY + 1;
20568  
20569			var vertexCounter = 0;
20570			var groupCount = 0;
20571  
20572			var ix, iy;
20573  
20574			var vector = new Vector3();
20575  
20576			// generate vertices, normals and uvs
20577  
20578			for ( iy = 0; iy < gridY1; iy ++ ) {
20579  
20580				var y = iy * segmentHeight - heightHalf;
20581  
20582				for ( ix = 0; ix < gridX1; ix ++ ) {
20583  
20584					var x = ix * segmentWidth - widthHalf;
20585  
20586					// set values to correct vector component
20587  
20588					vector[ u ] = x * udir;
20589					vector[ v ] = y * vdir;
20590					vector[ w ] = depthHalf;
20591  
20592					// now apply vector to vertex buffer
20593  
20594					vertices.push( vector.x, vector.y, vector.z );
20595  
20596					// set values to correct vector component
20597  
20598					vector[ u ] = 0;
20599					vector[ v ] = 0;
20600					vector[ w ] = depth > 0 ? 1 : - 1;
20601  
20602					// now apply vector to normal buffer
20603  
20604					normals.push( vector.x, vector.y, vector.z );
20605  
20606					// uvs
20607  
20608					uvs.push( ix / gridX );
20609					uvs.push( 1 - ( iy / gridY ) );
20610  
20611					// counters
20612  
20613					vertexCounter += 1;
20614  
20615				}
20616  
20617			}
20618  
20619			// indices
20620  
20621			// 1. you need three indices to draw a single face
20622			// 2. a single segment consists of two faces
20623			// 3. so we need to generate six (2*3) indices per segment
20624  
20625			for ( iy = 0; iy < gridY; iy ++ ) {
20626  
20627				for ( ix = 0; ix < gridX; ix ++ ) {
20628  
20629					var a = numberOfVertices + ix + gridX1 * iy;
20630					var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
20631					var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
20632					var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
20633  
20634					// faces
20635  
20636					indices.push( a, b, d );
20637					indices.push( b, c, d );
20638  
20639					// increase counter
20640  
20641					groupCount += 6;
20642  
20643				}
20644  
20645			}
20646  
20647			// add a group to the geometry. this will ensure multi material support
20648  
20649			scope.addGroup( groupStart, groupCount, materialIndex );
20650  
20651			// calculate new start value for groups
20652  
20653			groupStart += groupCount;
20654  
20655			// update total number of vertices
20656  
20657			numberOfVertices += vertexCounter;
20658  
20659		}
20660  
20661	}
20662  
20663	BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
20664	BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
20665  
20666	/**
20667	 * @author mrdoob / http://mrdoob.com/
20668	 * @author Mugen87 / https://github.com/Mugen87
20669	 */
20670  
20671	// PlaneGeometry
20672  
20673	function PlaneGeometry( width, height, widthSegments, heightSegments ) {
20674  
20675		Geometry.call( this );
20676  
20677		this.type = 'PlaneGeometry';
20678  
20679		this.parameters = {
20680			width: width,
20681			height: height,
20682			widthSegments: widthSegments,
20683			heightSegments: heightSegments
20684		};
20685  
20686		this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
20687		this.mergeVertices();
20688  
20689	}
20690  
20691	PlaneGeometry.prototype = Object.create( Geometry.prototype );
20692	PlaneGeometry.prototype.constructor = PlaneGeometry;
20693  
20694	// PlaneBufferGeometry
20695  
20696	function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
20697  
20698		BufferGeometry.call( this );
20699  
20700		this.type = 'PlaneBufferGeometry';
20701  
20702		this.parameters = {
20703			width: width,
20704			height: height,
20705			widthSegments: widthSegments,
20706			heightSegments: heightSegments
20707		};
20708  
20709		width = width || 1;
20710		height = height || 1;
20711  
20712		var width_half = width / 2;
20713		var height_half = height / 2;
20714  
20715		var gridX = Math.floor( widthSegments ) || 1;
20716		var gridY = Math.floor( heightSegments ) || 1;
20717  
20718		var gridX1 = gridX + 1;
20719		var gridY1 = gridY + 1;
20720  
20721		var segment_width = width / gridX;
20722		var segment_height = height / gridY;
20723  
20724		var ix, iy;
20725  
20726		// buffers
20727  
20728		var indices = [];
20729		var vertices = [];
20730		var normals = [];
20731		var uvs = [];
20732  
20733		// generate vertices, normals and uvs
20734  
20735		for ( iy = 0; iy < gridY1; iy ++ ) {
20736  
20737			var y = iy * segment_height - height_half;
20738  
20739			for ( ix = 0; ix < gridX1; ix ++ ) {
20740  
20741				var x = ix * segment_width - width_half;
20742  
20743				vertices.push( x, - y, 0 );
20744  
20745				normals.push( 0, 0, 1 );
20746  
20747				uvs.push( ix / gridX );
20748				uvs.push( 1 - ( iy / gridY ) );
20749  
20750			}
20751  
20752		}
20753  
20754		// indices
20755  
20756		for ( iy = 0; iy < gridY; iy ++ ) {
20757  
20758			for ( ix = 0; ix < gridX; ix ++ ) {
20759  
20760				var a = ix + gridX1 * iy;
20761				var b = ix + gridX1 * ( iy + 1 );
20762				var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
20763				var d = ( ix + 1 ) + gridX1 * iy;
20764  
20765				// faces
20766  
20767				indices.push( a, b, d );
20768				indices.push( b, c, d );
20769  
20770			}
20771  
20772		}
20773  
20774		// build geometry
20775  
20776		this.setIndex( indices );
20777		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
20778		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
20779		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
20780  
20781	}
20782  
20783	PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
20784	PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
20785  
20786	/**
20787	 * @author mrdoob / http://mrdoob.com/
20788	 * @author alteredq / http://alteredqualia.com/
20789	 */
20790  
20791	var materialId = 0;
20792  
20793	function Material() {
20794  
20795		Object.defineProperty( this, 'id', { value: materialId ++ } );
20796  
20797		this.uuid = _Math.generateUUID();
20798  
20799		this.name = '';
20800		this.type = 'Material';
20801  
20802		this.fog = true;
20803		this.lights = true;
20804  
20805		this.blending = NormalBlending;
20806		this.side = FrontSide;
20807		this.flatShading = false;
20808		this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
20809  
20810		this.opacity = 1;
20811		this.transparent = false;
20812  
20813		this.blendSrc = SrcAlphaFactor;
20814		this.blendDst = OneMinusSrcAlphaFactor;
20815		this.blendEquation = AddEquation;
20816		this.blendSrcAlpha = null;
20817		this.blendDstAlpha = null;
20818		this.blendEquationAlpha = null;
20819  
20820		this.depthFunc = LessEqualDepth;
20821		this.depthTest = true;
20822		this.depthWrite = true;
20823  
20824		this.clippingPlanes = null;
20825		this.clipIntersection = false;
20826		this.clipShadows = false;
20827  
20828		this.shadowSide = null;
20829  
20830		this.colorWrite = true;
20831  
20832		this.precision = null; // override the renderer's default precision for this material
20833  
20834		this.polygonOffset = false;
20835		this.polygonOffsetFactor = 0;
20836		this.polygonOffsetUnits = 0;
20837  
20838		this.dithering = false;
20839  
20840		this.alphaTest = 0;
20841		this.premultipliedAlpha = false;
20842  
20843		this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
20844  
20845		this.visible = true;
20846  
20847		this.userData = {};
20848  
20849		this.needsUpdate = true;
20850  
20851	}
20852  
20853	Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
20854  
20855		constructor: Material,
20856  
20857		isMaterial: true,
20858  
20859		onBeforeCompile: function () {},
20860  
20861		setValues: function ( values ) {
20862  
20863			if ( values === undefined ) return;
20864  
20865			for ( var key in values ) {
20866  
20867				var newValue = values[ key ];
20868  
20869				if ( newValue === undefined ) {
20870  
20871					console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
20872					continue;
20873  
20874				}
20875  
20876				// for backward compatability if shading is set in the constructor
20877				if ( key === 'shading' ) {
20878  
20879					console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
20880					this.flatShading = ( newValue === FlatShading ) ? true : false;
20881					continue;
20882  
20883				}
20884  
20885				var currentValue = this[ key ];
20886  
20887				if ( currentValue === undefined ) {
20888  
20889					console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
20890					continue;
20891  
20892				}
20893  
20894				if ( currentValue && currentValue.isColor ) {
20895  
20896					currentValue.set( newValue );
20897  
20898				} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
20899  
20900					currentValue.copy( newValue );
20901  
20902				} else if ( key === 'overdraw' ) {
20903  
20904					// ensure overdraw is backwards-compatible with legacy boolean type
20905					this[ key ] = Number( newValue );
20906  
20907				} else {
20908  
20909					this[ key ] = newValue;
20910  
20911				}
20912  
20913			}
20914  
20915		},
20916  
20917		toJSON: function ( meta ) {
20918  
20919			var isRoot = ( meta === undefined || typeof meta === 'string' );
20920  
20921			if ( isRoot ) {
20922  
20923				meta = {
20924					textures: {},
20925					images: {}
20926				};
20927  
20928			}
20929  
20930			var data = {
20931				metadata: {
20932					version: 4.5,
20933					type: 'Material',
20934					generator: 'Material.toJSON'
20935				}
20936			};
20937  
20938			// standard Material serialization
20939			data.uuid = this.uuid;
20940			data.type = this.type;
20941  
20942			if ( this.name !== '' ) data.name = this.name;
20943  
20944			if ( this.color && this.color.isColor ) data.color = this.color.getHex();
20945  
20946			if ( this.roughness !== undefined ) data.roughness = this.roughness;
20947			if ( this.metalness !== undefined ) data.metalness = this.metalness;
20948  
20949			if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
20950			if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
20951  
20952			if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
20953			if ( this.shininess !== undefined ) data.shininess = this.shininess;
20954			if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
20955			if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness;
20956  
20957			if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
20958			if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
20959			if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
20960  
20961			if ( this.aoMap && this.aoMap.isTexture ) {
20962  
20963				data.aoMap = this.aoMap.toJSON( meta ).uuid;
20964				data.aoMapIntensity = this.aoMapIntensity;
20965  
20966			}
20967  
20968			if ( this.bumpMap && this.bumpMap.isTexture ) {
20969  
20970				data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
20971				data.bumpScale = this.bumpScale;
20972  
20973			}
20974  
20975			if ( this.normalMap && this.normalMap.isTexture ) {
20976  
20977				data.normalMap = this.normalMap.toJSON( meta ).uuid;
20978				data.normalScale = this.normalScale.toArray();
20979  
20980			}
20981  
20982			if ( this.displacementMap && this.displacementMap.isTexture ) {
20983  
20984				data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
20985				data.displacementScale = this.displacementScale;
20986				data.displacementBias = this.displacementBias;
20987  
20988			}
20989  
20990			if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
20991			if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
20992  
20993			if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
20994			if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
20995  
20996			if ( this.envMap && this.envMap.isTexture ) {
20997  
20998				data.envMap = this.envMap.toJSON( meta ).uuid;
20999				data.reflectivity = this.reflectivity; // Scale behind envMap
21000  
21001			}
21002  
21003			if ( this.gradientMap && this.gradientMap.isTexture ) {
21004  
21005				data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
21006  
21007			}
21008  
21009			if ( this.size !== undefined ) data.size = this.size;
21010			if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
21011  
21012			if ( this.blending !== NormalBlending ) data.blending = this.blending;
21013			if ( this.flatShading === true ) data.flatShading = this.flatShading;
21014			if ( this.side !== FrontSide ) data.side = this.side;
21015			if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
21016  
21017			if ( this.opacity < 1 ) data.opacity = this.opacity;
21018			if ( this.transparent === true ) data.transparent = this.transparent;
21019  
21020			data.depthFunc = this.depthFunc;
21021			data.depthTest = this.depthTest;
21022			data.depthWrite = this.depthWrite;
21023  
21024			// rotation (SpriteMaterial)
21025			if ( this.rotation !== 0 ) data.rotation = this.rotation;
21026  
21027			if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
21028			if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
21029			if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
21030			if ( this.scale !== undefined ) data.scale = this.scale;
21031  
21032			if ( this.dithering === true ) data.dithering = true;
21033  
21034			if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
21035			if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
21036  
21037			if ( this.wireframe === true ) data.wireframe = this.wireframe;
21038			if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
21039			if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
21040			if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
21041  
21042			if ( this.morphTargets === true ) data.morphTargets = true;
21043			if ( this.skinning === true ) data.skinning = true;
21044  
21045			if ( this.visible === false ) data.visible = false;
21046			if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
21047  
21048			// TODO: Copied from Object3D.toJSON
21049  
21050			function extractFromCache( cache ) {
21051  
21052				var values = [];
21053  
21054				for ( var key in cache ) {
21055  
21056					var data = cache[ key ];
21057					delete data.metadata;
21058					values.push( data );
21059  
21060				}
21061  
21062				return values;
21063  
21064			}
21065  
21066			if ( isRoot ) {
21067  
21068				var textures = extractFromCache( meta.textures );
21069				var images = extractFromCache( meta.images );
21070  
21071				if ( textures.length > 0 ) data.textures = textures;
21072				if ( images.length > 0 ) data.images = images;
21073  
21074			}
21075  
21076			return data;
21077  
21078		},
21079  
21080		clone: function () {
21081  
21082			return new this.constructor().copy( this );
21083  
21084		},
21085  
21086		copy: function ( source ) {
21087  
21088			this.name = source.name;
21089  
21090			this.fog = source.fog;
21091			this.lights = source.lights;
21092  
21093			this.blending = source.blending;
21094			this.side = source.side;
21095			this.flatShading = source.flatShading;
21096			this.vertexColors = source.vertexColors;
21097  
21098			this.opacity = source.opacity;
21099			this.transparent = source.transparent;
21100  
21101			this.blendSrc = source.blendSrc;
21102			this.blendDst = source.blendDst;
21103			this.blendEquation = source.blendEquation;
21104			this.blendSrcAlpha = source.blendSrcAlpha;
21105			this.blendDstAlpha = source.blendDstAlpha;
21106			this.blendEquationAlpha = source.blendEquationAlpha;
21107  
21108			this.depthFunc = source.depthFunc;
21109			this.depthTest = source.depthTest;
21110			this.depthWrite = source.depthWrite;
21111  
21112			this.colorWrite = source.colorWrite;
21113  
21114			this.precision = source.precision;
21115  
21116			this.polygonOffset = source.polygonOffset;
21117			this.polygonOffsetFactor = source.polygonOffsetFactor;
21118			this.polygonOffsetUnits = source.polygonOffsetUnits;
21119  
21120			this.dithering = source.dithering;
21121  
21122			this.alphaTest = source.alphaTest;
21123			this.premultipliedAlpha = source.premultipliedAlpha;
21124  
21125			this.overdraw = source.overdraw;
21126  
21127			this.visible = source.visible;
21128			this.userData = JSON.parse( JSON.stringify( source.userData ) );
21129  
21130			this.clipShadows = source.clipShadows;
21131			this.clipIntersection = source.clipIntersection;
21132  
21133			var srcPlanes = source.clippingPlanes,
21134				dstPlanes = null;
21135  
21136			if ( srcPlanes !== null ) {
21137  
21138				var n = srcPlanes.length;
21139				dstPlanes = new Array( n );
21140  
21141				for ( var i = 0; i !== n; ++ i )
21142					dstPlanes[ i ] = srcPlanes[ i ].clone();
21143  
21144			}
21145  
21146			this.clippingPlanes = dstPlanes;
21147  
21148			this.shadowSide = source.shadowSide;
21149  
21150			return this;
21151  
21152		},
21153  
21154		dispose: function () {
21155  
21156			this.dispatchEvent( { type: 'dispose' } );
21157  
21158		}
21159  
21160	} );
21161  
21162	/**
21163	 * @author mrdoob / http://mrdoob.com/
21164	 * @author alteredq / http://alteredqualia.com/
21165	 *
21166	 * parameters = {
21167	 *  color: <hex>,
21168	 *  opacity: <float>,
21169	 *  map: new THREE.Texture( <Image> ),
21170	 *
21171	 *  lightMap: new THREE.Texture( <Image> ),
21172	 *  lightMapIntensity: <float>
21173	 *
21174	 *  aoMap: new THREE.Texture( <Image> ),
21175	 *  aoMapIntensity: <float>
21176	 *
21177	 *  specularMap: new THREE.Texture( <Image> ),
21178	 *
21179	 *  alphaMap: new THREE.Texture( <Image> ),
21180	 *
21181	 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
21182	 *  combine: THREE.Multiply,
21183	 *  reflectivity: <float>,
21184	 *  refractionRatio: <float>,
21185	 *
21186	 *  depthTest: <bool>,
21187	 *  depthWrite: <bool>,
21188	 *
21189	 *  wireframe: <boolean>,
21190	 *  wireframeLinewidth: <float>,
21191	 *
21192	 *  skinning: <bool>,
21193	 *  morphTargets: <bool>
21194	 * }
21195	 */
21196  
21197	function MeshBasicMaterial( parameters ) {
21198  
21199		Material.call( this );
21200  
21201		this.type = 'MeshBasicMaterial';
21202  
21203		this.color = new Color( 0xffffff ); // emissive
21204  
21205		this.map = null;
21206  
21207		this.lightMap = null;
21208		this.lightMapIntensity = 1.0;
21209  
21210		this.aoMap = null;
21211		this.aoMapIntensity = 1.0;
21212  
21213		this.specularMap = null;
21214  
21215		this.alphaMap = null;
21216  
21217		this.envMap = null;
21218		this.combine = MultiplyOperation;
21219		this.reflectivity = 1;
21220		this.refractionRatio = 0.98;
21221  
21222		this.wireframe = false;
21223		this.wireframeLinewidth = 1;
21224		this.wireframeLinecap = 'round';
21225		this.wireframeLinejoin = 'round';
21226  
21227		this.skinning = false;
21228		this.morphTargets = false;
21229  
21230		this.lights = false;
21231  
21232		this.setValues( parameters );
21233  
21234	}
21235  
21236	MeshBasicMaterial.prototype = Object.create( Material.prototype );
21237	MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
21238  
21239	MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
21240  
21241	MeshBasicMaterial.prototype.copy = function ( source ) {
21242  
21243		Material.prototype.copy.call( this, source );
21244  
21245		this.color.copy( source.color );
21246  
21247		this.map = source.map;
21248  
21249		this.lightMap = source.lightMap;
21250		this.lightMapIntensity = source.lightMapIntensity;
21251  
21252		this.aoMap = source.aoMap;
21253		this.aoMapIntensity = source.aoMapIntensity;
21254  
21255		this.specularMap = source.specularMap;
21256  
21257		this.alphaMap = source.alphaMap;
21258  
21259		this.envMap = source.envMap;
21260		this.combine = source.combine;
21261		this.reflectivity = source.reflectivity;
21262		this.refractionRatio = source.refractionRatio;
21263  
21264		this.wireframe = source.wireframe;
21265		this.wireframeLinewidth = source.wireframeLinewidth;
21266		this.wireframeLinecap = source.wireframeLinecap;
21267		this.wireframeLinejoin = source.wireframeLinejoin;
21268  
21269		this.skinning = source.skinning;
21270		this.morphTargets = source.morphTargets;
21271  
21272		return this;
21273  
21274	};
21275  
21276	/**
21277	 * @author alteredq / http://alteredqualia.com/
21278	 *
21279	 * parameters = {
21280	 *  defines: { "label" : "value" },
21281	 *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
21282	 *
21283	 *  fragmentShader: <string>,
21284	 *  vertexShader: <string>,
21285	 *
21286	 *  wireframe: <boolean>,
21287	 *  wireframeLinewidth: <float>,
21288	 *
21289	 *  lights: <bool>,
21290	 *
21291	 *  skinning: <bool>,
21292	 *  morphTargets: <bool>,
21293	 *  morphNormals: <bool>
21294	 * }
21295	 */
21296  
21297	function ShaderMaterial( parameters ) {
21298  
21299		Material.call( this );
21300  
21301		this.type = 'ShaderMaterial';
21302  
21303		this.defines = {};
21304		this.uniforms = {};
21305  
21306		this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
21307		this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
21308  
21309		this.linewidth = 1;
21310  
21311		this.wireframe = false;
21312		this.wireframeLinewidth = 1;
21313  
21314		this.fog = false; // set to use scene fog
21315		this.lights = false; // set to use scene lights
21316		this.clipping = false; // set to use user-defined clipping planes
21317  
21318		this.skinning = false; // set to use skinning attribute streams
21319		this.morphTargets = false; // set to use morph targets
21320		this.morphNormals = false; // set to use morph normals
21321  
21322		this.extensions = {
21323			derivatives: false, // set to use derivatives
21324			fragDepth: false, // set to use fragment depth values
21325			drawBuffers: false, // set to use draw buffers
21326			shaderTextureLOD: false // set to use shader texture LOD
21327		};
21328  
21329		// When rendered geometry doesn't include these attributes but the material does,
21330		// use these default values in WebGL. This avoids errors when buffer data is missing.
21331		this.defaultAttributeValues = {
21332			'color': [ 1, 1, 1 ],
21333			'uv': [ 0, 0 ],
21334			'uv2': [ 0, 0 ]
21335		};
21336  
21337		this.index0AttributeName = undefined;
21338		this.uniformsNeedUpdate = false;
21339  
21340		if ( parameters !== undefined ) {
21341  
21342			if ( parameters.attributes !== undefined ) {
21343  
21344				console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
21345  
21346			}
21347  
21348			this.setValues( parameters );
21349  
21350		}
21351  
21352	}
21353  
21354	ShaderMaterial.prototype = Object.create( Material.prototype );
21355	ShaderMaterial.prototype.constructor = ShaderMaterial;
21356  
21357	ShaderMaterial.prototype.isShaderMaterial = true;
21358  
21359	ShaderMaterial.prototype.copy = function ( source ) {
21360  
21361		Material.prototype.copy.call( this, source );
21362  
21363		this.fragmentShader = source.fragmentShader;
21364		this.vertexShader = source.vertexShader;
21365  
21366		this.uniforms = UniformsUtils.clone( source.uniforms );
21367  
21368		this.defines = Object.assign( {}, source.defines );
21369  
21370		this.wireframe = source.wireframe;
21371		this.wireframeLinewidth = source.wireframeLinewidth;
21372  
21373		this.lights = source.lights;
21374		this.clipping = source.clipping;
21375  
21376		this.skinning = source.skinning;
21377  
21378		this.morphTargets = source.morphTargets;
21379		this.morphNormals = source.morphNormals;
21380  
21381		this.extensions = source.extensions;
21382  
21383		return this;
21384  
21385	};
21386  
21387	ShaderMaterial.prototype.toJSON = function ( meta ) {
21388  
21389		var data = Material.prototype.toJSON.call( this, meta );
21390  
21391		data.uniforms = this.uniforms;
21392		data.vertexShader = this.vertexShader;
21393		data.fragmentShader = this.fragmentShader;
21394  
21395		return data;
21396  
21397	};
21398  
21399	/**
21400	 * @author bhouston / http://clara.io
21401	 */
21402  
21403	function Ray( origin, direction ) {
21404  
21405		this.origin = ( origin !== undefined ) ? origin : new Vector3();
21406		this.direction = ( direction !== undefined ) ? direction : new Vector3();
21407  
21408	}
21409  
21410	Object.assign( Ray.prototype, {
21411  
21412		set: function ( origin, direction ) {
21413  
21414			this.origin.copy( origin );
21415			this.direction.copy( direction );
21416  
21417			return this;
21418  
21419		},
21420  
21421		clone: function () {
21422  
21423			return new this.constructor().copy( this );
21424  
21425		},
21426  
21427		copy: function ( ray ) {
21428  
21429			this.origin.copy( ray.origin );
21430			this.direction.copy( ray.direction );
21431  
21432			return this;
21433  
21434		},
21435  
21436		at: function ( t, target ) {
21437  
21438			if ( target === undefined ) {
21439  
21440				console.warn( 'THREE.Ray: .at() target is now required' );
21441				target = new Vector3();
21442  
21443			}
21444  
21445			return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
21446  
21447		},
21448  
21449		lookAt: function ( v ) {
21450  
21451			this.direction.copy( v ).sub( this.origin ).normalize();
21452  
21453			return this;
21454  
21455		},
21456  
21457		recast: function () {
21458  
21459			var v1 = new Vector3();
21460  
21461			return function recast( t ) {
21462  
21463				this.origin.copy( this.at( t, v1 ) );
21464  
21465				return this;
21466  
21467			};
21468  
21469		}(),
21470  
21471		closestPointToPoint: function ( point, target ) {
21472  
21473			if ( target === undefined ) {
21474  
21475				console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
21476				target = new Vector3();
21477  
21478			}
21479  
21480			target.subVectors( point, this.origin );
21481  
21482			var directionDistance = target.dot( this.direction );
21483  
21484			if ( directionDistance < 0 ) {
21485  
21486				return target.copy( this.origin );
21487  
21488			}
21489  
21490			return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
21491  
21492		},
21493  
21494		distanceToPoint: function ( point ) {
21495  
21496			return Math.sqrt( this.distanceSqToPoint( point ) );
21497  
21498		},
21499  
21500		distanceSqToPoint: function () {
21501  
21502			var v1 = new Vector3();
21503  
21504			return function distanceSqToPoint( point ) {
21505  
21506				var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
21507  
21508				// point behind the ray
21509  
21510				if ( directionDistance < 0 ) {
21511  
21512					return this.origin.distanceToSquared( point );
21513  
21514				}
21515  
21516				v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
21517  
21518				return v1.distanceToSquared( point );
21519  
21520			};
21521  
21522		}(),
21523  
21524		distanceSqToSegment: function () {
21525  
21526			var segCenter = new Vector3();
21527			var segDir = new Vector3();
21528			var diff = new Vector3();
21529  
21530			return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
21531  
21532				// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
21533				// It returns the min distance between the ray and the segment
21534				// defined by v0 and v1
21535				// It can also set two optional targets :
21536				// - The closest point on the ray
21537				// - The closest point on the segment
21538  
21539				segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
21540				segDir.copy( v1 ).sub( v0 ).normalize();
21541				diff.copy( this.origin ).sub( segCenter );
21542  
21543				var segExtent = v0.distanceTo( v1 ) * 0.5;
21544				var a01 = - this.direction.dot( segDir );
21545				var b0 = diff.dot( this.direction );
21546				var b1 = - diff.dot( segDir );
21547				var c = diff.lengthSq();
21548				var det = Math.abs( 1 - a01 * a01 );
21549				var s0, s1, sqrDist, extDet;
21550  
21551				if ( det > 0 ) {
21552  
21553					// The ray and segment are not parallel.
21554  
21555					s0 = a01 * b1 - b0;
21556					s1 = a01 * b0 - b1;
21557					extDet = segExtent * det;
21558  
21559					if ( s0 >= 0 ) {
21560  
21561						if ( s1 >= - extDet ) {
21562  
21563							if ( s1 <= extDet ) {
21564  
21565								// region 0
21566								// Minimum at interior points of ray and segment.
21567  
21568								var invDet = 1 / det;
21569								s0 *= invDet;
21570								s1 *= invDet;
21571								sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
21572  
21573							} else {
21574  
21575								// region 1
21576  
21577								s1 = segExtent;
21578								s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
21579								sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
21580  
21581							}
21582  
21583						} else {
21584  
21585							// region 5
21586  
21587							s1 = - segExtent;
21588							s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
21589							sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
21590  
21591						}
21592  
21593					} else {
21594  
21595						if ( s1 <= - extDet ) {
21596  
21597							// region 4
21598  
21599							s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
21600							s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
21601							sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
21602  
21603						} else if ( s1 <= extDet ) {
21604  
21605							// region 3
21606  
vendor: 4,199 bytes, lines 21607-21796
21607							s0 = 0;
21608							s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
21609							sqrDist = s1 * ( s1 + 2 * b1 ) + c;
21610  
21611						} else {
21612  
21613							// region 2
21614  
21615							s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
21616							s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
21617							sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
21618  
21619						}
21620  
21621					}
21622  
21623				} else {
21624  
21625					// Ray and segment are parallel.
21626  
21627					s1 = ( a01 > 0 ) ? - segExtent : segExtent;
21628					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
21629					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
21630  
21631				}
21632  
21633				if ( optionalPointOnRay ) {
21634  
21635					optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
21636  
21637				}
21638  
21639				if ( optionalPointOnSegment ) {
21640  
21641					optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
21642  
21643				}
21644  
21645				return sqrDist;
21646  
21647			};
21648  
21649		}(),
21650  
21651		intersectSphere: function () {
21652  
21653			var v1 = new Vector3();
21654  
21655			return function intersectSphere( sphere, target ) {
21656  
21657				v1.subVectors( sphere.center, this.origin );
21658				var tca = v1.dot( this.direction );
21659				var d2 = v1.dot( v1 ) - tca * tca;
21660				var radius2 = sphere.radius * sphere.radius;
21661  
21662				if ( d2 > radius2 ) return null;
21663  
21664				var thc = Math.sqrt( radius2 - d2 );
21665  
21666				// t0 = first intersect point - entrance on front of sphere
21667				var t0 = tca - thc;
21668  
21669				// t1 = second intersect point - exit point on back of sphere
21670				var t1 = tca + thc;
21671  
21672				// test to see if both t0 and t1 are behind the ray - if so, return null
21673				if ( t0 < 0 && t1 < 0 ) return null;
21674  
21675				// test to see if t0 is behind the ray:
21676				// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
21677				// in order to always return an intersect point that is in front of the ray.
21678				if ( t0 < 0 ) return this.at( t1, target );
21679  
21680				// else t0 is in front of the ray, so return the first collision point scaled by t0
21681				return this.at( t0, target );
21682  
21683			};
21684  
21685		}(),
21686  
21687		intersectsSphere: function ( sphere ) {
21688  
21689			return this.distanceToPoint( sphere.center ) <= sphere.radius;
21690  
21691		},
21692  
21693		distanceToPlane: function ( plane ) {
21694  
21695			var denominator = plane.normal.dot( this.direction );
21696  
21697			if ( denominator === 0 ) {
21698  
21699				// line is coplanar, return origin
21700				if ( plane.distanceToPoint( this.origin ) === 0 ) {
21701  
21702					return 0;
21703  
21704				}
21705  
21706				// Null is preferable to undefined since undefined means.... it is undefined
21707  
21708				return null;
21709  
21710			}
21711  
21712			var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
21713  
21714			// Return if the ray never intersects the plane
21715  
21716			return t >= 0 ? t : null;
21717  
21718		},
21719  
21720		intersectPlane: function ( plane, target ) {
21721  
21722			var t = this.distanceToPlane( plane );
21723  
21724			if ( t === null ) {
21725  
21726				return null;
21727  
21728			}
21729  
21730			return this.at( t, target );
21731  
21732		},
21733  
21734		intersectsPlane: function ( plane ) {
21735  
21736			// check if the ray lies on the plane first
21737  
21738			var distToPoint = plane.distanceToPoint( this.origin );
21739  
21740			if ( distToPoint === 0 ) {
21741  
21742				return true;
21743  
21744			}
21745  
21746			var denominator = plane.normal.dot( this.direction );
21747  
21748			if ( denominator * distToPoint < 0 ) {
21749  
21750				return true;
21751  
21752			}
21753  
21754			// ray origin is behind the plane (and is pointing behind it)
21755  
21756			return false;
21757  
21758		},
21759  
21760		intersectBox: function ( box, target ) {
21761  
21762			var tmin, tmax, tymin, tymax, tzmin, tzmax;
21763  
21764			var invdirx = 1 / this.direction.x,
21765				invdiry = 1 / this.direction.y,
21766				invdirz = 1 / this.direction.z;
21767  
21768			var origin = this.origin;
21769  
21770			if ( invdirx >= 0 ) {
21771  
21772				tmin = ( box.min.x - origin.x ) * invdirx;
21773				tmax = ( box.max.x - origin.x ) * invdirx;
21774  
21775			} else {
21776  
21777				tmin = ( box.max.x - origin.x ) * invdirx;
21778				tmax = ( box.min.x - origin.x ) * invdirx;
21779  
21780			}
21781  
21782			if ( invdiry >= 0 ) {
21783  
21784				tymin = ( box.min.y - origin.y ) * invdiry;
21785				tymax = ( box.max.y - origin.y ) * invdiry;
21786  
21787			} else {
21788  
21789				tymin = ( box.max.y - origin.y ) * invdiry;
21790				tymax = ( box.min.y - origin.y ) * invdiry;
21791  
21792			}
21793  
21794			if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
21795  
21796			// These lines also handle the case where tmin or tmax is NaN
vendor: 7,806 bytes, lines 21797-22174
21797			// (result of 0 * Infinity). x !== x returns true if x is NaN
21798  
21799			if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
21800  
21801			if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
21802  
21803			if ( invdirz >= 0 ) {
21804  
21805				tzmin = ( box.min.z - origin.z ) * invdirz;
21806				tzmax = ( box.max.z - origin.z ) * invdirz;
21807  
21808			} else {
21809  
21810				tzmin = ( box.max.z - origin.z ) * invdirz;
21811				tzmax = ( box.min.z - origin.z ) * invdirz;
21812  
21813			}
21814  
21815			if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
21816  
21817			if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
21818  
21819			if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
21820  
21821			//return point closest to the ray (positive side)
21822  
21823			if ( tmax < 0 ) return null;
21824  
21825			return this.at( tmin >= 0 ? tmin : tmax, target );
21826  
21827		},
21828  
21829		intersectsBox: ( function () {
21830  
21831			var v = new Vector3();
21832  
21833			return function intersectsBox( box ) {
21834  
21835				return this.intersectBox( box, v ) !== null;
21836  
21837			};
21838  
21839		} )(),
21840  
21841		intersectTriangle: function () {
21842  
21843			// Compute the offset origin, edges, and normal.
21844			var diff = new Vector3();
21845			var edge1 = new Vector3();
21846			var edge2 = new Vector3();
21847			var normal = new Vector3();
21848  
21849			return function intersectTriangle( a, b, c, backfaceCulling, target ) {
21850  
21851				// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
21852  
21853				edge1.subVectors( b, a );
21854				edge2.subVectors( c, a );
21855				normal.crossVectors( edge1, edge2 );
21856  
21857				// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
21858				// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
21859				//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
21860				//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
21861				//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
21862				var DdN = this.direction.dot( normal );
21863				var sign;
21864  
21865				if ( DdN > 0 ) {
21866  
21867					if ( backfaceCulling ) return null;
21868					sign = 1;
21869  
21870				} else if ( DdN < 0 ) {
21871  
21872					sign = - 1;
21873					DdN = - DdN;
21874  
21875				} else {
21876  
21877					return null;
21878  
21879				}
21880  
21881				diff.subVectors( this.origin, a );
21882				var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
21883  
21884				// b1 < 0, no intersection
21885				if ( DdQxE2 < 0 ) {
21886  
21887					return null;
21888  
21889				}
21890  
21891				var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
21892  
21893				// b2 < 0, no intersection
21894				if ( DdE1xQ < 0 ) {
21895  
21896					return null;
21897  
21898				}
21899  
21900				// b1+b2 > 1, no intersection
21901				if ( DdQxE2 + DdE1xQ > DdN ) {
21902  
21903					return null;
21904  
21905				}
21906  
21907				// Line intersects triangle, check if ray does.
21908				var QdN = - sign * diff.dot( normal );
21909  
21910				// t < 0, no intersection
21911				if ( QdN < 0 ) {
21912  
21913					return null;
21914  
21915				}
21916  
21917				// Ray intersects triangle.
21918				return this.at( QdN / DdN, target );
21919  
21920			};
21921  
21922		}(),
21923  
21924		applyMatrix4: function ( matrix4 ) {
21925  
21926			this.origin.applyMatrix4( matrix4 );
21927			this.direction.transformDirection( matrix4 );
21928  
21929			return this;
21930  
21931		},
21932  
21933		equals: function ( ray ) {
21934  
21935			return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
21936  
21937		}
21938  
21939	} );
21940  
21941	/**
21942	 * @author bhouston / http://clara.io
21943	 */
21944  
21945	function Line3( start, end ) {
21946  
21947		this.start = ( start !== undefined ) ? start : new Vector3();
21948		this.end = ( end !== undefined ) ? end : new Vector3();
21949  
21950	}
21951  
21952	Object.assign( Line3.prototype, {
21953  
21954		set: function ( start, end ) {
21955  
21956			this.start.copy( start );
21957			this.end.copy( end );
21958  
21959			return this;
21960  
21961		},
21962  
21963		clone: function () {
21964  
21965			return new this.constructor().copy( this );
21966  
21967		},
21968  
21969		copy: function ( line ) {
21970  
21971			this.start.copy( line.start );
21972			this.end.copy( line.end );
21973  
21974			return this;
21975  
21976		},
21977  
21978		getCenter: function ( target ) {
21979  
21980			if ( target === undefined ) {
21981  
21982				console.warn( 'THREE.Line3: .getCenter() target is now required' );
21983				target = new Vector3();
21984  
21985			}
21986  
21987			return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
21988  
21989		},
21990  
21991		delta: function ( target ) {
21992  
21993			if ( target === undefined ) {
21994  
21995				console.warn( 'THREE.Line3: .delta() target is now required' );
21996				target = new Vector3();
21997  
21998			}
21999  
22000			return target.subVectors( this.end, this.start );
22001  
22002		},
22003  
22004		distanceSq: function () {
22005  
22006			return this.start.distanceToSquared( this.end );
22007  
22008		},
22009  
22010		distance: function () {
22011  
22012			return this.start.distanceTo( this.end );
22013  
22014		},
22015  
22016		at: function ( t, target ) {
22017  
22018			if ( target === undefined ) {
22019  
22020				console.warn( 'THREE.Line3: .at() target is now required' );
22021				target = new Vector3();
22022  
22023			}
22024  
22025			return this.delta( target ).multiplyScalar( t ).add( this.start );
22026  
22027		},
22028  
22029		closestPointToPointParameter: function () {
22030  
22031			var startP = new Vector3();
22032			var startEnd = new Vector3();
22033  
22034			return function closestPointToPointParameter( point, clampToLine ) {
22035  
22036				startP.subVectors( point, this.start );
22037				startEnd.subVectors( this.end, this.start );
22038  
22039				var startEnd2 = startEnd.dot( startEnd );
22040				var startEnd_startP = startEnd.dot( startP );
22041  
22042				var t = startEnd_startP / startEnd2;
22043  
22044				if ( clampToLine ) {
22045  
22046					t = _Math.clamp( t, 0, 1 );
22047  
22048				}
22049  
22050				return t;
22051  
22052			};
22053  
22054		}(),
22055  
22056		closestPointToPoint: function ( point, clampToLine, target ) {
22057  
22058			var t = this.closestPointToPointParameter( point, clampToLine );
22059  
22060			if ( target === undefined ) {
22061  
22062				console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
22063				target = new Vector3();
22064  
22065			}
22066  
22067			return this.delta( target ).multiplyScalar( t ).add( this.start );
22068  
22069		},
22070  
22071		applyMatrix4: function ( matrix ) {
22072  
22073			this.start.applyMatrix4( matrix );
22074			this.end.applyMatrix4( matrix );
22075  
22076			return this;
22077  
22078		},
22079  
22080		equals: function ( line ) {
22081  
22082			return line.start.equals( this.start ) && line.end.equals( this.end );
22083  
22084		}
22085  
22086	} );
22087  
22088	/**
22089	 * @author bhouston / http://clara.io
22090	 * @author mrdoob / http://mrdoob.com/
22091	 */
22092  
22093	function Triangle( a, b, c ) {
22094  
22095		this.a = ( a !== undefined ) ? a : new Vector3();
22096		this.b = ( b !== undefined ) ? b : new Vector3();
22097		this.c = ( c !== undefined ) ? c : new Vector3();
22098  
22099	}
22100  
22101	Object.assign( Triangle, {
22102  
22103		getNormal: function () {
22104  
22105			var v0 = new Vector3();
22106  
22107			return function getNormal( a, b, c, target ) {
22108  
22109				if ( target === undefined ) {
22110  
22111					console.warn( 'THREE.Triangle: .getNormal() target is now required' );
22112					target = new Vector3();
22113  
22114				}
22115  
22116				target.subVectors( c, b );
22117				v0.subVectors( a, b );
22118				target.cross( v0 );
22119  
22120				var targetLengthSq = target.lengthSq();
22121				if ( targetLengthSq > 0 ) {
22122  
22123					return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
22124  
22125				}
22126  
22127				return target.set( 0, 0, 0 );
22128  
22129			};
22130  
22131		}(),
22132  
22133		// static/instance method to calculate barycentric coordinates
22134		// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
22135		getBarycoord: function () {
22136  
22137			var v0 = new Vector3();
22138			var v1 = new Vector3();
22139			var v2 = new Vector3();
22140  
22141			return function getBarycoord( point, a, b, c, target ) {
22142  
22143				v0.subVectors( c, a );
22144				v1.subVectors( b, a );
22145				v2.subVectors( point, a );
22146  
22147				var dot00 = v0.dot( v0 );
22148				var dot01 = v0.dot( v1 );
22149				var dot02 = v0.dot( v2 );
22150				var dot11 = v1.dot( v1 );
22151				var dot12 = v1.dot( v2 );
22152  
22153				var denom = ( dot00 * dot11 - dot01 * dot01 );
22154  
22155				if ( target === undefined ) {
22156  
22157					console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
22158					target = new Vector3();
22159  
22160				}
22161  
22162				// collinear or singular triangle
22163				if ( denom === 0 ) {
22164  
22165					// arbitrary location outside of triangle?
22166					// not sure if this is the best idea, maybe should be returning undefined
22167					return target.set( - 2, - 1, - 1 );
22168  
22169				}
22170  
22171				var invDenom = 1 / denom;
22172				var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
22173				var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
22174  
22175				// barycentric coordinates must always sum to 1
22176				return target.set( 1 - u - v, v, u );
22177  
22178			};
22179  
22180		}(),
22181  
22182		containsPoint: function () {
22183  
22184			var v1 = new Vector3();
22185  
22186			return function containsPoint( point, a, b, c ) {
22187  
22188				Triangle.getBarycoord( point, a, b, c, v1 );
22189  
22190				return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
22191  
22192			};
22193  
22194		}()
22195  
22196	} );
22197  
22198	Object.assign( Triangle.prototype, {
22199  
22200		set: function ( a, b, c ) {
22201  
22202			this.a.copy( a );
22203			this.b.copy( b );
22204			this.c.copy( c );
22205  
22206			return this;
22207  
22208		},
22209  
22210		setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
22211  
22212			this.a.copy( points[ i0 ] );
22213			this.b.copy( points[ i1 ] );
22214			this.c.copy( points[ i2 ] );
22215  
22216			return this;
22217  
22218		},
22219  
22220		clone: function () {
22221  
22222			return new this.constructor().copy( this );
22223  
22224		},
22225  
22226		copy: function ( triangle ) {
22227  
22228			this.a.copy( triangle.a );
22229			this.b.copy( triangle.b );
22230			this.c.copy( triangle.c );
22231  
22232			return this;
22233  
22234		},
22235  
22236		getArea: function () {
22237  
22238			var v0 = new Vector3();
22239			var v1 = new Vector3();
22240  
22241			return function getArea() {
22242  
22243				v0.subVectors( this.c, this.b );
22244				v1.subVectors( this.a, this.b );
22245  
22246				return v0.cross( v1 ).length() * 0.5;
22247  
22248			};
22249  
22250		}(),
22251  
22252		getMidpoint: function ( target ) {
22253  
22254			if ( target === undefined ) {
22255  
22256				console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
22257				target = new Vector3();
22258  
22259			}
22260  
22261			return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
22262  
22263		},
22264  
22265		getNormal: function ( target ) {
22266  
22267			return Triangle.getNormal( this.a, this.b, this.c, target );
22268  
22269		},
22270  
22271		getPlane: function ( target ) {
22272  
22273			if ( target === undefined ) {
22274  
22275				console.warn( 'THREE.Triangle: .getPlane() target is now required' );
22276				target = new Vector3();
22277  
22278			}
22279  
22280			return target.setFromCoplanarPoints( this.a, this.b, this.c );
22281  
22282		},
22283  
22284		getBarycoord: function ( point, target ) {
22285  
22286			return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
22287  
22288		},
22289  
22290		containsPoint: function ( point ) {
22291  
22292			return Triangle.containsPoint( point, this.a, this.b, this.c );
22293  
22294		},
22295  
22296		intersectsBox: function ( box ) {
22297  
22298			return box.intersectsTriangle( this );
22299  
22300		},
22301  
22302		closestPointToPoint: function () {
22303  
22304			var plane = new Plane();
22305			var edgeList = [ new Line3(), new Line3(), new Line3() ];
22306			var projectedPoint = new Vector3();
22307			var closestPoint = new Vector3();
22308  
22309			return function closestPointToPoint( point, target ) {
22310  
22311				if ( target === undefined ) {
22312  
22313					console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
22314					target = new Vector3();
22315  
22316				}
22317  
22318				var minDistance = Infinity;
22319  
22320				// project the point onto the plane of the triangle
22321  
22322				plane.setFromCoplanarPoints( this.a, this.b, this.c );
22323				plane.projectPoint( point, projectedPoint );
22324  
22325				// check if the projection lies within the triangle
22326  
22327				if ( this.containsPoint( projectedPoint ) === true ) {
22328  
22329					// if so, this is the closest point
22330  
22331					target.copy( projectedPoint );
22332  
22333				} else {
22334  
22335					// if not, the point falls outside the triangle. the target is the closest point to the triangle's edges or vertices
22336  
22337					edgeList[ 0 ].set( this.a, this.b );
22338					edgeList[ 1 ].set( this.b, this.c );
22339					edgeList[ 2 ].set( this.c, this.a );
22340  
22341					for ( var i = 0; i < edgeList.length; i ++ ) {
22342  
22343						edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
22344  
22345						var distance = projectedPoint.distanceToSquared( closestPoint );
22346  
22347						if ( distance < minDistance ) {
22348  
22349							minDistance = distance;
22350  
22351							target.copy( closestPoint );
22352  
22353						}
22354  
22355					}
22356  
22357				}
22358  
22359				return target;
22360  
22361			};
22362  
22363		}(),
22364  
22365		equals: function ( triangle ) {
22366  
22367			return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
22368  
22369		}
22370  
22371	} );
22372  
22373	/**
22374	 * @author mrdoob / http://mrdoob.com/
22375	 * @author alteredq / http://alteredqualia.com/
22376	 * @author mikael emtinger / http://gomo.se/
22377	 * @author jonobr1 / http://jonobr1.com/
22378	 */
22379  
22380	function Mesh( geometry, material ) {
22381  
22382		Object3D.call( this );
22383  
22384		this.type = 'Mesh';
22385  
22386		this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
22387		this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
22388  
22389		this.drawMode = TrianglesDrawMode;
22390  
22391		this.updateMorphTargets();
22392  
22393	}
22394  
22395	Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
22396  
22397		constructor: Mesh,
22398  
22399		isMesh: true,
22400  
22401		setDrawMode: function ( value ) {
22402  
22403			this.drawMode = value;
22404  
22405		},
22406  
22407		copy: function ( source ) {
22408  
22409			Object3D.prototype.copy.call( this, source );
22410  
22411			this.drawMode = source.drawMode;
22412  
22413			if ( source.morphTargetInfluences !== undefined ) {
22414  
22415				this.morphTargetInfluences = source.morphTargetInfluences.slice();
22416  
22417			}
22418  
22419			if ( source.morphTargetDictionary !== undefined ) {
22420  
22421				this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
22422  
22423			}
22424  
22425			return this;
22426  
22427		},
22428  
22429		updateMorphTargets: function () {
22430  
22431			var geometry = this.geometry;
22432			var m, ml, name;
22433  
22434			if ( geometry.isBufferGeometry ) {
22435  
22436				var morphAttributes = geometry.morphAttributes;
22437				var keys = Object.keys( morphAttributes );
22438  
22439				if ( keys.length > 0 ) {
22440  
22441					var morphAttribute = morphAttributes[ keys[ 0 ] ];
22442  
22443					if ( morphAttribute !== undefined ) {
22444  
22445						this.morphTargetInfluences = [];
22446						this.morphTargetDictionary = {};
22447  
22448						for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
22449  
22450							name = morphAttribute[ m ].name || String( m );
22451  
22452							this.morphTargetInfluences.push( 0 );
22453							this.morphTargetDictionary[ name ] = m;
22454  
22455						}
22456  
22457					}
22458  
22459				}
22460  
22461			} else {
22462  
22463				var morphTargets = geometry.morphTargets;
22464  
22465				if ( morphTargets !== undefined && morphTargets.length > 0 ) {
22466  
22467					this.morphTargetInfluences = [];
22468					this.morphTargetDictionary = {};
22469  
22470					for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
22471  
22472						name = morphTargets[ m ].name || String( m );
22473  
22474						this.morphTargetInfluences.push( 0 );
22475						this.morphTargetDictionary[ name ] = m;
22476  
22477					}
22478  
22479				}
22480  
22481			}
22482  
22483		},
22484  
22485		raycast: ( function () {
22486  
22487			var inverseMatrix = new Matrix4();
22488			var ray = new Ray();
22489			var sphere = new Sphere();
22490  
22491			var vA = new Vector3();
22492			var vB = new Vector3();
22493			var vC = new Vector3();
22494  
22495			var tempA = new Vector3();
22496			var tempB = new Vector3();
22497			var tempC = new Vector3();
22498  
22499			var uvA = new Vector2();
22500			var uvB = new Vector2();
22501			var uvC = new Vector2();
22502  
22503			var barycoord = new Vector3();
22504  
22505			var intersectionPoint = new Vector3();
22506			var intersectionPointWorld = new Vector3();
22507  
22508			function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
22509  
22510				Triangle.getBarycoord( point, p1, p2, p3, barycoord );
22511  
22512				uv1.multiplyScalar( barycoord.x );
22513				uv2.multiplyScalar( barycoord.y );
22514				uv3.multiplyScalar( barycoord.z );
22515  
22516				uv1.add( uv2 ).add( uv3 );
22517  
22518				return uv1.clone();
22519  
22520			}
22521  
22522			function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
22523  
22524				var intersect;
22525  
22526				if ( material.side === BackSide ) {
22527  
22528					intersect = ray.intersectTriangle( pC, pB, pA, true, point );
22529  
22530				} else {
22531  
22532					intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
22533  
22534				}
22535  
22536				if ( intersect === null ) return null;
22537  
22538				intersectionPointWorld.copy( point );
22539				intersectionPointWorld.applyMatrix4( object.matrixWorld );
22540  
22541				var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
22542  
22543				if ( distance < raycaster.near || distance > raycaster.far ) return null;
22544  
22545				return {
22546					distance: distance,
22547					point: intersectionPointWorld.clone(),
22548					object: object
22549				};
22550  
22551			}
22552  
22553			function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) {
22554  
22555				vA.fromBufferAttribute( position, a );
22556				vB.fromBufferAttribute( position, b );
22557				vC.fromBufferAttribute( position, c );
22558  
22559				var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint );
22560  
22561				if ( intersection ) {
22562  
22563					if ( uv ) {
22564  
22565						uvA.fromBufferAttribute( uv, a );
22566						uvB.fromBufferAttribute( uv, b );
22567						uvC.fromBufferAttribute( uv, c );
22568  
22569						intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
22570  
22571					}
22572  
22573					var face = new Face3( a, b, c );
22574					Triangle.getNormal( vA, vB, vC, face.normal );
22575  
22576					intersection.face = face;
22577  
22578				}
22579  
22580				return intersection;
22581  
22582			}
22583  
22584			return function raycast( raycaster, intersects ) {
22585  
22586				var geometry = this.geometry;
22587				var material = this.material;
22588				var matrixWorld = this.matrixWorld;
22589  
22590				if ( material === undefined ) return;
22591  
22592				// Checking boundingSphere distance to ray
22593  
22594				if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
22595  
22596				sphere.copy( geometry.boundingSphere );
22597				sphere.applyMatrix4( matrixWorld );
22598  
22599				if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
22600  
22601				//
22602  
22603				inverseMatrix.getInverse( matrixWorld );
22604				ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
22605  
22606				// Check boundingBox before continuing
22607  
22608				if ( geometry.boundingBox !== null ) {
22609  
22610					if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
22611  
22612				}
22613  
22614				var intersection;
22615  
22616				if ( geometry.isBufferGeometry ) {
22617  
22618					var a, b, c;
22619					var index = geometry.index;
22620					var position = geometry.attributes.position;
22621					var uv = geometry.attributes.uv;
22622					var i, l;
22623  
22624					if ( index !== null ) {
22625  
22626						// indexed buffer geometry
22627  
22628						for ( i = 0, l = index.count; i < l; i += 3 ) {
22629  
22630							a = index.getX( i );
22631							b = index.getX( i + 1 );
22632							c = index.getX( i + 2 );
22633  
22634							intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
22635  
22636							if ( intersection ) {
22637  
22638								intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
22639								intersects.push( intersection );
22640  
22641							}
22642  
22643						}
22644  
22645					} else if ( position !== undefined ) {
22646  
22647						// non-indexed buffer geometry
22648  
22649						for ( i = 0, l = position.count; i < l; i += 3 ) {
22650  
22651							a = i;
22652							b = i + 1;
22653							c = i + 2;
22654  
22655							intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
22656  
22657							if ( intersection ) {
22658  
22659								intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
22660								intersects.push( intersection );
22661  
22662							}
22663  
22664						}
22665  
22666					}
22667  
22668				} else if ( geometry.isGeometry ) {
22669  
22670					var fvA, fvB, fvC;
22671					var isMultiMaterial = Array.isArray( material );
22672  
22673					var vertices = geometry.vertices;
22674					var faces = geometry.faces;
22675					var uvs;
22676  
22677					var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
22678					if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
22679  
22680					for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
22681  
22682						var face = faces[ f ];
22683						var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
22684  
22685						if ( faceMaterial === undefined ) continue;
22686  
22687						fvA = vertices[ face.a ];
22688						fvB = vertices[ face.b ];
22689						fvC = vertices[ face.c ];
22690  
22691						if ( faceMaterial.morphTargets === true ) {
22692  
22693							var morphTargets = geometry.morphTargets;
22694							var morphInfluences = this.morphTargetInfluences;
22695  
22696							vA.set( 0, 0, 0 );
22697							vB.set( 0, 0, 0 );
22698							vC.set( 0, 0, 0 );
22699  
22700							for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
22701  
22702								var influence = morphInfluences[ t ];
22703  
22704								if ( influence === 0 ) continue;
22705  
22706								var targets = morphTargets[ t ].vertices;
22707  
22708								vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
22709								vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
22710								vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
22711  
22712							}
22713  
22714							vA.add( fvA );
22715							vB.add( fvB );
22716							vC.add( fvC );
22717  
22718							fvA = vA;
22719							fvB = vB;
22720							fvC = vC;
22721  
22722						}
22723  
22724						intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
22725  
22726						if ( intersection ) {
22727  
22728							if ( uvs && uvs[ f ] ) {
22729  
22730								var uvs_f = uvs[ f ];
22731								uvA.copy( uvs_f[ 0 ] );
22732								uvB.copy( uvs_f[ 1 ] );
22733								uvC.copy( uvs_f[ 2 ] );
22734  
22735								intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
22736  
22737							}
22738  
22739							intersection.face = face;
22740							intersection.faceIndex = f;
22741							intersects.push( intersection );
22742  
22743						}
22744  
22745					}
22746  
22747				}
22748  
22749			};
22750  
22751		}() ),
22752  
22753		clone: function () {
22754  
22755			return new this.constructor( this.geometry, this.material ).copy( this );
22756  
22757		}
22758  
22759	} );
22760  
22761	/**
22762	 * @author mrdoob / http://mrdoob.com/
22763	 */
22764  
22765	function WebGLBackground( renderer, state, objects, premultipliedAlpha ) {
22766  
22767		var clearColor = new Color( 0x000000 );
22768		var clearAlpha = 0;
22769  
22770		var planeCamera, planeMesh;
22771		var boxMesh;
22772  
22773		function render( renderList, scene, camera, forceClear ) {
22774  
22775			var background = scene.background;
22776  
22777			if ( background === null ) {
22778  
22779				setClear( clearColor, clearAlpha );
22780  
22781			} else if ( background && background.isColor ) {
22782  
22783				setClear( background, 1 );
22784				forceClear = true;
22785  
22786			}
22787  
22788			if ( renderer.autoClear || forceClear ) {
22789  
22790				renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
22791  
22792			}
22793  
22794			if ( background && background.isCubeTexture ) {
22795  
22796				if ( boxMesh === undefined ) {
22797  
22798					boxMesh = new Mesh(
22799						new BoxBufferGeometry( 1, 1, 1 ),
22800						new ShaderMaterial( {
22801							uniforms: ShaderLib.cube.uniforms,
22802							vertexShader: ShaderLib.cube.vertexShader,
22803							fragmentShader: ShaderLib.cube.fragmentShader,
22804							side: BackSide,
22805							depthTest: true,
22806							depthWrite: false,
22807							fog: false
22808						} )
22809					);
22810  
22811					boxMesh.geometry.removeAttribute( 'normal' );
22812					boxMesh.geometry.removeAttribute( 'uv' );
22813  
22814					boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
22815  
22816						this.matrixWorld.copyPosition( camera.matrixWorld );
22817  
22818					};
22819  
22820					objects.update( boxMesh );
22821  
22822				}
22823  
22824				boxMesh.material.uniforms.tCube.value = background;
22825  
22826				renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null );
22827  
22828			} else if ( background && background.isTexture ) {
22829  
22830				if ( planeCamera === undefined ) {
22831  
22832					planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
22833  
22834					planeMesh = new Mesh(
22835						new PlaneBufferGeometry( 2, 2 ),
22836						new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } )
22837					);
22838  
22839					objects.update( planeMesh );
22840  
22841				}
22842  
22843				planeMesh.material.map = background;
22844  
22845				// TODO Push this to renderList
22846  
22847				renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null );
22848  
22849			}
22850  
22851		}
22852  
22853		function setClear( color, alpha ) {
22854  
22855			state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
22856  
22857		}
22858  
22859		return {
22860  
22861			getClearColor: function () {
22862  
22863				return clearColor;
22864  
22865			},
22866			setClearColor: function ( color, alpha ) {
22867  
22868				clearColor.set( color );
22869				clearAlpha = alpha !== undefined ? alpha : 1;
22870				setClear( clearColor, clearAlpha );
22871  
22872			},
22873			getClearAlpha: function () {
22874  
22875				return clearAlpha;
22876  
22877			},
22878			setClearAlpha: function ( alpha ) {
22879  
22880				clearAlpha = alpha;
22881				setClear( clearColor, clearAlpha );
22882  
22883			},
22884			render: render
22885  
22886		};
22887  
22888	}
22889  
22890	/**
22891	 * @author mrdoob / http://mrdoob.com/
22892	 */
22893  
22894	function WebGLBufferRenderer( gl, extensions, info ) {
22895  
22896		var mode;
22897  
22898		function setMode( value ) {
22899  
22900			mode = value;
22901  
22902		}
22903  
22904		function render( start, count ) {
22905  
22906			gl.drawArrays( mode, start, count );
22907  
22908			info.update( count, mode );
22909  
22910		}
22911  
22912		function renderInstances( geometry, start, count ) {
22913  
22914			var extension = extensions.get( 'ANGLE_instanced_arrays' );
22915  
22916			if ( extension === null ) {
22917  
22918				console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
22919				return;
22920  
22921			}
22922  
22923			extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
22924  
22925			info.update( count, mode, geometry.maxInstancedCount );
22926  
22927		}
22928  
22929		//
22930  
22931		this.setMode = setMode;
22932		this.render = render;
22933		this.renderInstances = renderInstances;
22934  
22935	}
22936  
22937	/**
22938	 * @author mrdoob / http://mrdoob.com/
22939	 */
22940  
22941	function WebGLCapabilities( gl, extensions, parameters ) {
22942  
22943		var maxAnisotropy;
22944  
22945		function getMaxAnisotropy() {
22946  
22947			if ( maxAnisotropy !== undefined ) return maxAnisotropy;
22948  
22949			var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
22950  
22951			if ( extension !== null ) {
22952  
22953				maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
22954  
22955			} else {
22956  
22957				maxAnisotropy = 0;
22958  
22959			}
22960  
22961			return maxAnisotropy;
22962  
22963		}
22964  
22965		function getMaxPrecision( precision ) {
22966  
22967			if ( precision === 'highp' ) {
22968  
22969				if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
22970					 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
22971  
22972					return 'highp';
22973  
22974				}
22975  
22976				precision = 'mediump';
22977  
22978			}
22979  
22980			if ( precision === 'mediump' ) {
22981  
22982				if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
22983					 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
22984  
22985					return 'mediump';
22986  
22987				}
22988  
22989			}
22990  
22991			return 'lowp';
22992  
22993		}
22994  
22995		var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
22996		var maxPrecision = getMaxPrecision( precision );
22997  
22998		if ( maxPrecision !== precision ) {
22999  
23000			console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
23001			precision = maxPrecision;
23002  
23003		}
23004  
23005		var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
23006  
23007		var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
23008		var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
23009		var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
23010		var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
23011  
23012		var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
23013		var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
23014		var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
23015		var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
23016  
23017		var vertexTextures = maxVertexTextures > 0;
23018		var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
23019		var floatVertexTextures = vertexTextures && floatFragmentTextures;
23020  
23021		return {
23022  
23023			getMaxAnisotropy: getMaxAnisotropy,
23024			getMaxPrecision: getMaxPrecision,
vendor: 8,210 bytes, lines 23025-23416
23025  
23026			precision: precision,
23027			logarithmicDepthBuffer: logarithmicDepthBuffer,
23028  
23029			maxTextures: maxTextures,
23030			maxVertexTextures: maxVertexTextures,
23031			maxTextureSize: maxTextureSize,
23032			maxCubemapSize: maxCubemapSize,
23033  
23034			maxAttributes: maxAttributes,
23035			maxVertexUniforms: maxVertexUniforms,
23036			maxVaryings: maxVaryings,
23037			maxFragmentUniforms: maxFragmentUniforms,
23038  
23039			vertexTextures: vertexTextures,
23040			floatFragmentTextures: floatFragmentTextures,
23041			floatVertexTextures: floatVertexTextures
23042  
23043		};
23044  
23045	}
23046  
23047	/**
23048	 * @author tschw
23049	 */
23050  
23051	function WebGLClipping() {
23052  
23053		var scope = this,
23054  
23055			globalState = null,
23056			numGlobalPlanes = 0,
23057			localClippingEnabled = false,
23058			renderingShadows = false,
23059  
23060			plane = new Plane(),
23061			viewNormalMatrix = new Matrix3(),
23062  
23063			uniform = { value: null, needsUpdate: false };
23064  
23065		this.uniform = uniform;
23066		this.numPlanes = 0;
23067		this.numIntersection = 0;
23068  
23069		this.init = function ( planes, enableLocalClipping, camera ) {
23070  
23071			var enabled =
23072				planes.length !== 0 ||
23073				enableLocalClipping ||
23074				// enable state of previous frame - the clipping code has to
23075				// run another frame in order to reset the state:
23076				numGlobalPlanes !== 0 ||
23077				localClippingEnabled;
23078  
23079			localClippingEnabled = enableLocalClipping;
23080  
23081			globalState = projectPlanes( planes, camera, 0 );
23082			numGlobalPlanes = planes.length;
23083  
23084			return enabled;
23085  
23086		};
23087  
23088		this.beginShadows = function () {
23089  
23090			renderingShadows = true;
23091			projectPlanes( null );
23092  
23093		};
23094  
23095		this.endShadows = function () {
23096  
23097			renderingShadows = false;
23098			resetGlobalState();
23099  
23100		};
23101  
23102		this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
23103  
23104			if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
23105  
23106				// there's no local clipping
23107  
23108				if ( renderingShadows ) {
23109  
23110					// there's no global clipping
23111  
23112					projectPlanes( null );
23113  
23114				} else {
23115  
23116					resetGlobalState();
23117  
23118				}
23119  
23120			} else {
23121  
23122				var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
23123					lGlobal = nGlobal * 4,
23124  
23125					dstArray = cache.clippingState || null;
23126  
23127				uniform.value = dstArray; // ensure unique state
23128  
23129				dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
23130  
23131				for ( var i = 0; i !== lGlobal; ++ i ) {
23132  
23133					dstArray[ i ] = globalState[ i ];
23134  
23135				}
23136  
23137				cache.clippingState = dstArray;
23138				this.numIntersection = clipIntersection ? this.numPlanes : 0;
23139				this.numPlanes += nGlobal;
23140  
23141			}
23142  
23143  
23144		};
23145  
23146		function resetGlobalState() {
23147  
23148			if ( uniform.value !== globalState ) {
23149  
23150				uniform.value = globalState;
23151				uniform.needsUpdate = numGlobalPlanes > 0;
23152  
23153			}
23154  
23155			scope.numPlanes = numGlobalPlanes;
23156			scope.numIntersection = 0;
23157  
23158		}
23159  
23160		function projectPlanes( planes, camera, dstOffset, skipTransform ) {
23161  
23162			var nPlanes = planes !== null ? planes.length : 0,
23163				dstArray = null;
23164  
23165			if ( nPlanes !== 0 ) {
23166  
23167				dstArray = uniform.value;
23168  
23169				if ( skipTransform !== true || dstArray === null ) {
23170  
23171					var flatSize = dstOffset + nPlanes * 4,
23172						viewMatrix = camera.matrixWorldInverse;
23173  
23174					viewNormalMatrix.getNormalMatrix( viewMatrix );
23175  
23176					if ( dstArray === null || dstArray.length < flatSize ) {
23177  
23178						dstArray = new Float32Array( flatSize );
23179  
23180					}
23181  
23182					for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
23183  
23184						plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
23185  
23186						plane.normal.toArray( dstArray, i4 );
23187						dstArray[ i4 + 3 ] = plane.constant;
23188  
23189					}
23190  
23191				}
23192  
23193				uniform.value = dstArray;
23194				uniform.needsUpdate = true;
23195  
23196			}
23197  
23198			scope.numPlanes = nPlanes;
23199  
23200			return dstArray;
23201  
23202		}
23203  
23204	}
23205  
23206	/**
23207	 * @author mrdoob / http://mrdoob.com/
23208	 */
23209  
23210	function WebGLExtensions( gl ) {
23211  
23212		var extensions = {};
23213  
23214		return {
23215  
23216			get: function ( name ) {
23217  
23218				if ( extensions[ name ] !== undefined ) {
23219  
23220					return extensions[ name ];
23221  
23222				}
23223  
23224				var extension;
23225  
23226				switch ( name ) {
23227  
23228					case 'WEBGL_depth_texture':
23229						extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
23230						break;
23231  
23232					case 'EXT_texture_filter_anisotropic':
23233						extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
23234						break;
23235  
23236					case 'WEBGL_compressed_texture_s3tc':
23237						extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
23238						break;
23239  
23240					case 'WEBGL_compressed_texture_pvrtc':
23241						extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
23242						break;
23243  
23244					default:
23245						extension = gl.getExtension( name );
23246  
23247				}
23248  
23249				if ( extension === null ) {
23250  
23251					console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
23252  
23253				}
23254  
23255				extensions[ name ] = extension;
23256  
23257				return extension;
23258  
23259			}
23260  
23261		};
23262  
23263	}
23264  
23265	/**
23266	 * @author mrdoob / http://mrdoob.com/
23267	 */
23268  
23269	function WebGLGeometries( gl, attributes, info ) {
23270  
23271		var geometries = {};
23272		var wireframeAttributes = {};
23273  
23274		function onGeometryDispose( event ) {
23275  
23276			var geometry = event.target;
23277			var buffergeometry = geometries[ geometry.id ];
23278  
23279			if ( buffergeometry.index !== null ) {
23280  
23281				attributes.remove( buffergeometry.index );
23282  
23283			}
23284  
23285			for ( var name in buffergeometry.attributes ) {
23286  
23287				attributes.remove( buffergeometry.attributes[ name ] );
23288  
23289			}
23290  
23291			geometry.removeEventListener( 'dispose', onGeometryDispose );
23292  
23293			delete geometries[ geometry.id ];
23294  
23295			// TODO Remove duplicate code
23296  
23297			var attribute = wireframeAttributes[ geometry.id ];
23298  
23299			if ( attribute ) {
23300  
23301				attributes.remove( attribute );
23302				delete wireframeAttributes[ geometry.id ];
23303  
23304			}
23305  
23306			attribute = wireframeAttributes[ buffergeometry.id ];
23307  
23308			if ( attribute ) {
23309  
23310				attributes.remove( attribute );
23311				delete wireframeAttributes[ buffergeometry.id ];
23312  
23313			}
23314  
23315			//
23316  
23317			info.memory.geometries --;
23318  
23319		}
23320  
23321		function get( object, geometry ) {
23322  
23323			var buffergeometry = geometries[ geometry.id ];
23324  
23325			if ( buffergeometry ) return buffergeometry;
23326  
23327			geometry.addEventListener( 'dispose', onGeometryDispose );
23328  
23329			if ( geometry.isBufferGeometry ) {
23330  
23331				buffergeometry = geometry;
23332  
23333			} else if ( geometry.isGeometry ) {
23334  
23335				if ( geometry._bufferGeometry === undefined ) {
23336  
23337					geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
23338  
23339				}
23340  
23341				buffergeometry = geometry._bufferGeometry;
23342  
23343			}
23344  
23345			geometries[ geometry.id ] = buffergeometry;
23346  
23347			info.memory.geometries ++;
23348  
23349			return buffergeometry;
23350  
23351		}
23352  
23353		function update( geometry ) {
23354  
23355			var index = geometry.index;
23356			var geometryAttributes = geometry.attributes;
23357  
23358			if ( index !== null ) {
23359  
23360				attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
23361  
23362			}
23363  
23364			for ( var name in geometryAttributes ) {
23365  
23366				attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
23367  
23368			}
23369  
23370			// morph targets
23371  
23372			var morphAttributes = geometry.morphAttributes;
23373  
23374			for ( var name in morphAttributes ) {
23375  
23376				var array = morphAttributes[ name ];
23377  
23378				for ( var i = 0, l = array.length; i < l; i ++ ) {
23379  
23380					attributes.update( array[ i ], gl.ARRAY_BUFFER );
23381  
23382				}
23383  
23384			}
23385  
23386		}
23387  
23388		function getWireframeAttribute( geometry ) {
23389  
23390			var attribute = wireframeAttributes[ geometry.id ];
23391  
23392			if ( attribute ) return attribute;
23393  
23394			var indices = [];
23395  
23396			var geometryIndex = geometry.index;
23397			var geometryAttributes = geometry.attributes;
23398  
23399			// console.time( 'wireframe' );
23400  
23401			if ( geometryIndex !== null ) {
23402  
23403				var array = geometryIndex.array;
23404  
23405				for ( var i = 0, l = array.length; i < l; i += 3 ) {
23406  
23407					var a = array[ i + 0 ];
23408					var b = array[ i + 1 ];
23409					var c = array[ i + 2 ];
23410  
23411					indices.push( a, b, b, c, c, a );
23412  
23413				}
23414  
23415			} else {
23416  
23417				var array = geometryAttributes.position.array;
23418  
23419				for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
23420  
23421					var a = i + 0;
23422					var b = i + 1;
23423					var c = i + 2;
23424  
23425					indices.push( a, b, b, c, c, a );
23426  
23427				}
23428  
23429			}
23430  
23431			// console.timeEnd( 'wireframe' );
23432  
23433			attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
23434  
23435			attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
23436  
23437			wireframeAttributes[ geometry.id ] = attribute;
23438  
23439			return attribute;
23440  
23441		}
23442  
23443		return {
23444  
23445			get: get,
23446			update: update,
23447  
23448			getWireframeAttribute: getWireframeAttribute
23449  
23450		};
23451  
23452	}
23453  
23454	/**
23455	 * @author mrdoob / http://mrdoob.com/
23456	 */
23457  
23458	function WebGLIndexedBufferRenderer( gl, extensions, info ) {
23459  
23460		var mode;
23461  
23462		function setMode( value ) {
23463  
23464			mode = value;
23465  
23466		}
23467  
23468		var type, bytesPerElement;
23469  
23470		function setIndex( value ) {
23471  
23472			type = value.type;
23473			bytesPerElement = value.bytesPerElement;
23474  
23475		}
23476  
23477		function render( start, count ) {
23478  
23479			gl.drawElements( mode, count, type, start * bytesPerElement );
23480  
23481			info.update( count, mode );
23482  
23483		}
23484  
23485		function renderInstances( geometry, start, count ) {
23486  
23487			var extension = extensions.get( 'ANGLE_instanced_arrays' );
23488  
23489			if ( extension === null ) {
23490  
23491				console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
23492				return;
23493  
23494			}
23495  
23496			extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
23497  
23498			info.update( count, mode, geometry.maxInstancedCount );
23499  
23500		}
23501  
23502		//
23503  
23504		this.setMode = setMode;
23505		this.setIndex = setIndex;
23506		this.render = render;
23507		this.renderInstances = renderInstances;
23508  
23509	}
23510  
23511	/**
23512	 * @author Mugen87 / https://github.com/Mugen87
23513	 */
23514  
23515	function WebGLInfo( gl ) {
23516  
23517		var memory = {
23518			geometries: 0,
23519			textures: 0
23520		};
23521  
23522		var render = {
23523			frame: 0,
23524			calls: 0,
23525			triangles: 0,
23526			points: 0,
23527			lines: 0
23528		};
23529  
23530		function update( count, mode, instanceCount ) {
23531  
23532			instanceCount = instanceCount || 1;
23533  
23534			render.calls ++;
23535  
23536			switch ( mode ) {
23537  
23538				case gl.TRIANGLES:
23539					render.triangles += instanceCount * ( count / 3 );
23540					break;
23541  
23542				case gl.TRIANGLE_STRIP:
23543				case gl.TRIANGLE_FAN:
23544					render.triangles += instanceCount * ( count - 2 );
23545					break;
23546  
23547				case gl.LINES:
23548					render.lines += instanceCount * ( count / 2 );
23549					break;
23550  
23551				case gl.LINE_STRIP:
23552					render.lines += instanceCount * ( count - 1 );
23553					break;
23554  
23555				case gl.LINE_LOOP:
23556					render.lines += instanceCount * count;
23557					break;
23558  
23559				case gl.POINTS:
23560					render.points += instanceCount * count;
23561					break;
23562  
23563				default:
23564					console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
23565					break;
23566  
23567			}
23568  
23569		}
23570  
23571		function reset() {
23572  
23573			render.frame ++;
23574			render.calls = 0;
23575			render.triangles = 0;
23576			render.points = 0;
23577			render.lines = 0;
23578  
23579		}
23580  
23581		return {
23582			memory: memory,
23583			render: render,
23584			programs: null,
23585			autoReset: true,
23586			reset: reset,
23587			update: update
23588		};
23589  
23590	}
23591  
23592	/**
23593	 * @author mrdoob / http://mrdoob.com/
23594	 */
23595  
23596	function absNumericalSort( a, b ) {
23597  
23598		return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
23599  
23600	}
23601  
23602	function WebGLMorphtargets( gl ) {
23603  
23604		var influencesList = {};
23605		var morphInfluences = new Float32Array( 8 );
23606  
23607		function update( object, geometry, material, program ) {
23608  
23609			var objectInfluences = object.morphTargetInfluences;
23610  
23611			var length = objectInfluences.length;
23612  
23613			var influences = influencesList[ geometry.id ];
23614  
23615			if ( influences === undefined ) {
23616  
23617				// initialise list
23618  
23619				influences = [];
23620  
23621				for ( var i = 0; i < length; i ++ ) {
23622  
23623					influences[ i ] = [ i, 0 ];
23624  
23625				}
23626  
23627				influencesList[ geometry.id ] = influences;
23628  
23629			}
23630  
23631			var morphTargets = material.morphTargets && geometry.morphAttributes.position;
23632			var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
23633  
23634			// Remove current morphAttributes
23635  
23636			for ( var i = 0; i < length; i ++ ) {
23637  
23638				var influence = influences[ i ];
23639  
23640				if ( influence[ 1 ] !== 0 ) {
23641  
23642					if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i );
23643					if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i );
23644  
23645				}
23646  
23647			}
23648  
23649			// Collect influences
23650  
23651			for ( var i = 0; i < length; i ++ ) {
23652  
23653				var influence = influences[ i ];
23654  
23655				influence[ 0 ] = i;
23656				influence[ 1 ] = objectInfluences[ i ];
23657  
23658			}
23659  
23660			influences.sort( absNumericalSort );
23661  
23662			// Add morphAttributes
23663  
23664			for ( var i = 0; i < 8; i ++ ) {
23665  
23666				var influence = influences[ i ];
23667  
23668				if ( influence ) {
23669  
23670					var index = influence[ 0 ];
23671					var value = influence[ 1 ];
23672  
23673					if ( value ) {
23674  
23675						if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] );
23676						if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] );
23677  
23678						morphInfluences[ i ] = value;
23679						continue;
23680  
23681					}
23682  
23683				}
23684  
23685				morphInfluences[ i ] = 0;
23686  
23687			}
23688  
23689			program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
23690  
23691		}
23692  
23693		return {
23694  
23695			update: update
23696  
23697		};
23698  
23699	}
23700  
23701	/**
23702	 * @author mrdoob / http://mrdoob.com/
23703	 */
23704  
23705	function WebGLObjects( geometries, info ) {
23706  
23707		var updateList = {};
23708  
23709		function update( object ) {
23710  
23711			var frame = info.render.frame;
23712  
23713			var geometry = object.geometry;
23714			var buffergeometry = geometries.get( object, geometry );
23715  
23716			// Update once per frame
23717  
vendor: 16,111 bytes, lines 23718-24548
23718			if ( updateList[ buffergeometry.id ] !== frame ) {
23719  
23720				if ( geometry.isGeometry ) {
23721  
23722					buffergeometry.updateFromObject( object );
23723  
23724				}
23725  
23726				geometries.update( buffergeometry );
23727  
23728				updateList[ buffergeometry.id ] = frame;
23729  
23730			}
23731  
23732			return buffergeometry;
23733  
23734		}
23735  
23736		function dispose() {
23737  
23738			updateList = {};
23739  
23740		}
23741  
23742		return {
23743  
23744			update: update,
23745			dispose: dispose
23746  
23747		};
23748  
23749	}
23750  
23751	/**
23752	 * @author mrdoob / http://mrdoob.com/
23753	 */
23754  
23755	function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
23756  
23757		images = images !== undefined ? images : [];
23758		mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
23759  
23760		Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
23761  
23762		this.flipY = false;
23763  
23764	}
23765  
23766	CubeTexture.prototype = Object.create( Texture.prototype );
23767	CubeTexture.prototype.constructor = CubeTexture;
23768  
23769	CubeTexture.prototype.isCubeTexture = true;
23770  
23771	Object.defineProperty( CubeTexture.prototype, 'images', {
23772  
23773		get: function () {
23774  
23775			return this.image;
23776  
23777		},
23778  
23779		set: function ( value ) {
23780  
23781			this.image = value;
23782  
23783		}
23784  
23785	} );
23786  
23787	/**
23788	 * @author tschw
23789	 *
23790	 * Uniforms of a program.
23791	 * Those form a tree structure with a special top-level container for the root,
23792	 * which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
23793	 *
23794	 *
23795	 * Properties of inner nodes including the top-level container:
23796	 *
23797	 * .seq - array of nested uniforms
23798	 * .map - nested uniforms by name
23799	 *
23800	 *
23801	 * Methods of all nodes except the top-level container:
23802	 *
23803	 * .setValue( gl, value, [renderer] )
23804	 *
23805	 * 		uploads a uniform value(s)
23806	 *  	the 'renderer' parameter is needed for sampler uniforms
23807	 *
23808	 *
23809	 * Static methods of the top-level container (renderer factorizations):
23810	 *
23811	 * .upload( gl, seq, values, renderer )
23812	 *
23813	 * 		sets uniforms in 'seq' to 'values[id].value'
23814	 *
23815	 * .seqWithValue( seq, values ) : filteredSeq
23816	 *
23817	 * 		filters 'seq' entries with corresponding entry in values
23818	 *
23819	 *
23820	 * Methods of the top-level container (renderer factorizations):
23821	 *
23822	 * .setValue( gl, name, value )
23823	 *
23824	 * 		sets uniform with  name 'name' to 'value'
23825	 *
23826	 * .set( gl, obj, prop )
23827	 *
23828	 * 		sets uniform from object and property with same name than uniform
23829	 *
23830	 * .setOptional( gl, obj, prop )
23831	 *
23832	 * 		like .set for an optional property of the object
23833	 *
23834	 */
23835  
23836	var emptyTexture = new Texture();
23837	var emptyCubeTexture = new CubeTexture();
23838  
23839	// --- Base for inner nodes (including the root) ---
23840  
23841	function UniformContainer() {
23842  
23843		this.seq = [];
23844		this.map = {};
23845  
23846	}
23847  
23848	// --- Utilities ---
23849  
23850	// Array Caches (provide typed arrays for temporary by size)
23851  
23852	var arrayCacheF32 = [];
23853	var arrayCacheI32 = [];
23854  
23855	// Float32Array caches used for uploading Matrix uniforms
23856  
23857	var mat4array = new Float32Array( 16 );
23858	var mat3array = new Float32Array( 9 );
23859	var mat2array = new Float32Array( 4 );
23860  
23861	// Flattening for arrays of vectors and matrices
23862  
23863	function flatten( array, nBlocks, blockSize ) {
23864  
23865		var firstElem = array[ 0 ];
23866  
23867		if ( firstElem <= 0 || firstElem > 0 ) return array;
23868		// unoptimized: ! isNaN( firstElem )
23869		// see http://jacksondunstan.com/articles/983
23870  
23871		var n = nBlocks * blockSize,
23872			r = arrayCacheF32[ n ];
23873  
23874		if ( r === undefined ) {
23875  
23876			r = new Float32Array( n );
23877			arrayCacheF32[ n ] = r;
23878  
23879		}
23880  
23881		if ( nBlocks !== 0 ) {
23882  
23883			firstElem.toArray( r, 0 );
23884  
23885			for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
23886  
23887				offset += blockSize;
23888				array[ i ].toArray( r, offset );
23889  
23890			}
23891  
23892		}
23893  
23894		return r;
23895  
23896	}
23897  
23898	function arraysEqual( a, b ) {
23899  
23900		if ( a.length !== b.length ) return false;
23901  
23902		for ( var i = 0, l = a.length; i < l; i ++ ) {
23903  
23904			if ( a[ i ] !== b[ i ] ) return false;
23905  
23906		}
23907  
23908		return true;
23909  
23910	}
23911  
23912	function copyArray( a, b ) {
23913  
23914		for ( var i = 0, l = b.length; i < l; i ++ ) {
23915  
23916			a[ i ] = b[ i ];
23917  
23918		}
23919  
23920	}
23921  
23922	// Texture unit allocation
23923  
23924	function allocTexUnits( renderer, n ) {
23925  
23926		var r = arrayCacheI32[ n ];
23927  
23928		if ( r === undefined ) {
23929  
23930			r = new Int32Array( n );
23931			arrayCacheI32[ n ] = r;
23932  
23933		}
23934  
23935		for ( var i = 0; i !== n; ++ i )
23936			r[ i ] = renderer.allocTextureUnit();
23937  
23938		return r;
23939  
23940	}
23941  
23942	// --- Setters ---
23943  
23944	// Note: Defining these methods externally, because they come in a bunch
23945	// and this way their names minify.
23946  
23947	// Single scalar
23948  
23949	function setValue1f( gl, v ) {
23950  
23951		var cache = this.cache;
23952  
23953		if ( cache[ 0 ] === v ) return;
23954  
23955		gl.uniform1f( this.addr, v );
23956  
23957		cache[ 0 ] = v;
23958  
23959	}
23960  
23961	function setValue1i( gl, v ) {
23962  
23963		var cache = this.cache;
23964  
23965		if ( cache[ 0 ] === v ) return;
23966  
23967		gl.uniform1i( this.addr, v );
23968  
23969		cache[ 0 ] = v;
23970  
23971	}
23972  
23973	// Single float vector (from flat array or THREE.VectorN)
23974  
23975	function setValue2fv( gl, v ) {
23976  
23977		var cache = this.cache;
23978  
23979		if ( v.x !== undefined ) {
23980  
23981			if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
23982  
23983				gl.uniform2f( this.addr, v.x, v.y );
23984  
23985				cache[ 0 ] = v.x;
23986				cache[ 1 ] = v.y;
23987  
23988			}
23989  
23990		} else {
23991  
23992			if ( arraysEqual( cache, v ) ) return;
23993  
23994			gl.uniform2fv( this.addr, v );
23995  
23996			copyArray( cache, v );
23997  
23998		}
23999  
24000	}
24001  
24002	function setValue3fv( gl, v ) {
24003  
24004		var cache = this.cache;
24005  
24006		if ( v.x !== undefined ) {
24007  
24008			if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
24009  
24010				gl.uniform3f( this.addr, v.x, v.y, v.z );
24011  
24012				cache[ 0 ] = v.x;
24013				cache[ 1 ] = v.y;
24014				cache[ 2 ] = v.z;
24015  
24016			}
24017  
24018		} else if ( v.r !== undefined ) {
24019  
24020			if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
24021  
24022				gl.uniform3f( this.addr, v.r, v.g, v.b );
24023  
24024				cache[ 0 ] = v.r;
24025				cache[ 1 ] = v.g;
24026				cache[ 2 ] = v.b;
24027  
24028			}
24029  
24030		} else {
24031  
24032			if ( arraysEqual( cache, v ) ) return;
24033  
24034			gl.uniform3fv( this.addr, v );
24035  
24036			copyArray( cache, v );
24037  
24038		}
24039  
24040	}
24041  
24042	function setValue4fv( gl, v ) {
24043  
24044		var cache = this.cache;
24045  
24046		if ( v.x !== undefined ) {
24047  
24048			if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
24049  
24050				gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
24051  
24052				cache[ 0 ] = v.x;
24053				cache[ 1 ] = v.y;
24054				cache[ 2 ] = v.z;
24055				cache[ 3 ] = v.w;
24056  
24057			}
24058  
24059		} else {
24060  
24061			if ( arraysEqual( cache, v ) ) return;
24062  
24063			gl.uniform4fv( this.addr, v );
24064  
24065			copyArray( cache, v );
24066  
24067		}
24068  
24069	}
24070  
24071	// Single matrix (from flat array or MatrixN)
24072  
24073	function setValue2fm( gl, v ) {
24074  
24075		var cache = this.cache;
24076		var elements = v.elements;
24077  
24078		if ( elements === undefined ) {
24079  
24080			if ( arraysEqual( cache, v ) ) return;
24081  
24082			gl.uniformMatrix2fv( this.addr, false, v );
24083  
24084			copyArray( cache, v );
24085  
24086		} else {
24087  
24088			if ( arraysEqual( cache, elements ) ) return;
24089  
24090			mat2array.set( elements );
24091  
24092			gl.uniformMatrix2fv( this.addr, false, mat2array );
24093  
24094			copyArray( cache, elements );
24095  
24096		}
24097  
24098	}
24099  
24100	function setValue3fm( gl, v ) {
24101  
24102		var cache = this.cache;
24103		var elements = v.elements;
24104  
24105		if ( elements === undefined ) {
24106  
24107			if ( arraysEqual( cache, v ) ) return;
24108  
24109			gl.uniformMatrix3fv( this.addr, false, v );
24110  
24111			copyArray( cache, v );
24112  
24113		} else {
24114  
24115			if ( arraysEqual( cache, elements ) ) return;
24116  
24117			mat3array.set( elements );
24118  
24119			gl.uniformMatrix3fv( this.addr, false, mat3array );
24120  
24121			copyArray( cache, elements );
24122  
24123		}
24124  
24125	}
24126  
24127	function setValue4fm( gl, v ) {
24128  
24129		var cache = this.cache;
24130		var elements = v.elements;
24131  
24132		if ( elements === undefined ) {
24133  
24134			if ( arraysEqual( cache, v ) ) return;
24135  
24136			gl.uniformMatrix4fv( this.addr, false, v );
24137  
24138			copyArray( cache, v );
24139  
24140		} else {
24141  
24142			if ( arraysEqual( cache, elements ) ) return;
24143  
24144			mat4array.set( elements );
24145  
24146			gl.uniformMatrix4fv( this.addr, false, mat4array );
24147  
24148			copyArray( cache, elements );
24149  
24150		}
24151  
24152	}
24153  
24154	// Single texture (2D / Cube)
24155  
24156	function setValueT1( gl, v, renderer ) {
24157  
24158		var cache = this.cache;
24159		var unit = renderer.allocTextureUnit();
24160  
24161		if ( cache[ 0 ] !== unit ) {
24162  
24163			gl.uniform1i( this.addr, unit );
24164			cache[ 0 ] = unit;
24165  
24166		}
24167  
24168		renderer.setTexture2D( v || emptyTexture, unit );
24169  
24170	}
24171  
24172	function setValueT6( gl, v, renderer ) {
24173  
24174		var cache = this.cache;
24175		var unit = renderer.allocTextureUnit();
24176  
24177		if ( cache[ 0 ] !== unit ) {
24178  
24179			gl.uniform1i( this.addr, unit );
24180			cache[ 0 ] = unit;
24181  
24182		}
24183  
24184		renderer.setTextureCube( v || emptyCubeTexture, unit );
24185  
24186	}
24187  
24188	// Integer / Boolean vectors or arrays thereof (always flat arrays)
24189  
24190	function setValue2iv( gl, v ) {
24191  
24192		var cache = this.cache;
24193  
24194		if ( arraysEqual( cache, v ) ) return;
24195  
24196		gl.uniform2iv( this.addr, v );
24197  
24198		copyArray( cache, v );
24199  
24200	}
24201  
24202	function setValue3iv( gl, v ) {
24203  
24204		var cache = this.cache;
24205  
24206		if ( arraysEqual( cache, v ) ) return;
24207  
24208		gl.uniform3iv( this.addr, v );
24209  
24210		copyArray( cache, v );
24211  
24212	}
24213  
24214	function setValue4iv( gl, v ) {
24215  
24216		var cache = this.cache;
24217  
24218		if ( arraysEqual( cache, v ) ) return;
24219  
24220		gl.uniform4iv( this.addr, v );
24221  
24222		copyArray( cache, v );
24223  
24224	}
24225  
24226	// Helper to pick the right setter for the singular case
24227  
24228	function getSingularSetter( type ) {
24229  
24230		switch ( type ) {
24231  
24232			case 0x1406: return setValue1f; // FLOAT
24233			case 0x8b50: return setValue2fv; // _VEC2
24234			case 0x8b51: return setValue3fv; // _VEC3
24235			case 0x8b52: return setValue4fv; // _VEC4
24236  
24237			case 0x8b5a: return setValue2fm; // _MAT2
24238			case 0x8b5b: return setValue3fm; // _MAT3
24239			case 0x8b5c: return setValue4fm; // _MAT4
24240  
24241			case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
24242			case 0x8b60: return setValueT6; // SAMPLER_CUBE
24243  
24244			case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
24245			case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
24246			case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
24247			case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
24248  
24249		}
24250  
24251	}
24252  
24253	// Array of scalars
24254  
24255	function setValue1fv( gl, v ) {
24256  
24257		var cache = this.cache;
24258  
24259		if ( arraysEqual( cache, v ) ) return;
24260  
24261		gl.uniform1fv( this.addr, v );
24262  
24263		copyArray( cache, v );
24264  
24265	}
24266	function setValue1iv( gl, v ) {
24267  
24268		var cache = this.cache;
24269  
24270		if ( arraysEqual( cache, v ) ) return;
24271  
24272		gl.uniform1iv( this.addr, v );
24273  
24274		copyArray( cache, v );
24275  
24276	}
24277  
24278	// Array of vectors (flat or from THREE classes)
24279  
24280	function setValueV2a( gl, v ) {
24281  
24282		var cache = this.cache;
24283		var data = flatten( v, this.size, 2 );
24284  
24285		if ( arraysEqual( cache, data ) ) return;
24286  
24287		gl.uniform2fv( this.addr, data );
24288  
24289		this.updateCache( data );
24290  
24291	}
24292  
24293	function setValueV3a( gl, v ) {
24294  
24295		var cache = this.cache;
24296		var data = flatten( v, this.size, 3 );
24297  
24298		if ( arraysEqual( cache, data ) ) return;
24299  
24300		gl.uniform3fv( this.addr, data );
24301  
24302		this.updateCache( data );
24303  
24304	}
24305  
24306	function setValueV4a( gl, v ) {
24307  
24308		var cache = this.cache;
24309		var data = flatten( v, this.size, 4 );
24310  
24311		if ( arraysEqual( cache, data ) ) return;
24312  
24313		gl.uniform4fv( this.addr, data );
24314  
24315		this.updateCache( data );
24316  
24317	}
24318  
24319	// Array of matrices (flat or from THREE clases)
24320  
24321	function setValueM2a( gl, v ) {
24322  
24323		var cache = this.cache;
24324		var data = flatten( v, this.size, 4 );
24325  
24326		if ( arraysEqual( cache, data ) ) return;
24327  
24328		gl.uniformMatrix2fv( this.addr, false, data );
24329  
24330		this.updateCache( data );
24331  
24332	}
24333  
24334	function setValueM3a( gl, v ) {
24335  
24336		var cache = this.cache;
24337		var data = flatten( v, this.size, 9 );
24338  
24339		if ( arraysEqual( cache, data ) ) return;
24340  
24341		gl.uniformMatrix3fv( this.addr, false, data );
24342  
24343		this.updateCache( data );
24344  
24345	}
24346  
24347	function setValueM4a( gl, v ) {
24348  
24349		var cache = this.cache;
24350		var data = flatten( v, this.size, 16 );
24351  
24352		if ( arraysEqual( cache, data ) ) return;
24353  
24354		gl.uniformMatrix4fv( this.addr, false, data );
24355  
24356		this.updateCache( data );
24357  
24358	}
24359  
24360	// Array of textures (2D / Cube)
24361  
24362	function setValueT1a( gl, v, renderer ) {
24363  
24364		var cache = this.cache;
24365		var n = v.length;
24366  
24367		var units = allocTexUnits( renderer, n );
24368  
24369		if ( arraysEqual( cache, units ) === false ) {
24370  
24371			gl.uniform1iv( this.addr, units );
24372			copyArray( cache, units );
24373  
24374		}
24375  
24376		for ( var i = 0; i !== n; ++ i ) {
24377  
24378			renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
24379  
24380		}
24381  
24382	}
24383  
24384	function setValueT6a( gl, v, renderer ) {
24385  
24386		var cache = this.cache;
24387		var n = v.length;
24388  
24389		var units = allocTexUnits( renderer, n );
24390  
24391		if ( arraysEqual( cache, units ) === false ) {
24392  
24393			gl.uniform1iv( this.addr, units );
24394			copyArray( cache, units );
24395  
24396		}
24397  
24398		for ( var i = 0; i !== n; ++ i ) {
24399  
24400			renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
24401  
24402		}
24403  
24404	}
24405  
24406	// Helper to pick the right setter for a pure (bottom-level) array
24407  
24408	function getPureArraySetter( type ) {
24409  
24410		switch ( type ) {
24411  
24412			case 0x1406: return setValue1fv; // FLOAT
24413			case 0x8b50: return setValueV2a; // _VEC2
24414			case 0x8b51: return setValueV3a; // _VEC3
24415			case 0x8b52: return setValueV4a; // _VEC4
24416  
24417			case 0x8b5a: return setValueM2a; // _MAT2
24418			case 0x8b5b: return setValueM3a; // _MAT3
24419			case 0x8b5c: return setValueM4a; // _MAT4
24420  
24421			case 0x8b5e: return setValueT1a; // SAMPLER_2D
24422			case 0x8b60: return setValueT6a; // SAMPLER_CUBE
24423  
24424			case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
24425			case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
24426			case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
24427			case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
24428  
24429		}
24430  
24431	}
24432  
24433	// --- Uniform Classes ---
24434  
24435	function SingleUniform( id, activeInfo, addr ) {
24436  
24437		this.id = id;
24438		this.addr = addr;
24439		this.cache = [];
24440		this.setValue = getSingularSetter( activeInfo.type );
24441  
24442		// this.path = activeInfo.name; // DEBUG
24443  
24444	}
24445  
24446	function PureArrayUniform( id, activeInfo, addr ) {
24447  
24448		this.id = id;
24449		this.addr = addr;
24450		this.cache = [];
24451		this.size = activeInfo.size;
24452		this.setValue = getPureArraySetter( activeInfo.type );
24453  
24454		// this.path = activeInfo.name; // DEBUG
24455  
24456	}
24457  
24458	PureArrayUniform.prototype.updateCache = function ( data ) {
24459  
24460		var cache = this.cache;
24461  
24462		if ( data instanceof Float32Array && cache.length !== data.length ) {
24463  
24464			this.cache = new Float32Array( data.length );
24465  
24466		}
24467  
24468		copyArray( cache, data );
24469  
24470	};
24471  
24472	function StructuredUniform( id ) {
24473  
24474		this.id = id;
24475  
24476		UniformContainer.call( this ); // mix-in
24477  
24478	}
24479  
24480	StructuredUniform.prototype.setValue = function ( gl, value ) {
24481  
24482		// Note: Don't need an extra 'renderer' parameter, since samplers
24483		// are not allowed in structured uniforms.
24484  
24485		var seq = this.seq;
24486  
24487		for ( var i = 0, n = seq.length; i !== n; ++ i ) {
24488  
24489			var u = seq[ i ];
24490			u.setValue( gl, value[ u.id ] );
24491  
24492		}
24493  
24494	};
24495  
24496	// --- Top-level ---
24497  
24498	// Parser - builds up the property tree from the path strings
24499  
24500	var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
24501  
24502	// extracts
24503	// 	- the identifier (member name or array index)
24504	//  - followed by an optional right bracket (found when array index)
24505	//  - followed by an optional left bracket or dot (type of subscript)
24506	//
24507	// Note: These portions can be read in a non-overlapping fashion and
24508	// allow straightforward parsing of the hierarchy that WebGL encodes
24509	// in the uniform names.
24510  
24511	function addUniform( container, uniformObject ) {
24512  
24513		container.seq.push( uniformObject );
24514		container.map[ uniformObject.id ] = uniformObject;
24515  
24516	}
24517  
24518	function parseUniform( activeInfo, addr, container ) {
24519  
24520		var path = activeInfo.name,
24521			pathLength = path.length;
24522  
24523		// reset RegExp object, because of the early exit of a previous run
24524		RePathPart.lastIndex = 0;
24525  
24526		while ( true ) {
24527  
24528			var match = RePathPart.exec( path ),
24529				matchEnd = RePathPart.lastIndex,
24530  
24531				id = match[ 1 ],
24532				idIsIndex = match[ 2 ] === ']',
24533				subscript = match[ 3 ];
24534  
24535			if ( idIsIndex ) id = id | 0; // convert to integer
24536  
24537			if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
24538  
24539				// bare name or "pure" bottom-level array "[0]" suffix
24540  
24541				addUniform( container, subscript === undefined ?
24542					new SingleUniform( id, activeInfo, addr ) :
24543					new PureArrayUniform( id, activeInfo, addr ) );
24544  
24545				break;
24546  
24547			} else {
24548  
24549				// step into inner node / create it in case it doesn't exist
24550  
24551				var map = container.map, next = map[ id ];
24552  
24553				if ( next === undefined ) {
24554  
24555					next = new StructuredUniform( id );
24556					addUniform( container, next );
24557  
24558				}
24559  
24560				container = next;
24561  
24562			}
24563  
24564		}
24565  
24566	}
24567  
24568	// Root Container
24569  
24570	function WebGLUniforms( gl, program, renderer ) {
24571  
24572		UniformContainer.call( this );
24573  
24574		this.renderer = renderer;
24575  
24576		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
24577  
24578		for ( var i = 0; i < n; ++ i ) {
24579  
24580			var info = gl.getActiveUniform( program, i ),
24581				addr = gl.getUniformLocation( program, info.name );
24582  
24583			parseUniform( info, addr, this );
24584  
24585		}
24586  
24587	}
24588  
24589	WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
24590  
24591		var u = this.map[ name ];
24592  
24593		if ( u !== undefined ) u.setValue( gl, value, this.renderer );
24594  
24595	};
24596  
24597	WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
24598  
24599		var v = object[ name ];
24600  
24601		if ( v !== undefined ) this.setValue( gl, name, v );
24602  
24603	};
24604  
24605  
24606	// Static interface
24607  
24608	WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
24609  
24610		for ( var i = 0, n = seq.length; i !== n; ++ i ) {
24611  
24612			var u = seq[ i ],
24613				v = values[ u.id ];
24614  
24615			if ( v.needsUpdate !== false ) {
24616  
24617				// note: always updating when .needsUpdate is undefined
24618				u.setValue( gl, v.value, renderer );
24619  
24620			}
24621  
24622		}
24623  
24624	};
24625  
24626	WebGLUniforms.seqWithValue = function ( seq, values ) {
24627  
24628		var r = [];
24629  
24630		for ( var i = 0, n = seq.length; i !== n; ++ i ) {
24631  
24632			var u = seq[ i ];
24633			if ( u.id in values ) r.push( u );
24634  
24635		}
24636  
24637		return r;
24638  
24639	};
24640  
24641	/**
24642	 * @author mrdoob / http://mrdoob.com/
24643	 */
24644  
24645	function addLineNumbers( string ) {
24646  
24647		var lines = string.split( '\n' );
24648  
24649		for ( var i = 0; i < lines.length; i ++ ) {
24650  
24651			lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
24652  
24653		}
24654  
24655		return lines.join( '\n' );
24656  
24657	}
24658  
24659	function WebGLShader( gl, type, string ) {
24660  
24661		var shader = gl.createShader( type );
24662  
24663		gl.shaderSource( shader, string );
24664		gl.compileShader( shader );
24665  
24666		if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
24667  
24668			console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
24669  
24670		}
24671  
24672		if ( gl.getShaderInfoLog( shader ) !== '' ) {
24673  
24674			console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
24675  
24676		}
24677  
24678		// --enable-privileged-webgl-extension
24679		// console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
24680  
24681		return shader;
24682  
24683	}
24684  
24685	/**
24686	 * @author mrdoob / http://mrdoob.com/
24687	 */
24688  
24689	var programIdCount = 0;
24690  
24691	function getEncodingComponents( encoding ) {
24692  
24693		switch ( encoding ) {
24694  
24695			case LinearEncoding:
24696				return [ 'Linear', '( value )' ];
24697			case sRGBEncoding:
24698				return [ 'sRGB', '( value )' ];
24699			case RGBEEncoding:
24700				return [ 'RGBE', '( value )' ];
24701			case RGBM7Encoding:
24702				return [ 'RGBM', '( value, 7.0 )' ];
24703			case RGBM16Encoding:
24704				return [ 'RGBM', '( value, 16.0 )' ];
24705			case RGBDEncoding:
24706				return [ 'RGBD', '( value, 256.0 )' ];
24707			case GammaEncoding:
24708				return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
24709			default:
24710				throw new Error( 'unsupported encoding: ' + encoding );
24711  
24712		}
24713  
24714	}
24715  
24716	function getTexelDecodingFunction( functionName, encoding ) {
24717  
24718		var components = getEncodingComponents( encoding );
24719		return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
24720  
24721	}
24722  
24723	function getTexelEncodingFunction( functionName, encoding ) {
24724  
24725		var components = getEncodingComponents( encoding );
24726		return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
24727  
24728	}
24729  
24730	function getToneMappingFunction( functionName, toneMapping ) {
24731  
24732		var toneMappingName;
24733  
24734		switch ( toneMapping ) {
24735  
24736			case LinearToneMapping:
24737				toneMappingName = 'Linear';
24738				break;
24739  
24740			case ReinhardToneMapping:
24741				toneMappingName = 'Reinhard';
24742				break;
24743  
24744			case Uncharted2ToneMapping:
24745				toneMappingName = 'Uncharted2';
24746				break;
24747  
24748			case CineonToneMapping:
24749				toneMappingName = 'OptimizedCineon';
24750				break;
24751  
24752			default:
24753				throw new Error( 'unsupported toneMapping: ' + toneMapping );
24754  
24755		}
24756  
24757		return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
24758  
24759	}
24760  
24761	function generateExtensions( extensions, parameters, rendererExtensions ) {
24762  
24763		extensions = extensions || {};
24764  
24765		var chunks = [
24766			( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
24767			( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
24768			( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
24769			( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
24770		];
24771  
24772		return chunks.filter( filterEmptyLine ).join( '\n' );
24773  
24774	}
24775  
24776	function generateDefines( defines ) {
24777  
24778		var chunks = [];
24779  
24780		for ( var name in defines ) {
24781  
24782			var value = defines[ name ];
24783  
24784			if ( value === false ) continue;
24785  
24786			chunks.push( '#define ' + name + ' ' + value );
24787  
24788		}
24789  
24790		return chunks.join( '\n' );
24791  
24792	}
24793  
24794	function fetchAttributeLocations( gl, program ) {
24795  
24796		var attributes = {};
24797  
24798		var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
24799  
24800		for ( var i = 0; i < n; i ++ ) {
24801  
24802			var info = gl.getActiveAttrib( program, i );
24803			var name = info.name;
24804  
24805			// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
24806  
24807			attributes[ name ] = gl.getAttribLocation( program, name );
24808  
24809		}
24810  
24811		return attributes;
24812  
24813	}
24814  
24815	function filterEmptyLine( string ) {
24816  
24817		return string !== '';
24818  
24819	}
24820  
24821	function replaceLightNums( string, parameters ) {
24822  
24823		return string
24824			.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
24825			.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
24826			.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
24827			.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
24828			.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
24829  
24830	}
24831  
24832	function replaceClippingPlaneNums( string, parameters ) {
24833  
24834		return string
24835			.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
24836			.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
24837  
24838	}
24839  
24840	function parseIncludes( string ) {
24841  
24842		var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
24843  
24844		function replace( match, include ) {
24845  
24846			var replace = ShaderChunk[ include ];
24847  
24848			if ( replace === undefined ) {
24849  
24850				throw new Error( 'Can not resolve #include <' + include + '>' );
24851  
24852			}
24853  
24854			return parseIncludes( replace );
24855  
24856		}
24857  
24858		return string.replace( pattern, replace );
24859  
24860	}
24861  
24862	function unrollLoops( string ) {
24863  
24864		var pattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
24865  
24866		function replace( match, start, end, snippet ) {
24867  
24868			var unroll = '';
24869  
24870			for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
24871  
24872				unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
24873  
24874			}
24875  
24876			return unroll;
24877  
24878		}
24879  
24880		return string.replace( pattern, replace );
24881  
24882	}
24883  
24884	function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
24885  
24886		var gl = renderer.context;
24887  
24888		var defines = material.defines;
24889  
24890		var vertexShader = shader.vertexShader;
24891		var fragmentShader = shader.fragmentShader;
24892  
24893		var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
24894  
24895		if ( parameters.shadowMapType === PCFShadowMap ) {
24896  
24897			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
24898  
24899		} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
24900  
24901			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
24902  
24903		}
24904  
24905		var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
24906		var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
24907		var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
24908  
24909		if ( parameters.envMap ) {
24910  
24911			switch ( material.envMap.mapping ) {
24912  
24913				case CubeReflectionMapping:
24914				case CubeRefractionMapping:
24915					envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
24916					break;
24917  
24918				case CubeUVReflectionMapping:
24919				case CubeUVRefractionMapping:
24920					envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
24921					break;
24922  
24923				case EquirectangularReflectionMapping:
24924				case EquirectangularRefractionMapping:
24925					envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
24926					break;
24927  
24928				case SphericalReflectionMapping:
24929					envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
24930					break;
24931  
24932			}
24933  
24934			switch ( material.envMap.mapping ) {
24935  
24936				case CubeRefractionMapping:
24937				case EquirectangularRefractionMapping:
24938					envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
24939					break;
24940  
24941			}
24942  
24943			switch ( material.combine ) {
24944  
24945				case MultiplyOperation:
24946					envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
24947					break;
24948  
24949				case MixOperation:
24950					envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
24951					break;
24952  
24953				case AddOperation:
24954					envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
24955					break;
24956  
24957			}
24958  
24959		}
24960  
24961		var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
24962  
24963		// console.log( 'building new program ' );
24964  
24965		//
24966  
24967		var customExtensions = generateExtensions( material.extensions, parameters, extensions );
24968  
24969		var customDefines = generateDefines( defines );
24970  
24971		//
24972  
24973		var program = gl.createProgram();
24974  
24975		var prefixVertex, prefixFragment;
24976  
24977		if ( material.isRawShaderMaterial ) {
24978  
24979			prefixVertex = [
24980  
24981				customDefines
24982  
24983			].filter( filterEmptyLine ).join( '\n' );
24984  
24985			if ( prefixVertex.length > 0 ) {
24986  
24987				prefixVertex += '\n';
24988  
24989			}
24990  
24991			prefixFragment = [
24992  
24993				customExtensions,
24994				customDefines
24995  
24996			].filter( filterEmptyLine ).join( '\n' );
24997  
24998			if ( prefixFragment.length > 0 ) {
24999  
25000				prefixFragment += '\n';
25001  
25002			}
25003  
25004		} else {
25005  
25006			prefixVertex = [
25007  
25008				'precision ' + parameters.precision + ' float;',
25009				'precision ' + parameters.precision + ' int;',
25010  
25011				'#define SHADER_NAME ' + shader.name,
25012  
25013				customDefines,
25014  
25015				parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
25016  
25017				'#define GAMMA_FACTOR ' + gammaFactorDefine,
25018  
25019				'#define MAX_BONES ' + parameters.maxBones,
25020				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
25021				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
25022  
25023				parameters.map ? '#define USE_MAP' : '',
25024				parameters.envMap ? '#define USE_ENVMAP' : '',
25025				parameters.envMap ? '#define ' + envMapModeDefine : '',
25026				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
25027				parameters.aoMap ? '#define USE_AOMAP' : '',
25028				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
25029				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
25030				parameters.normalMap ? '#define USE_NORMALMAP' : '',
25031				parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
25032				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
25033				parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
25034				parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
25035				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
25036				parameters.vertexColors ? '#define USE_COLOR' : '',
25037  
25038				parameters.flatShading ? '#define FLAT_SHADED' : '',
25039  
25040				parameters.skinning ? '#define USE_SKINNING' : '',
25041				parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
25042  
25043				parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
25044				parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
25045				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
25046				parameters.flipSided ? '#define FLIP_SIDED' : '',
25047  
25048				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
25049				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
25050  
25051				parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
25052  
25053				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
25054				parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
25055  
25056				'uniform mat4 modelMatrix;',
25057				'uniform mat4 modelViewMatrix;',
25058				'uniform mat4 projectionMatrix;',
25059				'uniform mat4 viewMatrix;',
25060				'uniform mat3 normalMatrix;',
25061				'uniform vec3 cameraPosition;',
25062  
25063				'attribute vec3 position;',
25064				'attribute vec3 normal;',
25065				'attribute vec2 uv;',
25066  
25067				'#ifdef USE_COLOR',
25068  
25069				'	attribute vec3 color;',
25070  
25071				'#endif',
25072  
25073				'#ifdef USE_MORPHTARGETS',
25074  
25075				'	attribute vec3 morphTarget0;',
25076				'	attribute vec3 morphTarget1;',
25077				'	attribute vec3 morphTarget2;',
25078				'	attribute vec3 morphTarget3;',
25079  
25080				'	#ifdef USE_MORPHNORMALS',
25081  
25082				'		attribute vec3 morphNormal0;',
25083				'		attribute vec3 morphNormal1;',
25084				'		attribute vec3 morphNormal2;',
25085				'		attribute vec3 morphNormal3;',
25086  
25087				'	#else',
25088  
25089				'		attribute vec3 morphTarget4;',
25090				'		attribute vec3 morphTarget5;',
25091				'		attribute vec3 morphTarget6;',
25092				'		attribute vec3 morphTarget7;',
25093  
25094				'	#endif',
25095  
25096				'#endif',
25097  
25098				'#ifdef USE_SKINNING',
25099  
25100				'	attribute vec4 skinIndex;',
25101				'	attribute vec4 skinWeight;',
25102  
25103				'#endif',
25104  
25105				'\n'
25106  
25107			].filter( filterEmptyLine ).join( '\n' );
25108  
25109			prefixFragment = [
25110  
25111				customExtensions,
25112  
25113				'precision ' + parameters.precision + ' float;',
25114				'precision ' + parameters.precision + ' int;',
25115  
25116				'#define SHADER_NAME ' + shader.name,
25117  
25118				customDefines,
25119  
25120				parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
25121  
25122				'#define GAMMA_FACTOR ' + gammaFactorDefine,
25123  
25124				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
25125				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
25126  
25127				parameters.map ? '#define USE_MAP' : '',
25128				parameters.envMap ? '#define USE_ENVMAP' : '',
25129				parameters.envMap ? '#define ' + envMapTypeDefine : '',
25130				parameters.envMap ? '#define ' + envMapModeDefine : '',
25131				parameters.envMap ? '#define ' + envMapBlendingDefine : '',
25132				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
25133				parameters.aoMap ? '#define USE_AOMAP' : '',
25134				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
25135				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
25136				parameters.normalMap ? '#define USE_NORMALMAP' : '',
25137				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
25138				parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
25139				parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
25140				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
25141				parameters.vertexColors ? '#define USE_COLOR' : '',
25142  
25143				parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
25144  
25145				parameters.flatShading ? '#define FLAT_SHADED' : '',
25146  
25147				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
25148				parameters.flipSided ? '#define FLIP_SIDED' : '',
25149  
25150				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
25151				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
25152  
25153				parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
25154  
25155				parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
25156  
25157				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
25158				parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
25159  
25160				parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
25161  
25162				'uniform mat4 viewMatrix;',
25163				'uniform vec3 cameraPosition;',
25164  
25165				( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
25166				( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
25167				( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
25168  
25169				parameters.dithering ? '#define DITHERING' : '',
25170  
25171				( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
25172				parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
25173				parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
25174				parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
25175				parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
25176  
25177				parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',
25178  
25179				'\n'
25180  
25181			].filter( filterEmptyLine ).join( '\n' );
25182  
25183		}
25184  
25185		vertexShader = parseIncludes( vertexShader );
25186		vertexShader = replaceLightNums( vertexShader, parameters );
25187		vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
25188  
25189		fragmentShader = parseIncludes( fragmentShader );
25190		fragmentShader = replaceLightNums( fragmentShader, parameters );
25191		fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
25192  
25193		vertexShader = unrollLoops( vertexShader );
25194		fragmentShader = unrollLoops( fragmentShader );
25195  
25196		var vertexGlsl = prefixVertex + vertexShader;
25197		var fragmentGlsl = prefixFragment + fragmentShader;
25198  
25199		// console.log( '*VERTEX*', vertexGlsl );
25200		// console.log( '*FRAGMENT*', fragmentGlsl );
25201  
25202		var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
25203		var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
25204  
25205		gl.attachShader( program, glVertexShader );
25206		gl.attachShader( program, glFragmentShader );
25207  
25208		// Force a particular attribute to index 0.
25209  
25210		if ( material.index0AttributeName !== undefined ) {
25211  
25212			gl.bindAttribLocation( program, 0, material.index0AttributeName );
25213  
25214		} else if ( parameters.morphTargets === true ) {
25215  
25216			// programs with morphTargets displace position out of attribute 0
25217			gl.bindAttribLocation( program, 0, 'position' );
25218  
25219		}
25220  
25221		gl.linkProgram( program );
25222  
25223		var programLog = gl.getProgramInfoLog( program ).trim();
25224		var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
25225		var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
25226  
25227		var runnable = true;
25228		var haveDiagnostics = true;
25229  
25230		// console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
25231		// console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
25232  
25233		if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
25234  
25235			runnable = false;
vendor: 4,320 bytes, lines 25236-25421
25236  
25237			console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
25238  
25239		} else if ( programLog !== '' ) {
25240  
25241			console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
25242  
25243		} else if ( vertexLog === '' || fragmentLog === '' ) {
25244  
25245			haveDiagnostics = false;
25246  
25247		}
25248  
25249		if ( haveDiagnostics ) {
25250  
25251			this.diagnostics = {
25252  
25253				runnable: runnable,
25254				material: material,
25255  
25256				programLog: programLog,
25257  
25258				vertexShader: {
25259  
25260					log: vertexLog,
25261					prefix: prefixVertex
25262  
25263				},
25264  
25265				fragmentShader: {
25266  
25267					log: fragmentLog,
25268					prefix: prefixFragment
25269  
25270				}
25271  
25272			};
25273  
25274		}
25275  
25276		// clean up
25277  
25278		gl.deleteShader( glVertexShader );
25279		gl.deleteShader( glFragmentShader );
25280  
25281		// set up caching for uniform locations
25282  
25283		var cachedUniforms;
25284  
25285		this.getUniforms = function () {
25286  
25287			if ( cachedUniforms === undefined ) {
25288  
25289				cachedUniforms = new WebGLUniforms( gl, program, renderer );
25290  
25291			}
25292  
25293			return cachedUniforms;
25294  
25295		};
25296  
25297		// set up caching for attribute locations
25298  
25299		var cachedAttributes;
25300  
25301		this.getAttributes = function () {
25302  
25303			if ( cachedAttributes === undefined ) {
25304  
25305				cachedAttributes = fetchAttributeLocations( gl, program );
25306  
25307			}
25308  
25309			return cachedAttributes;
25310  
25311		};
25312  
25313		// free resource
25314  
25315		this.destroy = function () {
25316  
25317			gl.deleteProgram( program );
25318			this.program = undefined;
25319  
25320		};
25321  
25322		// DEPRECATED
25323  
25324		Object.defineProperties( this, {
25325  
25326			uniforms: {
25327				get: function () {
25328  
25329					console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
25330					return this.getUniforms();
25331  
25332				}
25333			},
25334  
25335			attributes: {
25336				get: function () {
25337  
25338					console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
25339					return this.getAttributes();
25340  
25341				}
25342			}
25343  
25344		} );
25345  
25346  
25347		//
25348  
25349		this.name = shader.name;
25350		this.id = programIdCount ++;
25351		this.code = code;
25352		this.usedTimes = 1;
25353		this.program = program;
25354		this.vertexShader = glVertexShader;
25355		this.fragmentShader = glFragmentShader;
25356  
25357		return this;
25358  
25359	}
25360  
25361	/**
25362	 * @author mrdoob / http://mrdoob.com/
25363	 */
25364  
25365	function WebGLPrograms( renderer, extensions, capabilities ) {
25366  
25367		var programs = [];
25368  
25369		var shaderIDs = {
25370			MeshDepthMaterial: 'depth',
25371			MeshDistanceMaterial: 'distanceRGBA',
25372			MeshNormalMaterial: 'normal',
25373			MeshBasicMaterial: 'basic',
25374			MeshLambertMaterial: 'lambert',
25375			MeshPhongMaterial: 'phong',
25376			MeshToonMaterial: 'phong',
25377			MeshStandardMaterial: 'physical',
25378			MeshPhysicalMaterial: 'physical',
25379			LineBasicMaterial: 'basic',
25380			LineDashedMaterial: 'dashed',
25381			PointsMaterial: 'points',
25382			ShadowMaterial: 'shadow'
25383		};
25384  
25385		var parameterNames = [
25386			"precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
25387			"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
25388			"roughnessMap", "metalnessMap", "gradientMap",
25389			"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
25390			"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
25391			"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
25392			"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
25393			"numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
25394			"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
25395			"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
25396		];
25397  
25398  
25399		function allocateBones( object ) {
25400  
25401			var skeleton = object.skeleton;
25402			var bones = skeleton.bones;
25403  
25404			if ( capabilities.floatVertexTextures ) {
25405  
25406				return 1024;
25407  
25408			} else {
25409  
25410				// default for when object is not specified
25411				// ( for example when prebuilding shader to be used with multiple objects )
25412				//
25413				//  - leave some extra space for other uniforms
25414				//  - limit here is ANGLE's 254 max uniform vectors
25415				//    (up to 54 should be safe)
25416  
25417				var nVertexUniforms = capabilities.maxVertexUniforms;
25418				var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
25419  
25420				var maxBones = Math.min( nVertexMatrices, bones.length );
25421  
25422				if ( maxBones < bones.length ) {
25423  
25424					console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
25425					return 0;
25426  
25427				}
25428  
25429				return maxBones;
25430  
25431			}
25432  
25433		}
25434  
25435		function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
25436  
25437			var encoding;
25438  
25439			if ( ! map ) {
25440  
25441				encoding = LinearEncoding;
25442  
25443			} else if ( map.isTexture ) {
25444  
25445				encoding = map.encoding;
25446  
25447			} else if ( map.isWebGLRenderTarget ) {
25448  
25449				console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
25450				encoding = map.texture.encoding;
25451  
25452			}
25453  
25454			// add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
25455			if ( encoding === LinearEncoding && gammaOverrideLinear ) {
25456  
25457				encoding = GammaEncoding;
25458  
25459			}
25460  
25461			return encoding;
25462  
25463		}
25464  
25465		this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
25466  
25467			var shaderID = shaderIDs[ material.type ];
25468  
25469			// heuristics to create shader parameters according to lights in the scene
25470			// (not to blow over maxLights budget)
25471  
25472			var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
25473			var precision = capabilities.precision;
25474  
25475			if ( material.precision !== null ) {
25476  
25477				precision = capabilities.getMaxPrecision( material.precision );
25478  
25479				if ( precision !== material.precision ) {
25480  
25481					console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
25482  
25483				}
25484  
25485			}
25486  
25487			var currentRenderTarget = renderer.getRenderTarget();
25488  
25489			var parameters = {
25490  
25491				shaderID: shaderID,
25492  
25493				precision: precision,
25494				supportsVertexTextures: capabilities.vertexTextures,
25495				outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
25496				map: !! material.map,
25497				mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
25498				envMap: !! material.envMap,
25499				envMapMode: material.envMap && material.envMap.mapping,
25500				envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
25501				envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
25502				lightMap: !! material.lightMap,
25503				aoMap: !! material.aoMap,
25504				emissiveMap: !! material.emissiveMap,
25505				emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
25506				bumpMap: !! material.bumpMap,
25507				normalMap: !! material.normalMap,
25508				displacementMap: !! material.displacementMap,
25509				roughnessMap: !! material.roughnessMap,
25510				metalnessMap: !! material.metalnessMap,
25511				specularMap: !! material.specularMap,
25512				alphaMap: !! material.alphaMap,
25513  
25514				gradientMap: !! material.gradientMap,
25515  
25516				combine: material.combine,
25517  
25518				vertexColors: material.vertexColors,
25519  
25520				fog: !! fog,
25521				useFog: material.fog,
25522				fogExp: ( fog && fog.isFogExp2 ),
25523  
25524				flatShading: material.flatShading,
25525  
25526				sizeAttenuation: material.sizeAttenuation,
25527				logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
25528  
25529				skinning: material.skinning && maxBones > 0,
25530				maxBones: maxBones,
25531				useVertexTexture: capabilities.floatVertexTextures,
25532  
25533				morphTargets: material.morphTargets,
25534				morphNormals: material.morphNormals,
25535				maxMorphTargets: renderer.maxMorphTargets,
25536				maxMorphNormals: renderer.maxMorphNormals,
25537  
25538				numDirLights: lights.directional.length,
25539				numPointLights: lights.point.length,
25540				numSpotLights: lights.spot.length,
25541				numRectAreaLights: lights.rectArea.length,
25542				numHemiLights: lights.hemi.length,
25543  
25544				numClippingPlanes: nClipPlanes,
25545				numClipIntersection: nClipIntersection,
25546  
25547				dithering: material.dithering,
25548  
25549				shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
25550				shadowMapType: renderer.shadowMap.type,
25551  
25552				toneMapping: renderer.toneMapping,
25553				physicallyCorrectLights: renderer.physicallyCorrectLights,
25554  
25555				premultipliedAlpha: material.premultipliedAlpha,
25556  
25557				alphaTest: material.alphaTest,
25558				doubleSided: material.side === DoubleSide,
25559				flipSided: material.side === BackSide,
25560  
25561				depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
25562  
25563			};
25564  
25565			return parameters;
25566  
25567		};
25568  
25569		this.getProgramCode = function ( material, parameters ) {
25570  
25571			var array = [];
25572  
25573			if ( parameters.shaderID ) {
25574  
25575				array.push( parameters.shaderID );
25576  
25577			} else {
25578  
25579				array.push( material.fragmentShader );
25580				array.push( material.vertexShader );
25581  
25582			}
25583  
25584			if ( material.defines !== undefined ) {
25585  
25586				for ( var name in material.defines ) {
25587  
25588					array.push( name );
25589					array.push( material.defines[ name ] );
25590  
25591				}
25592  
25593			}
25594  
25595			for ( var i = 0; i < parameterNames.length; i ++ ) {
25596  
25597				array.push( parameters[ parameterNames[ i ] ] );
25598  
25599			}
25600  
25601			array.push( material.onBeforeCompile.toString() );
25602  
25603			array.push( renderer.gammaOutput );
25604  
25605			return array.join();
25606  
25607		};
25608  
25609		this.acquireProgram = function ( material, shader, parameters, code ) {
25610  
25611			var program;
25612  
25613			// Check if code has been already compiled
25614			for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
25615  
25616				var programInfo = programs[ p ];
25617  
25618				if ( programInfo.code === code ) {
25619  
25620					program = programInfo;
25621					++ program.usedTimes;
25622  
25623					break;
25624  
25625				}
25626  
25627			}
25628  
25629			if ( program === undefined ) {
25630  
25631				program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
25632				programs.push( program );
25633  
25634			}
25635  
25636			return program;
25637  
25638		};
25639  
25640		this.releaseProgram = function ( program ) {
25641  
25642			if ( -- program.usedTimes === 0 ) {
25643  
25644				// Remove from unordered set
25645				var i = programs.indexOf( program );
25646				programs[ i ] = programs[ programs.length - 1 ];
25647				programs.pop();
25648  
25649				// Free WebGL resources
25650				program.destroy();
25651  
25652			}
25653  
25654		};
25655  
25656		// Exposed for resource monitoring & error feedback via renderer.info:
25657		this.programs = programs;
25658  
25659	}
25660  
25661	/**
25662	 * @author fordacious / fordacious.github.io
25663	 */
25664  
25665	function WebGLProperties() {
25666  
25667		var properties = new WeakMap();
25668  
25669		function get( object ) {
25670  
25671			var map = properties.get( object );
25672  
25673			if ( map === undefined ) {
25674  
25675				map = {};
25676				properties.set( object, map );
25677  
25678			}
25679  
25680			return map;
25681  
25682		}
25683  
25684		function remove( object ) {
25685  
25686			properties.delete( object );
25687  
25688		}
25689  
25690		function update( object, key, value ) {
25691  
25692			properties.get( object )[ key ] = value;
25693  
25694		}
25695  
25696		function dispose() {
25697  
25698			properties = new WeakMap();
25699  
25700		}
25701  
25702		return {
25703			get: get,
25704			remove: remove,
25705			update: update,
25706			dispose: dispose
25707		};
25708  
25709	}
25710  
25711	/**
25712	 * @author mrdoob / http://mrdoob.com/
25713	 */
25714  
25715	function painterSortStable( a, b ) {
25716  
25717		if ( a.renderOrder !== b.renderOrder ) {
25718  
25719			return a.renderOrder - b.renderOrder;
25720  
25721		} else if ( a.program && b.program && a.program !== b.program ) {
25722  
25723			return a.program.id - b.program.id;
25724  
25725		} else if ( a.material.id !== b.material.id ) {
25726  
25727			return a.material.id - b.material.id;
25728  
25729		} else if ( a.z !== b.z ) {
25730  
25731			return a.z - b.z;
25732  
25733		} else {
25734  
25735			return a.id - b.id;
25736  
25737		}
25738  
25739	}
25740  
25741	function reversePainterSortStable( a, b ) {
25742  
25743		if ( a.renderOrder !== b.renderOrder ) {
25744  
25745			return a.renderOrder - b.renderOrder;
25746  
25747		} if ( a.z !== b.z ) {
25748  
25749			return b.z - a.z;
25750  
25751		} else {
25752  
25753			return a.id - b.id;
25754  
25755		}
25756  
25757	}
25758  
25759	function WebGLRenderList() {
25760  
25761		var renderItems = [];
25762		var renderItemsIndex = 0;
25763  
25764		var opaque = [];
25765		var transparent = [];
25766  
25767		function init() {
25768  
25769			renderItemsIndex = 0;
25770  
25771			opaque.length = 0;
25772			transparent.length = 0;
25773  
25774		}
25775  
25776		function push( object, geometry, material, z, group ) {
25777  
25778			var renderItem = renderItems[ renderItemsIndex ];
25779  
25780			if ( renderItem === undefined ) {
25781  
25782				renderItem = {
25783					id: object.id,
25784					object: object,
25785					geometry: geometry,
25786					material: material,
25787					program: material.program,
25788					renderOrder: object.renderOrder,
25789					z: z,
25790					group: group
25791				};
25792  
25793				renderItems[ renderItemsIndex ] = renderItem;
25794  
25795			} else {
25796  
25797				renderItem.id = object.id;
25798				renderItem.object = object;
25799				renderItem.geometry = geometry;
25800				renderItem.material = material;
25801				renderItem.program = material.program;
25802				renderItem.renderOrder = object.renderOrder;
25803				renderItem.z = z;
25804				renderItem.group = group;
25805  
25806			}
25807  
25808			( material.transparent === true ? transparent : opaque ).push( renderItem );
25809  
25810			renderItemsIndex ++;
25811  
25812		}
25813  
25814		function sort() {
25815  
25816			if ( opaque.length > 1 ) opaque.sort( painterSortStable );
25817			if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
25818  
25819		}
25820  
25821		return {
25822			opaque: opaque,
25823			transparent: transparent,
25824  
25825			init: init,
25826			push: push,
25827  
25828			sort: sort
25829		};
25830  
25831	}
25832  
25833	function WebGLRenderLists() {
25834  
25835		var lists = {};
25836  
25837		function get( scene, camera ) {
25838  
25839			var hash = scene.id + ',' + camera.id;
25840			var list = lists[ hash ];
25841  
25842			if ( list === undefined ) {
25843  
25844				// console.log( 'THREE.WebGLRenderLists:', hash );
25845  
25846				list = new WebGLRenderList();
25847				lists[ hash ] = list;
25848  
25849			}
25850  
25851			return list;
25852  
25853		}
25854  
25855		function dispose() {
25856  
25857			lists = {};
25858  
25859		}
25860  
25861		return {
25862			get: get,
25863			dispose: dispose
25864		};
25865  
25866	}
25867  
25868	/**
25869	 * @author mrdoob / http://mrdoob.com/
25870	 */
25871  
25872	function UniformsCache() {
25873  
25874		var lights = {};
25875  
25876		return {
25877  
25878			get: function ( light ) {
25879  
25880				if ( lights[ light.id ] !== undefined ) {
25881  
25882					return lights[ light.id ];
25883  
25884				}
25885  
25886				var uniforms;
25887  
25888				switch ( light.type ) {
25889  
25890					case 'DirectionalLight':
25891						uniforms = {
25892							direction: new Vector3(),
25893							color: new Color(),
25894  
25895							shadow: false,
25896							shadowBias: 0,
25897							shadowRadius: 1,
25898							shadowMapSize: new Vector2()
25899						};
25900						break;
25901  
25902					case 'SpotLight':
25903						uniforms = {
25904							position: new Vector3(),
25905							direction: new Vector3(),
25906							color: new Color(),
25907							distance: 0,
25908							coneCos: 0,
25909							penumbraCos: 0,
25910							decay: 0,
25911  
25912							shadow: false,
25913							shadowBias: 0,
25914							shadowRadius: 1,
25915							shadowMapSize: new Vector2()
25916						};
25917						break;
25918  
25919					case 'PointLight':
25920						uniforms = {
25921							position: new Vector3(),
25922							color: new Color(),
25923							distance: 0,
25924							decay: 0,
25925  
25926							shadow: false,
25927							shadowBias: 0,
25928							shadowRadius: 1,
25929							shadowMapSize: new Vector2(),
25930							shadowCameraNear: 1,
25931							shadowCameraFar: 1000
25932						};
25933						break;
25934  
25935					case 'HemisphereLight':
25936						uniforms = {
25937							direction: new Vector3(),
25938							skyColor: new Color(),
25939							groundColor: new Color()
25940						};
25941						break;
25942  
25943					case 'RectAreaLight':
25944						uniforms = {
25945							color: new Color(),
25946							position: new Vector3(),
25947							halfWidth: new Vector3(),
25948							halfHeight: new Vector3()
25949							// TODO (abelnation): set RectAreaLight shadow uniforms
25950						};
25951						break;
25952  
25953				}
25954  
25955				lights[ light.id ] = uniforms;
25956  
25957				return uniforms;
25958  
25959			}
25960  
25961		};
25962  
25963	}
25964  
25965	var count = 0;
25966  
25967	function WebGLLights() {
25968  
25969		var cache = new UniformsCache();
25970  
25971		var state = {
25972  
25973			id: count ++,
25974  
25975			hash: '',
25976  
25977			ambient: [ 0, 0, 0 ],
25978			directional: [],
25979			directionalShadowMap: [],
25980			directionalShadowMatrix: [],
25981			spot: [],
25982			spotShadowMap: [],
25983			spotShadowMatrix: [],
25984			rectArea: [],
25985			point: [],
25986			pointShadowMap: [],
25987			pointShadowMatrix: [],
25988			hemi: []
25989  
25990		};
25991  
25992		var vector3 = new Vector3();
25993		var matrix4 = new Matrix4();
25994		var matrix42 = new Matrix4();
25995  
25996		function setup( lights, shadows, camera ) {
25997  
25998			var r = 0, g = 0, b = 0;
25999  
26000			var directionalLength = 0;
26001			var pointLength = 0;
26002			var spotLength = 0;
26003			var rectAreaLength = 0;
26004			var hemiLength = 0;
26005  
26006			var viewMatrix = camera.matrixWorldInverse;
26007  
26008			for ( var i = 0, l = lights.length; i < l; i ++ ) {
26009  
26010				var light = lights[ i ];
26011  
26012				var color = light.color;
26013				var intensity = light.intensity;
26014				var distance = light.distance;
26015  
26016				var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
26017  
26018				if ( light.isAmbientLight ) {
26019  
26020					r += color.r * intensity;
26021					g += color.g * intensity;
26022					b += color.b * intensity;
26023  
26024				} else if ( light.isDirectionalLight ) {
26025  
26026					var uniforms = cache.get( light );
26027  
26028					uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
26029					uniforms.direction.setFromMatrixPosition( light.matrixWorld );
26030					vector3.setFromMatrixPosition( light.target.matrixWorld );
26031					uniforms.direction.sub( vector3 );
26032					uniforms.direction.transformDirection( viewMatrix );
26033  
26034					uniforms.shadow = light.castShadow;
26035  
26036					if ( light.castShadow ) {
26037  
26038						var shadow = light.shadow;
26039  
26040						uniforms.shadowBias = shadow.bias;
26041						uniforms.shadowRadius = shadow.radius;
26042						uniforms.shadowMapSize = shadow.mapSize;
26043  
26044					}
26045  
26046					state.directionalShadowMap[ directionalLength ] = shadowMap;
26047					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
26048					state.directional[ directionalLength ] = uniforms;
26049  
26050					directionalLength ++;
26051  
26052				} else if ( light.isSpotLight ) {
26053  
26054					var uniforms = cache.get( light );
26055  
26056					uniforms.position.setFromMatrixPosition( light.matrixWorld );
26057					uniforms.position.applyMatrix4( viewMatrix );
26058  
26059					uniforms.color.copy( color ).multiplyScalar( intensity );
26060					uniforms.distance = distance;
26061  
26062					uniforms.direction.setFromMatrixPosition( light.matrixWorld );
26063					vector3.setFromMatrixPosition( light.target.matrixWorld );
26064					uniforms.direction.sub( vector3 );
26065					uniforms.direction.transformDirection( viewMatrix );
26066  
26067					uniforms.coneCos = Math.cos( light.angle );
26068					uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
26069					uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
26070  
26071					uniforms.shadow = light.castShadow;
26072  
26073					if ( light.castShadow ) {
26074  
26075						var shadow = light.shadow;
26076  
26077						uniforms.shadowBias = shadow.bias;
26078						uniforms.shadowRadius = shadow.radius;
26079						uniforms.shadowMapSize = shadow.mapSize;
26080  
26081					}
26082  
26083					state.spotShadowMap[ spotLength ] = shadowMap;
26084					state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
26085					state.spot[ spotLength ] = uniforms;
26086  
26087					spotLength ++;
26088  
26089				} else if ( light.isRectAreaLight ) {
26090  
26091					var uniforms = cache.get( light );
26092  
26093					// (a) intensity is the total visible light emitted
26094					//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
26095  
26096					// (b) intensity is the brightness of the light
26097					uniforms.color.copy( color ).multiplyScalar( intensity );
26098  
26099					uniforms.position.setFromMatrixPosition( light.matrixWorld );
26100					uniforms.position.applyMatrix4( viewMatrix );
26101  
26102					// extract local rotation of light to derive width/height half vectors
26103					matrix42.identity();
26104					matrix4.copy( light.matrixWorld );
26105					matrix4.premultiply( viewMatrix );
26106					matrix42.extractRotation( matrix4 );
26107  
26108					uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
26109					uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
26110  
26111					uniforms.halfWidth.applyMatrix4( matrix42 );
26112					uniforms.halfHeight.applyMatrix4( matrix42 );
26113  
26114					// TODO (abelnation): RectAreaLight distance?
26115					// uniforms.distance = distance;
26116  
26117					state.rectArea[ rectAreaLength ] = uniforms;
26118  
26119					rectAreaLength ++;
26120  
26121				} else if ( light.isPointLight ) {
26122  
26123					var uniforms = cache.get( light );
26124  
26125					uniforms.position.setFromMatrixPosition( light.matrixWorld );
26126					uniforms.position.applyMatrix4( viewMatrix );
26127  
26128					uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
26129					uniforms.distance = light.distance;
26130					uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
26131  
26132					uniforms.shadow = light.castShadow;
26133  
26134					if ( light.castShadow ) {
26135  
26136						var shadow = light.shadow;
26137  
26138						uniforms.shadowBias = shadow.bias;
26139						uniforms.shadowRadius = shadow.radius;
26140						uniforms.shadowMapSize = shadow.mapSize;
26141						uniforms.shadowCameraNear = shadow.camera.near;
26142						uniforms.shadowCameraFar = shadow.camera.far;
26143  
26144					}
26145  
26146					state.pointShadowMap[ pointLength ] = shadowMap;
26147					state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
26148					state.point[ pointLength ] = uniforms;
26149  
26150					pointLength ++;
26151  
26152				} else if ( light.isHemisphereLight ) {
26153  
26154					var uniforms = cache.get( light );
26155  
26156					uniforms.direction.setFromMatrixPosition( light.matrixWorld );
26157					uniforms.direction.transformDirection( viewMatrix );
26158					uniforms.direction.normalize();
26159  
26160					uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
26161					uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
26162  
26163					state.hemi[ hemiLength ] = uniforms;
26164  
26165					hemiLength ++;
26166  
26167				}
26168  
26169			}
26170  
26171			state.ambient[ 0 ] = r;
26172			state.ambient[ 1 ] = g;
26173			state.ambient[ 2 ] = b;
26174  
26175			state.directional.length = directionalLength;
26176			state.spot.length = spotLength;
26177			state.rectArea.length = rectAreaLength;
26178			state.point.length = pointLength;
26179			state.hemi.length = hemiLength;
26180  
26181			state.hash = state.id + ',' + directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
26182  
26183		}
26184  
26185		return {
26186			setup: setup,
26187			state: state
26188		};
26189  
26190	}
26191  
26192	/**
26193	 * @author Mugen87 / https://github.com/Mugen87
26194	 */
26195  
26196	function WebGLRenderState() {
26197  
26198		var lights = new WebGLLights();
26199  
26200		var lightsArray = [];
26201		var shadowsArray = [];
26202		var spritesArray = [];
26203  
vendor: 4,489 bytes, lines 26204-26434
26204		function init() {
26205  
26206			lightsArray.length = 0;
26207			shadowsArray.length = 0;
26208			spritesArray.length = 0;
26209  
26210		}
26211  
26212		function pushLight( light ) {
26213  
26214			lightsArray.push( light );
26215  
26216		}
26217  
26218		function pushShadow( shadowLight ) {
26219  
26220			shadowsArray.push( shadowLight );
26221  
26222		}
26223  
26224		function pushSprite( shadowLight ) {
26225  
26226			spritesArray.push( shadowLight );
26227  
26228		}
26229  
26230		function setupLights( camera ) {
26231  
26232			lights.setup( lightsArray, shadowsArray, camera );
26233  
26234		}
26235  
26236		var state = {
26237			lightsArray: lightsArray,
26238			shadowsArray: shadowsArray,
26239			spritesArray: spritesArray,
26240  
26241			lights: lights
26242		};
26243  
26244		return {
26245			init: init,
26246			state: state,
26247			setupLights: setupLights,
26248  
26249			pushLight: pushLight,
26250			pushShadow: pushShadow,
26251			pushSprite: pushSprite
26252		};
26253  
26254	}
26255  
26256	function WebGLRenderStates() {
26257  
26258		var renderStates = {};
26259  
26260		function get( scene, camera ) {
26261  
26262			var hash = scene.id + ',' + camera.id;
26263  
26264			var renderState = renderStates[ hash ];
26265  
26266			if ( renderState === undefined ) {
26267  
26268				renderState = new WebGLRenderState();
26269				renderStates[ hash ] = renderState;
26270  
26271			}
26272  
26273			return renderState;
26274  
26275		}
26276  
26277		function dispose() {
26278  
26279			renderStates = {};
26280  
26281		}
26282  
26283		return {
26284			get: get,
26285			dispose: dispose
26286		};
26287  
26288	}
26289  
26290	/**
26291	 * @author mrdoob / http://mrdoob.com/
26292	 * @author alteredq / http://alteredqualia.com/
26293	 * @author bhouston / https://clara.io
26294	 * @author WestLangley / http://github.com/WestLangley
26295	 *
26296	 * parameters = {
26297	 *
26298	 *  opacity: <float>,
26299	 *
26300	 *  map: new THREE.Texture( <Image> ),
26301	 *
26302	 *  alphaMap: new THREE.Texture( <Image> ),
26303	 *
26304	 *  displacementMap: new THREE.Texture( <Image> ),
26305	 *  displacementScale: <float>,
26306	 *  displacementBias: <float>,
26307	 *
26308	 *  wireframe: <boolean>,
26309	 *  wireframeLinewidth: <float>
26310	 * }
26311	 */
26312  
26313	function MeshDepthMaterial( parameters ) {
26314  
26315		Material.call( this );
26316  
26317		this.type = 'MeshDepthMaterial';
26318  
26319		this.depthPacking = BasicDepthPacking;
26320  
26321		this.skinning = false;
26322		this.morphTargets = false;
26323  
26324		this.map = null;
26325  
26326		this.alphaMap = null;
26327  
26328		this.displacementMap = null;
26329		this.displacementScale = 1;
26330		this.displacementBias = 0;
26331  
26332		this.wireframe = false;
26333		this.wireframeLinewidth = 1;
26334  
26335		this.fog = false;
26336		this.lights = false;
26337  
26338		this.setValues( parameters );
26339  
26340	}
26341  
26342	MeshDepthMaterial.prototype = Object.create( Material.prototype );
26343	MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
26344  
26345	MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
26346  
26347	MeshDepthMaterial.prototype.copy = function ( source ) {
26348  
26349		Material.prototype.copy.call( this, source );
26350  
26351		this.depthPacking = source.depthPacking;
26352  
26353		this.skinning = source.skinning;
26354		this.morphTargets = source.morphTargets;
26355  
26356		this.map = source.map;
26357  
26358		this.alphaMap = source.alphaMap;
26359  
26360		this.displacementMap = source.displacementMap;
26361		this.displacementScale = source.displacementScale;
26362		this.displacementBias = source.displacementBias;
26363  
26364		this.wireframe = source.wireframe;
26365		this.wireframeLinewidth = source.wireframeLinewidth;
26366  
26367		return this;
26368  
26369	};
26370  
26371	/**
26372	 * @author WestLangley / http://github.com/WestLangley
26373	 *
26374	 * parameters = {
26375	 *
26376	 *  referencePosition: <float>,
26377	 *  nearDistance: <float>,
26378	 *  farDistance: <float>,
26379	 *
26380	 *  skinning: <bool>,
26381	 *  morphTargets: <bool>,
26382	 *
26383	 *  map: new THREE.Texture( <Image> ),
26384	 *
26385	 *  alphaMap: new THREE.Texture( <Image> ),
26386	 *
26387	 *  displacementMap: new THREE.Texture( <Image> ),
26388	 *  displacementScale: <float>,
26389	 *  displacementBias: <float>
26390	 *
26391	 * }
26392	 */
26393  
26394	function MeshDistanceMaterial( parameters ) {
26395  
26396		Material.call( this );
26397  
26398		this.type = 'MeshDistanceMaterial';
26399  
26400		this.referencePosition = new Vector3();
26401		this.nearDistance = 1;
26402		this.farDistance = 1000;
26403  
26404		this.skinning = false;
26405		this.morphTargets = false;
26406  
26407		this.map = null;
26408  
26409		this.alphaMap = null;
26410  
26411		this.displacementMap = null;
26412		this.displacementScale = 1;
26413		this.displacementBias = 0;
26414  
26415		this.fog = false;
26416		this.lights = false;
26417  
26418		this.setValues( parameters );
26419  
26420	}
26421  
26422	MeshDistanceMaterial.prototype = Object.create( Material.prototype );
26423	MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
26424  
26425	MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
26426  
26427	MeshDistanceMaterial.prototype.copy = function ( source ) {
26428  
26429		Material.prototype.copy.call( this, source );
26430  
26431		this.referencePosition.copy( source.referencePosition );
26432		this.nearDistance = source.nearDistance;
26433		this.farDistance = source.farDistance;
26434  
26435		this.skinning = source.skinning;
26436		this.morphTargets = source.morphTargets;
26437  
26438		this.map = source.map;
26439  
26440		this.alphaMap = source.alphaMap;
26441  
26442		this.displacementMap = source.displacementMap;
26443		this.displacementScale = source.displacementScale;
26444		this.displacementBias = source.displacementBias;
26445  
26446		return this;
26447  
26448	};
26449  
26450	/**
26451	 * @author alteredq / http://alteredqualia.com/
26452	 * @author mrdoob / http://mrdoob.com/
26453	 */
26454  
26455	function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
26456  
26457		var _frustum = new Frustum(),
26458			_projScreenMatrix = new Matrix4(),
26459  
26460			_shadowMapSize = new Vector2(),
26461			_maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
26462  
26463			_lookTarget = new Vector3(),
26464			_lightPositionWorld = new Vector3(),
26465  
26466			_MorphingFlag = 1,
26467			_SkinningFlag = 2,
26468  
26469			_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
26470  
26471			_depthMaterials = new Array( _NumberOfMaterialVariants ),
26472			_distanceMaterials = new Array( _NumberOfMaterialVariants ),
26473  
26474			_materialCache = {};
26475  
26476		var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
26477  
26478		var cubeDirections = [
26479			new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
26480			new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
26481		];
26482  
26483		var cubeUps = [
26484			new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
26485			new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
26486		];
26487  
26488		var cube2DViewPorts = [
26489			new Vector4(), new Vector4(), new Vector4(),
26490			new Vector4(), new Vector4(), new Vector4()
26491		];
26492  
26493		// init
26494  
26495		for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
26496  
26497			var useMorphing = ( i & _MorphingFlag ) !== 0;
26498			var useSkinning = ( i & _SkinningFlag ) !== 0;
26499  
26500			var depthMaterial = new MeshDepthMaterial( {
26501  
26502				depthPacking: RGBADepthPacking,
26503  
26504				morphTargets: useMorphing,
26505				skinning: useSkinning
26506  
26507			} );
26508  
26509			_depthMaterials[ i ] = depthMaterial;
26510  
26511			//
26512  
26513			var distanceMaterial = new MeshDistanceMaterial( {
26514  
26515				morphTargets: useMorphing,
26516				skinning: useSkinning
26517  
26518			} );
26519  
26520			_distanceMaterials[ i ] = distanceMaterial;
26521  
26522		}
26523  
26524		//
26525  
26526		var scope = this;
26527  
26528		this.enabled = false;
26529  
26530		this.autoUpdate = true;
26531		this.needsUpdate = false;
26532  
26533		this.type = PCFShadowMap;
26534  
26535		this.render = function ( lights, scene, camera ) {
26536  
26537			if ( scope.enabled === false ) return;
26538			if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
26539  
26540			if ( lights.length === 0 ) return;
26541  
26542			// TODO Clean up (needed in case of contextlost)
26543			var _gl = _renderer.context;
26544			var _state = _renderer.state;
26545  
26546			// Set GL state for depth map.
26547			_state.disable( _gl.BLEND );
26548			_state.buffers.color.setClear( 1, 1, 1, 1 );
26549			_state.buffers.depth.setTest( true );
26550			_state.setScissorTest( false );
26551  
26552			// render depth map
26553  
26554			var faceCount;
26555  
26556			for ( var i = 0, il = lights.length; i < il; i ++ ) {
26557  
26558				var light = lights[ i ];
26559				var shadow = light.shadow;
26560				var isPointLight = light && light.isPointLight;
26561  
26562				if ( shadow === undefined ) {
26563  
26564					console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
26565					continue;
26566  
26567				}
26568  
26569				var shadowCamera = shadow.camera;
26570  
26571				_shadowMapSize.copy( shadow.mapSize );
26572				_shadowMapSize.min( _maxShadowMapSize );
26573  
26574				if ( isPointLight ) {
26575  
26576					var vpWidth = _shadowMapSize.x;
26577					var vpHeight = _shadowMapSize.y;
26578  
26579					// These viewports map a cube-map onto a 2D texture with the
26580					// following orientation:
26581					//
26582					//  xzXZ
26583					//   y Y
26584					//
26585					// X - Positive x direction
26586					// x - Negative x direction
26587					// Y - Positive y direction
26588					// y - Negative y direction
26589					// Z - Positive z direction
26590					// z - Negative z direction
26591  
26592					// positive X
26593					cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
26594					// negative X
26595					cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
26596					// positive Z
26597					cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
26598					// negative Z
26599					cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
26600					// positive Y
26601					cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
26602					// negative Y
26603					cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
26604  
26605					_shadowMapSize.x *= 4.0;
26606					_shadowMapSize.y *= 2.0;
26607  
26608				}
26609  
26610				if ( shadow.map === null ) {
26611  
26612					var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
26613  
26614					shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
26615					shadow.map.texture.name = light.name + ".shadowMap";
26616  
26617					shadowCamera.updateProjectionMatrix();
26618  
26619				}
26620  
26621				if ( shadow.isSpotLightShadow ) {
26622  
26623					shadow.update( light );
26624  
26625				}
26626  
26627				var shadowMap = shadow.map;
26628				var shadowMatrix = shadow.matrix;
26629  
26630				_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
26631				shadowCamera.position.copy( _lightPositionWorld );
26632  
26633				if ( isPointLight ) {
26634  
26635					faceCount = 6;
26636  
26637					// for point lights we set the shadow matrix to be a translation-only matrix
26638					// equal to inverse of the light's position
26639  
26640					shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
26641  
26642				} else {
26643  
26644					faceCount = 1;
26645  
26646					_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
26647					shadowCamera.lookAt( _lookTarget );
26648					shadowCamera.updateMatrixWorld();
26649  
26650					// compute shadow matrix
26651  
26652					shadowMatrix.set(
26653						0.5, 0.0, 0.0, 0.5,
26654						0.0, 0.5, 0.0, 0.5,
26655						0.0, 0.0, 0.5, 0.5,
26656						0.0, 0.0, 0.0, 1.0
26657					);
26658  
26659					shadowMatrix.multiply( shadowCamera.projectionMatrix );
26660					shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
26661  
26662				}
26663  
26664				_renderer.setRenderTarget( shadowMap );
26665				_renderer.clear();
26666  
26667				// render shadow map for each cube face (if omni-directional) or
26668				// run a single pass if not
26669  
26670				for ( var face = 0; face < faceCount; face ++ ) {
26671  
26672					if ( isPointLight ) {
26673  
26674						_lookTarget.copy( shadowCamera.position );
26675						_lookTarget.add( cubeDirections[ face ] );
26676						shadowCamera.up.copy( cubeUps[ face ] );
26677						shadowCamera.lookAt( _lookTarget );
26678						shadowCamera.updateMatrixWorld();
26679  
26680						var vpDimensions = cube2DViewPorts[ face ];
26681						_state.viewport( vpDimensions );
26682  
26683					}
26684  
26685					// update camera matrices and frustum
26686  
26687					_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
26688					_frustum.setFromMatrix( _projScreenMatrix );
26689  
26690					// set object matrices & frustum culling
26691  
26692					renderObject( scene, camera, shadowCamera, isPointLight );
26693  
26694				}
26695  
26696			}
26697  
26698			scope.needsUpdate = false;
26699  
26700		};
26701  
26702		function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
26703  
26704			var geometry = object.geometry;
26705  
26706			var result = null;
26707  
26708			var materialVariants = _depthMaterials;
26709			var customMaterial = object.customDepthMaterial;
26710  
26711			if ( isPointLight ) {
26712  
26713				materialVariants = _distanceMaterials;
26714				customMaterial = object.customDistanceMaterial;
26715  
26716			}
26717  
26718			if ( ! customMaterial ) {
26719  
26720				var useMorphing = false;
26721  
26722				if ( material.morphTargets ) {
26723  
26724					if ( geometry && geometry.isBufferGeometry ) {
26725  
26726						useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
26727  
26728					} else if ( geometry && geometry.isGeometry ) {
26729  
26730						useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
26731  
26732					}
26733  
26734				}
26735  
26736				if ( object.isSkinnedMesh && material.skinning === false ) {
26737  
26738					console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
26739  
26740				}
26741  
26742				var useSkinning = object.isSkinnedMesh && material.skinning;
26743  
26744				var variantIndex = 0;
26745  
26746				if ( useMorphing ) variantIndex |= _MorphingFlag;
26747				if ( useSkinning ) variantIndex |= _SkinningFlag;
26748  
26749				result = materialVariants[ variantIndex ];
26750  
26751			} else {
26752  
26753				result = customMaterial;
26754  
26755			}
26756  
26757			if ( _renderer.localClippingEnabled &&
26758					material.clipShadows === true &&
26759					material.clippingPlanes.length !== 0 ) {
26760  
26761				// in this case we need a unique material instance reflecting the
26762				// appropriate state
26763  
26764				var keyA = result.uuid, keyB = material.uuid;
26765  
26766				var materialsForVariant = _materialCache[ keyA ];
26767  
26768				if ( materialsForVariant === undefined ) {
26769  
26770					materialsForVariant = {};
26771					_materialCache[ keyA ] = materialsForVariant;
26772  
26773				}
26774  
26775				var cachedMaterial = materialsForVariant[ keyB ];
26776  
26777				if ( cachedMaterial === undefined ) {
26778  
26779					cachedMaterial = result.clone();
26780					materialsForVariant[ keyB ] = cachedMaterial;
26781  
26782				}
26783  
26784				result = cachedMaterial;
26785  
26786			}
26787  
26788			result.visible = material.visible;
26789			result.wireframe = material.wireframe;
26790  
26791			result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
26792  
26793			result.clipShadows = material.clipShadows;
26794			result.clippingPlanes = material.clippingPlanes;
26795			result.clipIntersection = material.clipIntersection;
26796  
26797			result.wireframeLinewidth = material.wireframeLinewidth;
26798			result.linewidth = material.linewidth;
26799  
26800			if ( isPointLight && result.isMeshDistanceMaterial ) {
26801  
26802				result.referencePosition.copy( lightPositionWorld );
26803				result.nearDistance = shadowCameraNear;
26804				result.farDistance = shadowCameraFar;
26805  
26806			}
26807  
26808			return result;
26809  
26810		}
26811  
26812		function renderObject( object, camera, shadowCamera, isPointLight ) {
26813  
26814			if ( object.visible === false ) return;
26815  
26816			var visible = object.layers.test( camera.layers );
26817  
26818			if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
26819  
26820				if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
26821  
26822					object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
26823  
26824					var geometry = _objects.update( object );
26825					var material = object.material;
26826  
26827					if ( Array.isArray( material ) ) {
26828  
26829						var groups = geometry.groups;
26830  
26831						for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
26832  
26833							var group = groups[ k ];
26834							var groupMaterial = material[ group.materialIndex ];
26835  
26836							if ( groupMaterial && groupMaterial.visible ) {
26837  
26838								var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
26839								_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
26840  
26841							}
26842  
26843						}
26844  
26845					} else if ( material.visible ) {
26846  
26847						var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
26848						_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
26849  
26850					}
26851  
26852				}
26853  
26854			}
26855  
26856			var children = object.children;
26857  
26858			for ( var i = 0, l = children.length; i < l; i ++ ) {
26859  
26860				renderObject( children[ i ], camera, shadowCamera, isPointLight );
26861  
26862			}
26863  
26864		}
26865  
26866	}
26867  
26868	/**
26869	 * @author mrdoob / http://mrdoob.com/
26870	 */
26871  
26872	function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
26873  
26874		Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
26875  
26876		this.needsUpdate = true;
26877  
26878	}
26879  
26880	CanvasTexture.prototype = Object.create( Texture.prototype );
26881	CanvasTexture.prototype.constructor = CanvasTexture;
26882	CanvasTexture.prototype.isCanvasTexture = true;
26883  
26884	/**
26885	 * @author mikael emtinger / http://gomo.se/
26886	 * @author alteredq / http://alteredqualia.com/
26887	 */
26888  
26889	function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
26890  
26891		var vertexBuffer, elementBuffer;
26892		var program, attributes, uniforms;
26893  
26894		var texture;
26895  
26896		// decompose matrixWorld
26897  
26898		var spritePosition = new Vector3();
26899		var spriteRotation = new Quaternion();
26900		var spriteScale = new Vector3();
26901  
26902		function init() {
26903  
26904			var vertices = new Float32Array( [
26905				- 0.5, - 0.5, 0, 0,
26906				  0.5, - 0.5, 1, 0,
26907				  0.5, 0.5, 1, 1,
26908				- 0.5, 0.5, 0, 1
26909			] );
26910  
26911			var faces = new Uint16Array( [
26912				0, 1, 2,
26913				0, 2, 3
26914			] );
26915  
26916			vertexBuffer = gl.createBuffer();
26917			elementBuffer = gl.createBuffer();
26918  
26919			gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
26920			gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
26921  
26922			gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
26923			gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
26924  
26925			program = createProgram();
26926  
26927			attributes = {
26928				position: gl.getAttribLocation( program, 'position' ),
26929				uv: gl.getAttribLocation( program, 'uv' )
26930			};
26931  
26932			uniforms = {
26933				uvOffset: gl.getUniformLocation( program, 'uvOffset' ),
26934				uvScale: gl.getUniformLocation( program, 'uvScale' ),
26935  
26936				rotation: gl.getUniformLocation( program, 'rotation' ),
26937				center: gl.getUniformLocation( program, 'center' ),
26938				scale: gl.getUniformLocation( program, 'scale' ),
26939  
26940				color: gl.getUniformLocation( program, 'color' ),
26941				map: gl.getUniformLocation( program, 'map' ),
26942				opacity: gl.getUniformLocation( program, 'opacity' ),
26943  
26944				modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ),
26945				projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ),
26946  
26947				fogType: gl.getUniformLocation( program, 'fogType' ),
26948				fogDensity: gl.getUniformLocation( program, 'fogDensity' ),
26949				fogNear: gl.getUniformLocation( program, 'fogNear' ),
26950				fogFar: gl.getUniformLocation( program, 'fogFar' ),
26951				fogColor: gl.getUniformLocation( program, 'fogColor' ),
26952				fogDepth: gl.getUniformLocation( program, 'fogDepth' ),
26953  
26954				alphaTest: gl.getUniformLocation( program, 'alphaTest' )
26955			};
26956  
26957			var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
26958			canvas.width = 8;
26959			canvas.height = 8;
26960  
26961			var context = canvas.getContext( '2d' );
26962			context.fillStyle = 'white';
26963			context.fillRect( 0, 0, 8, 8 );
26964  
26965			texture = new CanvasTexture( canvas );
26966  
26967		}
26968  
26969		this.render = function ( sprites, scene, camera ) {
26970  
26971			if ( sprites.length === 0 ) return;
26972  
26973			// setup gl
26974  
26975			if ( program === undefined ) {
26976  
26977				init();
26978  
26979			}
26980  
26981			state.useProgram( program );
26982  
26983			state.initAttributes();
26984			state.enableAttribute( attributes.position );
26985			state.enableAttribute( attributes.uv );
26986			state.disableUnusedAttributes();
26987  
26988			state.disable( gl.CULL_FACE );
26989			state.enable( gl.BLEND );
26990  
26991			gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
26992			gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
26993			gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
26994  
26995			gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
26996  
26997			gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
26998  
26999			state.activeTexture( gl.TEXTURE0 );
27000			gl.uniform1i( uniforms.map, 0 );
27001  
27002			var oldFogType = 0;
27003			var sceneFogType = 0;
27004			var fog = scene.fog;
27005  
27006			if ( fog ) {
27007  
27008				gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
27009  
27010				if ( fog.isFog ) {
27011  
27012					gl.uniform1f( uniforms.fogNear, fog.near );
27013					gl.uniform1f( uniforms.fogFar, fog.far );
27014  
27015					gl.uniform1i( uniforms.fogType, 1 );
27016					oldFogType = 1;
27017					sceneFogType = 1;
27018  
27019				} else if ( fog.isFogExp2 ) {
27020  
27021					gl.uniform1f( uniforms.fogDensity, fog.density );
27022  
27023					gl.uniform1i( uniforms.fogType, 2 );
27024					oldFogType = 2;
27025					sceneFogType = 2;
27026  
27027				}
27028  
27029			} else {
27030  
27031				gl.uniform1i( uniforms.fogType, 0 );
27032				oldFogType = 0;
27033				sceneFogType = 0;
27034  
27035			}
27036  
27037  
27038			// update positions and sort
27039  
27040			for ( var i = 0, l = sprites.length; i < l; i ++ ) {
27041  
27042				var sprite = sprites[ i ];
27043  
27044				sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
27045				sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
27046  
27047			}
27048  
27049			sprites.sort( painterSortStable );
27050  
27051			// render all sprites
27052  
27053			var scale = [];
27054			var center = [];
27055  
27056			for ( var i = 0, l = sprites.length; i < l; i ++ ) {
27057  
27058				var sprite = sprites[ i ];
27059				var material = sprite.material;
27060  
27061				if ( material.visible === false ) continue;
27062  
27063				sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
27064  
27065				gl.uniform1f( uniforms.alphaTest, material.alphaTest );
27066				gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
27067  
27068				sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
27069  
27070				scale[ 0 ] = spriteScale.x;
27071				scale[ 1 ] = spriteScale.y;
27072  
27073				center[ 0 ] = sprite.center.x - 0.5;
27074				center[ 1 ] = sprite.center.y - 0.5;
27075  
27076				var fogType = 0;
27077  
27078				if ( scene.fog && material.fog ) {
27079  
27080					fogType = sceneFogType;
27081  
27082				}
27083  
27084				if ( oldFogType !== fogType ) {
27085  
27086					gl.uniform1i( uniforms.fogType, fogType );
27087					oldFogType = fogType;
27088  
27089				}
27090  
27091				if ( material.map !== null ) {
27092  
27093					gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
27094					gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
27095  
27096				} else {
27097  
27098					gl.uniform2f( uniforms.uvOffset, 0, 0 );
27099					gl.uniform2f( uniforms.uvScale, 1, 1 );
27100  
27101				}
27102  
27103				gl.uniform1f( uniforms.opacity, material.opacity );
27104				gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
27105  
27106				gl.uniform1f( uniforms.rotation, material.rotation );
27107				gl.uniform2fv( uniforms.center, center );
27108				gl.uniform2fv( uniforms.scale, scale );
27109  
27110				state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
27111				state.buffers.depth.setTest( material.depthTest );
27112				state.buffers.depth.setMask( material.depthWrite );
27113				state.buffers.color.setMask( material.colorWrite );
27114  
27115				textures.setTexture2D( material.map || texture, 0 );
27116  
27117				gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
27118  
27119				sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
27120  
27121			}
27122  
27123			// restore gl
27124  
27125			state.enable( gl.CULL_FACE );
27126  
27127			state.reset();
27128  
27129		};
27130  
27131		function createProgram() {
27132  
27133			var program = gl.createProgram();
27134  
27135			var vertexShader = gl.createShader( gl.VERTEX_SHADER );
27136			var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
27137  
27138			gl.shaderSource( vertexShader, [
27139  
27140				'precision ' + capabilities.precision + ' float;',
27141  
27142				'#define SHADER_NAME ' + 'SpriteMaterial',
27143  
27144				'uniform mat4 modelViewMatrix;',
27145				'uniform mat4 projectionMatrix;',
27146				'uniform float rotation;',
27147				'uniform vec2 center;',
27148				'uniform vec2 scale;',
27149				'uniform vec2 uvOffset;',
27150				'uniform vec2 uvScale;',
27151  
27152				'attribute vec2 position;',
27153				'attribute vec2 uv;',
27154  
27155				'varying vec2 vUV;',
27156				'varying float fogDepth;',
27157  
27158				'void main() {',
27159  
27160				'	vUV = uvOffset + uv * uvScale;',
27161  
27162				'	vec2 alignedPosition = ( position - center ) * scale;',
27163  
27164				'	vec2 rotatedPosition;',
27165				'	rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
27166				'	rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
27167  
27168				'	vec4 mvPosition;',
27169  
27170				'	mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
27171				'	mvPosition.xy += rotatedPosition;',
27172  
27173				'	gl_Position = projectionMatrix * mvPosition;',
27174  
27175				'	fogDepth = - mvPosition.z;',
27176  
27177				'}'
27178  
27179			].join( '\n' ) );
27180  
27181			gl.shaderSource( fragmentShader, [
27182  
27183				'precision ' + capabilities.precision + ' float;',
27184  
27185				'#define SHADER_NAME ' + 'SpriteMaterial',
27186  
27187				'uniform vec3 color;',
27188				'uniform sampler2D map;',
27189				'uniform float opacity;',
27190  
27191				'uniform int fogType;',
27192				'uniform vec3 fogColor;',
27193				'uniform float fogDensity;',
27194				'uniform float fogNear;',
27195				'uniform float fogFar;',
27196				'uniform float alphaTest;',
27197  
27198				'varying vec2 vUV;',
27199				'varying float fogDepth;',
27200  
27201				'void main() {',
27202  
27203				'	vec4 texture = texture2D( map, vUV );',
27204  
27205				'	gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
27206  
27207				'	if ( gl_FragColor.a < alphaTest ) discard;',
27208  
27209				'	if ( fogType > 0 ) {',
27210  
27211				'		float fogFactor = 0.0;',
27212  
27213				'		if ( fogType == 1 ) {',
27214  
27215				'			fogFactor = smoothstep( fogNear, fogFar, fogDepth );',
27216  
27217				'		} else {',
27218  
27219				'			const float LOG2 = 1.442695;',
27220				'			fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );',
27221				'			fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
27222  
27223				'		}',
27224  
27225				'		gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );',
27226  
27227				'	}',
27228  
27229				'}'
27230  
27231			].join( '\n' ) );
27232  
27233			gl.compileShader( vertexShader );
27234			gl.compileShader( fragmentShader );
27235  
27236			gl.attachShader( program, vertexShader );
27237			gl.attachShader( program, fragmentShader );
27238  
27239			gl.linkProgram( program );
27240  
27241			return program;
27242  
vendor: 5,248 bytes, lines 27243-27553
27243		}
27244  
27245		function painterSortStable( a, b ) {
27246  
27247			if ( a.renderOrder !== b.renderOrder ) {
27248  
27249				return a.renderOrder - b.renderOrder;
27250  
27251			} else if ( a.z !== b.z ) {
27252  
27253				return b.z - a.z;
27254  
27255			} else {
27256  
27257				return b.id - a.id;
27258  
27259			}
27260  
27261		}
27262  
27263	}
27264  
27265	/**
27266	 * @author mrdoob / http://mrdoob.com/
27267	 */
27268  
27269	function WebGLState( gl, extensions, utils ) {
27270  
27271		function ColorBuffer() {
27272  
27273			var locked = false;
27274  
27275			var color = new Vector4();
27276			var currentColorMask = null;
27277			var currentColorClear = new Vector4( 0, 0, 0, 0 );
27278  
27279			return {
27280  
27281				setMask: function ( colorMask ) {
27282  
27283					if ( currentColorMask !== colorMask && ! locked ) {
27284  
27285						gl.colorMask( colorMask, colorMask, colorMask, colorMask );
27286						currentColorMask = colorMask;
27287  
27288					}
27289  
27290				},
27291  
27292				setLocked: function ( lock ) {
27293  
27294					locked = lock;
27295  
27296				},
27297  
27298				setClear: function ( r, g, b, a, premultipliedAlpha ) {
27299  
27300					if ( premultipliedAlpha === true ) {
27301  
27302						r *= a; g *= a; b *= a;
27303  
27304					}
27305  
27306					color.set( r, g, b, a );
27307  
27308					if ( currentColorClear.equals( color ) === false ) {
27309  
27310						gl.clearColor( r, g, b, a );
27311						currentColorClear.copy( color );
27312  
27313					}
27314  
27315				},
27316  
27317				reset: function () {
27318  
27319					locked = false;
27320  
27321					currentColorMask = null;
27322					currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
27323  
27324				}
27325  
27326			};
27327  
27328		}
27329  
27330		function DepthBuffer() {
27331  
27332			var locked = false;
27333  
27334			var currentDepthMask = null;
27335			var currentDepthFunc = null;
27336			var currentDepthClear = null;
27337  
27338			return {
27339  
27340				setTest: function ( depthTest ) {
27341  
27342					if ( depthTest ) {
27343  
27344						enable( gl.DEPTH_TEST );
27345  
27346					} else {
27347  
27348						disable( gl.DEPTH_TEST );
27349  
27350					}
27351  
27352				},
27353  
27354				setMask: function ( depthMask ) {
27355  
27356					if ( currentDepthMask !== depthMask && ! locked ) {
27357  
27358						gl.depthMask( depthMask );
27359						currentDepthMask = depthMask;
27360  
27361					}
27362  
27363				},
27364  
27365				setFunc: function ( depthFunc ) {
27366  
27367					if ( currentDepthFunc !== depthFunc ) {
27368  
27369						if ( depthFunc ) {
27370  
27371							switch ( depthFunc ) {
27372  
27373								case NeverDepth:
27374  
27375									gl.depthFunc( gl.NEVER );
27376									break;
27377  
27378								case AlwaysDepth:
27379  
27380									gl.depthFunc( gl.ALWAYS );
27381									break;
27382  
27383								case LessDepth:
27384  
27385									gl.depthFunc( gl.LESS );
27386									break;
27387  
27388								case LessEqualDepth:
27389  
27390									gl.depthFunc( gl.LEQUAL );
27391									break;
27392  
27393								case EqualDepth:
27394  
27395									gl.depthFunc( gl.EQUAL );
27396									break;
27397  
27398								case GreaterEqualDepth:
27399  
27400									gl.depthFunc( gl.GEQUAL );
27401									break;
27402  
27403								case GreaterDepth:
27404  
27405									gl.depthFunc( gl.GREATER );
27406									break;
27407  
27408								case NotEqualDepth:
27409  
27410									gl.depthFunc( gl.NOTEQUAL );
27411									break;
27412  
27413								default:
27414  
27415									gl.depthFunc( gl.LEQUAL );
27416  
27417							}
27418  
27419						} else {
27420  
27421							gl.depthFunc( gl.LEQUAL );
27422  
27423						}
27424  
27425						currentDepthFunc = depthFunc;
27426  
27427					}
27428  
27429				},
27430  
27431				setLocked: function ( lock ) {
27432  
27433					locked = lock;
27434  
27435				},
27436  
27437				setClear: function ( depth ) {
27438  
27439					if ( currentDepthClear !== depth ) {
27440  
27441						gl.clearDepth( depth );
27442						currentDepthClear = depth;
27443  
27444					}
27445  
27446				},
27447  
27448				reset: function () {
27449  
27450					locked = false;
27451  
27452					currentDepthMask = null;
27453					currentDepthFunc = null;
27454					currentDepthClear = null;
27455  
27456				}
27457  
27458			};
27459  
27460		}
27461  
27462		function StencilBuffer() {
27463  
27464			var locked = false;
27465  
27466			var currentStencilMask = null;
27467			var currentStencilFunc = null;
27468			var currentStencilRef = null;
27469			var currentStencilFuncMask = null;
27470			var currentStencilFail = null;
27471			var currentStencilZFail = null;
27472			var currentStencilZPass = null;
27473			var currentStencilClear = null;
27474  
27475			return {
27476  
27477				setTest: function ( stencilTest ) {
27478  
27479					if ( stencilTest ) {
27480  
27481						enable( gl.STENCIL_TEST );
27482  
27483					} else {
27484  
27485						disable( gl.STENCIL_TEST );
27486  
27487					}
27488  
27489				},
27490  
27491				setMask: function ( stencilMask ) {
27492  
27493					if ( currentStencilMask !== stencilMask && ! locked ) {
27494  
27495						gl.stencilMask( stencilMask );
27496						currentStencilMask = stencilMask;
27497  
27498					}
27499  
27500				},
27501  
27502				setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
27503  
27504					if ( currentStencilFunc !== stencilFunc ||
27505						 currentStencilRef 	!== stencilRef 	||
27506						 currentStencilFuncMask !== stencilMask ) {
27507  
27508						gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
27509  
27510						currentStencilFunc = stencilFunc;
27511						currentStencilRef = stencilRef;
27512						currentStencilFuncMask = stencilMask;
27513  
27514					}
27515  
27516				},
27517  
27518				setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
27519  
27520					if ( currentStencilFail	 !== stencilFail 	||
27521						 currentStencilZFail !== stencilZFail ||
27522						 currentStencilZPass !== stencilZPass ) {
27523  
27524						gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
27525  
27526						currentStencilFail = stencilFail;
27527						currentStencilZFail = stencilZFail;
27528						currentStencilZPass = stencilZPass;
27529  
27530					}
27531  
27532				},
27533  
27534				setLocked: function ( lock ) {
27535  
27536					locked = lock;
27537  
27538				},
27539  
27540				setClear: function ( stencil ) {
27541  
27542					if ( currentStencilClear !== stencil ) {
27543  
27544						gl.clearStencil( stencil );
27545						currentStencilClear = stencil;
27546  
27547					}
27548  
27549				},
27550  
27551				reset: function () {
27552  
27553					locked = false;
27554  
27555					currentStencilMask = null;
27556					currentStencilFunc = null;
27557					currentStencilRef = null;
27558					currentStencilFuncMask = null;
27559					currentStencilFail = null;
27560					currentStencilZFail = null;
27561					currentStencilZPass = null;
27562					currentStencilClear = null;
27563  
27564				}
27565  
27566			};
27567  
27568		}
27569  
27570		//
27571  
27572		var colorBuffer = new ColorBuffer();
27573		var depthBuffer = new DepthBuffer();
27574		var stencilBuffer = new StencilBuffer();
27575  
27576		var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
27577		var newAttributes = new Uint8Array( maxVertexAttributes );
27578		var enabledAttributes = new Uint8Array( maxVertexAttributes );
27579		var attributeDivisors = new Uint8Array( maxVertexAttributes );
27580  
27581		var capabilities = {};
27582  
27583		var compressedTextureFormats = null;
27584  
27585		var currentProgram = null;
27586  
27587		var currentBlending = null;
27588		var currentBlendEquation = null;
27589		var currentBlendSrc = null;
27590		var currentBlendDst = null;
27591		var currentBlendEquationAlpha = null;
27592		var currentBlendSrcAlpha = null;
27593		var currentBlendDstAlpha = null;
27594		var currentPremultipledAlpha = false;
27595  
27596		var currentFlipSided = null;
27597		var currentCullFace = null;
27598  
27599		var currentLineWidth = null;
27600  
27601		var currentPolygonOffsetFactor = null;
27602		var currentPolygonOffsetUnits = null;
27603  
27604		var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
27605  
27606		var lineWidthAvailable = false;
27607		var version = 0;
27608		var glVersion = gl.getParameter( gl.VERSION );
27609  
27610		if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
27611  
27612			version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
27613			lineWidthAvailable = ( version >= 1.0 );
27614  
27615		} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
27616  
27617			version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
27618			lineWidthAvailable = ( version >= 2.0 );
27619  
27620		}
27621  
27622		var currentTextureSlot = null;
27623		var currentBoundTextures = {};
27624  
27625		var currentScissor = new Vector4();
27626		var currentViewport = new Vector4();
27627  
27628		function createTexture( type, target, count ) {
27629  
27630			var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
27631			var texture = gl.createTexture();
27632  
27633			gl.bindTexture( type, texture );
27634			gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
27635			gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
27636  
27637			for ( var i = 0; i < count; i ++ ) {
27638  
27639				gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
27640  
27641			}
27642  
27643			return texture;
27644  
27645		}
27646  
27647		var emptyTextures = {};
27648		emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
27649		emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
27650  
27651		// init
27652  
27653		colorBuffer.setClear( 0, 0, 0, 1 );
27654		depthBuffer.setClear( 1 );
27655		stencilBuffer.setClear( 0 );
27656  
27657		enable( gl.DEPTH_TEST );
27658		depthBuffer.setFunc( LessEqualDepth );
27659  
27660		setFlipSided( false );
27661		setCullFace( CullFaceBack );
27662		enable( gl.CULL_FACE );
27663  
27664		enable( gl.BLEND );
27665		setBlending( NormalBlending );
27666  
27667		//
27668  
27669		function initAttributes() {
27670  
27671			for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
27672  
27673				newAttributes[ i ] = 0;
27674  
27675			}
27676  
27677		}
27678  
27679		function enableAttribute( attribute ) {
27680  
27681			enableAttributeAndDivisor( attribute, 0 );
27682  
27683		}
27684  
27685		function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
27686  
27687			newAttributes[ attribute ] = 1;
27688  
27689			if ( enabledAttributes[ attribute ] === 0 ) {
27690  
27691				gl.enableVertexAttribArray( attribute );
27692				enabledAttributes[ attribute ] = 1;
27693  
27694			}
27695  
27696			if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
27697  
27698				var extension = extensions.get( 'ANGLE_instanced_arrays' );
27699  
27700				extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
27701				attributeDivisors[ attribute ] = meshPerAttribute;
27702  
27703			}
27704  
27705		}
27706  
27707		function disableUnusedAttributes() {
27708  
27709			for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
27710  
27711				if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
27712  
27713					gl.disableVertexAttribArray( i );
27714					enabledAttributes[ i ] = 0;
27715  
27716				}
27717  
27718			}
27719  
27720		}
27721  
27722		function enable( id ) {
27723  
27724			if ( capabilities[ id ] !== true ) {
27725  
27726				gl.enable( id );
27727				capabilities[ id ] = true;
27728  
27729			}
27730  
27731		}
27732  
27733		function disable( id ) {
27734  
27735			if ( capabilities[ id ] !== false ) {
27736  
27737				gl.disable( id );
27738				capabilities[ id ] = false;
27739  
27740			}
27741  
27742		}
27743  
27744		function getCompressedTextureFormats() {
27745  
27746			if ( compressedTextureFormats === null ) {
27747  
27748				compressedTextureFormats = [];
27749  
27750				if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
27751					 extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
27752					 extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
27753					 extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
27754  
27755					var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
27756  
27757					for ( var i = 0; i < formats.length; i ++ ) {
27758  
27759						compressedTextureFormats.push( formats[ i ] );
27760  
27761					}
27762  
27763				}
27764  
27765			}
27766  
27767			return compressedTextureFormats;
27768  
27769		}
27770  
27771		function useProgram( program ) {
27772  
27773			if ( currentProgram !== program ) {
27774  
27775				gl.useProgram( program );
27776  
27777				currentProgram = program;
27778  
27779				return true;
27780  
27781			}
27782  
27783			return false;
27784  
27785		}
27786  
27787		function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
27788  
27789			if ( blending !== NoBlending ) {
27790  
27791				enable( gl.BLEND );
27792  
27793			} else {
27794  
27795				disable( gl.BLEND );
27796  
27797			}
27798  
27799			if ( blending !== CustomBlending ) {
27800  
27801				if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
27802  
27803					switch ( blending ) {
27804  
27805						case AdditiveBlending:
27806  
27807							if ( premultipliedAlpha ) {
27808  
27809								gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27810								gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
27811  
27812							} else {
27813  
27814								gl.blendEquation( gl.FUNC_ADD );
27815								gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
27816  
27817							}
27818							break;
27819  
27820						case SubtractiveBlending:
27821  
27822							if ( premultipliedAlpha ) {
27823  
27824								gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27825								gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );
27826  
27827							} else {
27828  
27829								gl.blendEquation( gl.FUNC_ADD );
27830								gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
27831  
27832							}
27833							break;
27834  
27835						case MultiplyBlending:
27836  
27837							if ( premultipliedAlpha ) {
27838  
27839								gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27840								gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
27841  
27842							} else {
27843  
27844								gl.blendEquation( gl.FUNC_ADD );
27845								gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
27846  
27847							}
27848							break;
27849  
27850						default:
27851  
27852							if ( premultipliedAlpha ) {
27853  
27854								gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27855								gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
27856  
27857							} else {
27858  
27859								gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27860								gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
27861  
27862							}
27863  
27864					}
27865  
27866				}
27867  
27868				currentBlendEquation = null;
27869				currentBlendSrc = null;
27870				currentBlendDst = null;
27871				currentBlendEquationAlpha = null;
27872				currentBlendSrcAlpha = null;
27873				currentBlendDstAlpha = null;
27874  
27875			} else {
27876  
27877				blendEquationAlpha = blendEquationAlpha || blendEquation;
27878				blendSrcAlpha = blendSrcAlpha || blendSrc;
27879				blendDstAlpha = blendDstAlpha || blendDst;
27880  
27881				if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
27882  
27883					gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );
27884  
27885					currentBlendEquation = blendEquation;
27886					currentBlendEquationAlpha = blendEquationAlpha;
27887  
27888				}
27889  
27890				if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
27891  
27892					gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );
27893  
27894					currentBlendSrc = blendSrc;
27895					currentBlendDst = blendDst;
27896					currentBlendSrcAlpha = blendSrcAlpha;
27897					currentBlendDstAlpha = blendDstAlpha;
27898  
27899				}
27900  
27901			}
27902  
27903			currentBlending = blending;
27904			currentPremultipledAlpha = premultipliedAlpha;
27905  
27906		}
27907  
27908		function setMaterial( material, frontFaceCW ) {
27909  
27910			material.side === DoubleSide
27911				? disable( gl.CULL_FACE )
27912				: enable( gl.CULL_FACE );
27913  
27914			var flipSided = ( material.side === BackSide );
27915			if ( frontFaceCW ) flipSided = ! flipSided;
27916  
27917			setFlipSided( flipSided );
27918  
27919			material.transparent === true
27920				? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
27921				: setBlending( NoBlending );
27922  
27923			depthBuffer.setFunc( material.depthFunc );
27924			depthBuffer.setTest( material.depthTest );
27925			depthBuffer.setMask( material.depthWrite );
27926			colorBuffer.setMask( material.colorWrite );
27927  
27928			setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
27929  
27930		}
27931  
27932		//
27933  
27934		function setFlipSided( flipSided ) {
27935  
27936			if ( currentFlipSided !== flipSided ) {
27937  
27938				if ( flipSided ) {
27939  
27940					gl.frontFace( gl.CW );
27941  
27942				} else {
27943  
27944					gl.frontFace( gl.CCW );
27945  
27946				}
27947  
27948				currentFlipSided = flipSided;
27949  
27950			}
27951  
27952		}
27953  
27954		function setCullFace( cullFace ) {
27955  
27956			if ( cullFace !== CullFaceNone ) {
27957  
27958				enable( gl.CULL_FACE );
27959  
27960				if ( cullFace !== currentCullFace ) {
27961  
27962					if ( cullFace === CullFaceBack ) {
27963  
27964						gl.cullFace( gl.BACK );
27965  
27966					} else if ( cullFace === CullFaceFront ) {
27967  
27968						gl.cullFace( gl.FRONT );
27969  
27970					} else {
27971  
27972						gl.cullFace( gl.FRONT_AND_BACK );
27973  
27974					}
27975  
27976				}
27977  
27978			} else {
27979  
27980				disable( gl.CULL_FACE );
27981  
27982			}
27983  
27984			currentCullFace = cullFace;
27985  
27986		}
27987  
27988		function setLineWidth( width ) {
27989  
27990			if ( width !== currentLineWidth ) {
27991  
27992				if ( lineWidthAvailable ) gl.lineWidth( width );
27993  
27994				currentLineWidth = width;
27995  
27996			}
27997  
27998		}
27999  
28000		function setPolygonOffset( polygonOffset, factor, units ) {
28001  
28002			if ( polygonOffset ) {
28003  
28004				enable( gl.POLYGON_OFFSET_FILL );
28005  
28006				if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
28007  
28008					gl.polygonOffset( factor, units );
28009  
28010					currentPolygonOffsetFactor = factor;
28011					currentPolygonOffsetUnits = units;
28012  
28013				}
28014  
28015			} else {
28016  
28017				disable( gl.POLYGON_OFFSET_FILL );
28018  
28019			}
28020  
28021		}
28022  
28023		function setScissorTest( scissorTest ) {
28024  
28025			if ( scissorTest ) {
28026  
28027				enable( gl.SCISSOR_TEST );
28028  
28029			} else {
28030  
28031				disable( gl.SCISSOR_TEST );
28032  
28033			}
28034  
28035		}
28036  
28037		// texture
28038  
28039		function activeTexture( webglSlot ) {
28040  
28041			if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
28042  
28043			if ( currentTextureSlot !== webglSlot ) {
28044  
28045				gl.activeTexture( webglSlot );
28046				currentTextureSlot = webglSlot;
28047  
28048			}
28049  
28050		}
28051  
28052		function bindTexture( webglType, webglTexture ) {
28053  
28054			if ( currentTextureSlot === null ) {
28055  
28056				activeTexture();
28057  
28058			}
28059  
28060			var boundTexture = currentBoundTextures[ currentTextureSlot ];
28061  
28062			if ( boundTexture === undefined ) {
28063  
28064				boundTexture = { type: undefined, texture: undefined };
28065				currentBoundTextures[ currentTextureSlot ] = boundTexture;
28066  
28067			}
28068  
28069			if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
28070  
28071				gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
28072  
28073				boundTexture.type = webglType;
28074				boundTexture.texture = webglTexture;
28075  
28076			}
28077  
28078		}
28079  
28080		function compressedTexImage2D() {
28081  
28082			try {
28083  
28084				gl.compressedTexImage2D.apply( gl, arguments );
28085  
28086			} catch ( error ) {
28087  
28088				console.error( 'THREE.WebGLState:', error );
28089  
28090			}
28091  
28092		}
28093  
28094		function texImage2D() {
28095  
28096			try {
28097  
28098				gl.texImage2D.apply( gl, arguments );
28099  
28100			} catch ( error ) {
28101  
28102				console.error( 'THREE.WebGLState:', error );
28103  
28104			}
28105  
28106		}
28107  
28108		//
28109  
28110		function scissor( scissor ) {
28111  
28112			if ( currentScissor.equals( scissor ) === false ) {
28113  
28114				gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
28115				currentScissor.copy( scissor );
28116  
28117			}
28118  
28119		}
28120  
28121		function viewport( viewport ) {
28122  
28123			if ( currentViewport.equals( viewport ) === false ) {
28124  
28125				gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
28126				currentViewport.copy( viewport );
28127  
28128			}
28129  
28130		}
28131  
28132		//
28133  
28134		function reset() {
28135  
28136			for ( var i = 0; i < enabledAttributes.length; i ++ ) {
28137  
28138				if ( enabledAttributes[ i ] === 1 ) {
28139  
28140					gl.disableVertexAttribArray( i );
28141					enabledAttributes[ i ] = 0;
28142  
28143				}
28144  
28145			}
28146  
28147			capabilities = {};
28148  
28149			compressedTextureFormats = null;
28150  
28151			currentTextureSlot = null;
28152			currentBoundTextures = {};
28153  
28154			currentProgram = null;
28155  
28156			currentBlending = null;
28157  
28158			currentFlipSided = null;
28159			currentCullFace = null;
28160  
28161			colorBuffer.reset();
28162			depthBuffer.reset();
28163			stencilBuffer.reset();
28164  
28165		}
28166  
28167		return {
28168  
28169			buffers: {
28170				color: colorBuffer,
28171				depth: depthBuffer,
28172				stencil: stencilBuffer
28173			},
28174  
28175			initAttributes: initAttributes,
28176			enableAttribute: enableAttribute,
28177			enableAttributeAndDivisor: enableAttributeAndDivisor,
28178			disableUnusedAttributes: disableUnusedAttributes,
28179			enable: enable,
28180			disable: disable,
28181			getCompressedTextureFormats: getCompressedTextureFormats,
28182  
28183			useProgram: useProgram,
28184  
28185			setBlending: setBlending,
28186			setMaterial: setMaterial,
28187  
28188			setFlipSided: setFlipSided,
28189			setCullFace: setCullFace,
28190  
28191			setLineWidth: setLineWidth,
28192			setPolygonOffset: setPolygonOffset,
28193  
28194			setScissorTest: setScissorTest,
28195  
28196			activeTexture: activeTexture,
28197			bindTexture: bindTexture,
28198			compressedTexImage2D: compressedTexImage2D,
28199			texImage2D: texImage2D,
28200  
28201			scissor: scissor,
28202			viewport: viewport,
28203  
28204			reset: reset
28205  
28206		};
28207  
28208	}
28209  
28210	/**
28211	 * @author mrdoob / http://mrdoob.com/
28212	 */
28213  
28214	function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
28215  
28216		var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
28217		var _videoTextures = {};
28218		var _canvas;
28219  
28220		//
28221  
28222		function clampToMaxSize( image, maxSize ) {
28223  
28224			if ( image.width > maxSize || image.height > maxSize ) {
28225  
28226				if ( 'data' in image ) {
28227  
28228					console.warn( 'THREE.WebGLRenderer: image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
28229					return;
28230  
28231				}
28232  
28233				// Warning: Scaling through the canvas will only work with images that use
28234				// premultiplied alpha.
28235  
28236				var scale = maxSize / Math.max( image.width, image.height );
28237  
28238				var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
28239				canvas.width = Math.floor( image.width * scale );
28240				canvas.height = Math.floor( image.height * scale );
28241  
28242				var context = canvas.getContext( '2d' );
28243				context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
28244  
28245				console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
28246  
28247				return canvas;
28248  
28249			}
28250  
28251			return image;
28252  
28253		}
28254  
28255		function isPowerOfTwo( image ) {
28256  
28257			return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
28258  
28259		}
28260  
28261		function makePowerOfTwo( image ) {
28262  
28263			if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) {
28264  
28265				if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
28266  
28267				_canvas.width = _Math.floorPowerOfTwo( image.width );
28268				_canvas.height = _Math.floorPowerOfTwo( image.height );
28269  
28270				var context = _canvas.getContext( '2d' );
28271				context.drawImage( image, 0, 0, _canvas.width, _canvas.height );
28272  
28273				console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height, image );
28274  
28275				return _canvas;
28276  
28277			}
28278  
28279			return image;
28280  
28281		}
28282  
28283		function textureNeedsPowerOfTwo( texture ) {
28284  
28285			return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
28286				( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
28287  
28288		}
28289  
28290		function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
28291  
28292			return texture.generateMipmaps && isPowerOfTwo &&
28293				texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
28294  
28295		}
28296  
28297		function generateMipmap( target, texture, width, height ) {
28298  
28299			_gl.generateMipmap( target );
28300  
28301			var textureProperties = properties.get( texture );
28302  
28303			// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
28304			textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
28305  
28306		}
28307  
28308		// Fallback filters for non-power-of-2 textures
28309  
28310		function filterFallback( f ) {
28311  
28312			if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
28313  
28314				return _gl.NEAREST;
28315  
28316			}
28317  
28318			return _gl.LINEAR;
28319  
28320		}
28321  
28322		//
28323  
28324		function onTextureDispose( event ) {
28325  
28326			var texture = event.target;
28327  
28328			texture.removeEventListener( 'dispose', onTextureDispose );
28329  
28330			deallocateTexture( texture );
28331  
28332			if ( texture.isVideoTexture ) {
28333  
28334				delete _videoTextures[ texture.id ];
28335  
28336			}
28337  
28338			info.memory.textures --;
28339  
28340		}
28341  
28342		function onRenderTargetDispose( event ) {
28343  
28344			var renderTarget = event.target;
28345  
28346			renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
28347  
28348			deallocateRenderTarget( renderTarget );
28349  
28350			info.memory.textures --;
28351  
28352		}
28353  
28354		//
28355  
28356		function deallocateTexture( texture ) {
28357  
28358			var textureProperties = properties.get( texture );
28359  
28360			if ( texture.image && textureProperties.__image__webglTextureCube ) {
28361  
28362				// cube texture
28363  
28364				_gl.deleteTexture( textureProperties.__image__webglTextureCube );
28365  
28366			} else {
28367  
vendor: 4,521 bytes, lines 28368-28535
28368				// 2D texture
28369  
28370				if ( textureProperties.__webglInit === undefined ) return;
28371  
28372				_gl.deleteTexture( textureProperties.__webglTexture );
28373  
28374			}
28375  
28376			// remove all webgl properties
28377			properties.remove( texture );
28378  
28379		}
28380  
28381		function deallocateRenderTarget( renderTarget ) {
28382  
28383			var renderTargetProperties = properties.get( renderTarget );
28384			var textureProperties = properties.get( renderTarget.texture );
28385  
28386			if ( ! renderTarget ) return;
28387  
28388			if ( textureProperties.__webglTexture !== undefined ) {
28389  
28390				_gl.deleteTexture( textureProperties.__webglTexture );
28391  
28392			}
28393  
28394			if ( renderTarget.depthTexture ) {
28395  
28396				renderTarget.depthTexture.dispose();
28397  
28398			}
28399  
28400			if ( renderTarget.isWebGLRenderTargetCube ) {
28401  
28402				for ( var i = 0; i < 6; i ++ ) {
28403  
28404					_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
28405					if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
28406  
28407				}
28408  
28409			} else {
28410  
28411				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
28412				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
28413  
28414			}
28415  
28416			properties.remove( renderTarget.texture );
28417			properties.remove( renderTarget );
28418  
28419		}
28420  
28421		//
28422  
28423  
28424  
28425		function setTexture2D( texture, slot ) {
28426  
28427			var textureProperties = properties.get( texture );
28428  
28429			if ( texture.isVideoTexture ) updateVideoTexture( texture );
28430  
28431			if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
28432  
28433				var image = texture.image;
28434  
28435				if ( image === undefined ) {
28436  
28437					console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
28438  
28439				} else if ( image.complete === false ) {
28440  
28441					console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
28442  
28443				} else {
28444  
28445					uploadTexture( textureProperties, texture, slot );
28446					return;
28447  
28448				}
28449  
28450			}
28451  
28452			state.activeTexture( _gl.TEXTURE0 + slot );
28453			state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
28454  
28455		}
28456  
28457		function setTextureCube( texture, slot ) {
28458  
28459			var textureProperties = properties.get( texture );
28460  
28461			if ( texture.image.length === 6 ) {
28462  
28463				if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
28464  
28465					if ( ! textureProperties.__image__webglTextureCube ) {
28466  
28467						texture.addEventListener( 'dispose', onTextureDispose );
28468  
28469						textureProperties.__image__webglTextureCube = _gl.createTexture();
28470  
28471						info.memory.textures ++;
28472  
28473					}
28474  
28475					state.activeTexture( _gl.TEXTURE0 + slot );
28476					state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
28477  
28478					_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
28479  
28480					var isCompressed = ( texture && texture.isCompressedTexture );
28481					var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
28482  
28483					var cubeImage = [];
28484  
28485					for ( var i = 0; i < 6; i ++ ) {
28486  
28487						if ( ! isCompressed && ! isDataTexture ) {
28488  
28489							cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
28490  
28491						} else {
28492  
28493							cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
28494  
28495						}
28496  
28497					}
28498  
28499					var image = cubeImage[ 0 ],
28500						isPowerOfTwoImage = isPowerOfTwo( image ),
28501						glFormat = utils.convert( texture.format ),
28502						glType = utils.convert( texture.type );
28503  
28504					setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
28505  
28506					for ( var i = 0; i < 6; i ++ ) {
28507  
28508						if ( ! isCompressed ) {
28509  
28510							if ( isDataTexture ) {
28511  
28512								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
28513  
28514							} else {
28515  
28516								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
28517  
28518							}
28519  
28520						} else {
28521  
28522							var mipmap, mipmaps = cubeImage[ i ].mipmaps;
28523  
28524							for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
28525  
28526								mipmap = mipmaps[ j ];
28527  
28528								if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
28529  
28530									if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
28531  
28532										state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
28533  
28534									} else {
28535  
28536										console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
28537  
28538									}
28539  
28540								} else {
28541  
28542									state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
28543  
28544								}
28545  
28546							}
28547  
28548						}
28549  
28550					}
28551  
28552					if ( ! isCompressed ) {
28553  
28554						textureProperties.__maxMipLevel = 0;
28555  
28556					} else {
28557  
28558						textureProperties.__maxMipLevel = mipmaps.length - 1;
28559  
28560					}
28561  
28562					if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
28563  
28564						// We assume images for cube map have the same size.
28565						generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
28566  
28567					}
28568  
28569					textureProperties.__version = texture.version;
28570  
28571					if ( texture.onUpdate ) texture.onUpdate( texture );
28572  
28573				} else {
28574  
28575					state.activeTexture( _gl.TEXTURE0 + slot );
28576					state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
28577  
28578				}
28579  
28580			}
28581  
28582		}
28583  
28584		function setTextureCubeDynamic( texture, slot ) {
28585  
28586			state.activeTexture( _gl.TEXTURE0 + slot );
28587			state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
28588  
28589		}
28590  
28591		function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
28592  
28593			var extension;
28594  
28595			if ( isPowerOfTwoImage ) {
28596  
28597				_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
28598				_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
28599  
28600				_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
28601				_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
28602  
28603			} else {
28604  
28605				_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
28606				_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
28607  
28608				if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
28609  
28610					console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
28611  
28612				}
28613  
28614				_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
28615				_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
28616  
28617				if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
28618  
28619					console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
28620  
28621				}
28622  
28623			}
28624  
28625			extension = extensions.get( 'EXT_texture_filter_anisotropic' );
28626  
28627			if ( extension ) {
28628  
28629				if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
28630				if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
28631  
28632				if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
28633  
28634					_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
28635					properties.get( texture ).__currentAnisotropy = texture.anisotropy;
28636  
28637				}
28638  
28639			}
28640  
28641		}
28642  
28643		function uploadTexture( textureProperties, texture, slot ) {
28644  
28645			if ( textureProperties.__webglInit === undefined ) {
28646  
28647				textureProperties.__webglInit = true;
28648  
28649				texture.addEventListener( 'dispose', onTextureDispose );
28650  
28651				textureProperties.__webglTexture = _gl.createTexture();
28652  
28653				info.memory.textures ++;
28654  
28655			}
28656  
28657			state.activeTexture( _gl.TEXTURE0 + slot );
28658			state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
28659  
28660			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
28661			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
28662			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
28663  
28664			var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
28665  
28666			if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {
28667  
28668				image = makePowerOfTwo( image );
28669  
28670			}
28671  
28672			var isPowerOfTwoImage = isPowerOfTwo( image ),
28673				glFormat = utils.convert( texture.format ),
28674				glType = utils.convert( texture.type );
28675  
28676			setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
28677  
28678			var mipmap, mipmaps = texture.mipmaps;
28679  
28680			if ( texture.isDepthTexture ) {
28681  
28682				// populate depth texture with dummy data
28683  
28684				var internalFormat = _gl.DEPTH_COMPONENT;
28685  
28686				if ( texture.type === FloatType ) {
28687  
28688					if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
28689					internalFormat = _gl.DEPTH_COMPONENT32F;
28690  
28691				} else if ( _isWebGL2 ) {
28692  
28693					// WebGL 2.0 requires signed internalformat for glTexImage2D
28694					internalFormat = _gl.DEPTH_COMPONENT16;
28695  
28696				}
28697  
28698				if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
28699  
28700					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
28701					// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
28702					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
28703					if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
28704  
28705						console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
28706  
28707						texture.type = UnsignedShortType;
28708						glType = utils.convert( texture.type );
28709  
28710					}
28711  
28712				}
28713  
28714				// Depth stencil textures need the DEPTH_STENCIL internal format
28715				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
28716				if ( texture.format === DepthStencilFormat ) {
28717  
28718					internalFormat = _gl.DEPTH_STENCIL;
28719  
28720					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
28721					// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
28722					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
28723					if ( texture.type !== UnsignedInt248Type ) {
28724  
28725						console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
28726  
28727						texture.type = UnsignedInt248Type;
28728						glType = utils.convert( texture.type );
28729  
28730					}
28731  
28732				}
28733  
28734				state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
28735  
28736			} else if ( texture.isDataTexture ) {
28737  
28738				// use manually created mipmaps if available
28739				// if there are no manual mipmaps
28740				// set 0 level mipmap and then use GL to generate other mipmap levels
28741  
28742				if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
28743  
28744					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
28745  
28746						mipmap = mipmaps[ i ];
28747						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
28748  
28749					}
28750  
28751					texture.generateMipmaps = false;
28752					textureProperties.__maxMipLevel = mipmaps.length - 1;
28753  
28754				} else {
28755  
28756					state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
28757					textureProperties.__maxMipLevel = 0;
28758  
28759				}
28760  
28761			} else if ( texture.isCompressedTexture ) {
28762  
28763				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
28764  
28765					mipmap = mipmaps[ i ];
28766  
28767					if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
28768  
28769						if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
28770  
28771							state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
28772  
28773						} else {
28774  
28775							console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
28776  
28777						}
28778  
28779					} else {
28780  
28781						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
28782  
28783					}
28784  
28785				}
28786  
28787				textureProperties.__maxMipLevel = mipmaps.length - 1;
28788  
28789			} else {
28790  
28791				// regular Texture (image, video, canvas)
28792  
28793				// use manually created mipmaps if available
28794				// if there are no manual mipmaps
28795				// set 0 level mipmap and then use GL to generate other mipmap levels
28796  
28797				if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
28798  
28799					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
28800  
28801						mipmap = mipmaps[ i ];
28802						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
28803  
28804					}
28805  
28806					texture.generateMipmaps = false;
28807					textureProperties.__maxMipLevel = mipmaps.length - 1;
28808  
28809				} else {
28810  
28811					state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
28812					textureProperties.__maxMipLevel = 0;
28813  
28814				}
28815  
28816			}
28817  
28818			if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
28819  
28820				generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
28821  
28822			}
28823  
28824			textureProperties.__version = texture.version;
28825  
28826			if ( texture.onUpdate ) texture.onUpdate( texture );
28827  
28828		}
28829  
28830		// Render targets
28831  
28832		// Setup storage for target texture and bind it to correct framebuffer
28833		function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
28834  
28835			var glFormat = utils.convert( renderTarget.texture.format );
28836			var glType = utils.convert( renderTarget.texture.type );
28837			state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
28838			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
28839			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
28840			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
28841  
28842		}
28843  
28844		// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
28845		function setupRenderBufferStorage( renderbuffer, renderTarget ) {
28846  
28847			_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
28848  
28849			if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
28850  
28851				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
28852				_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
28853  
28854			} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
28855  
28856				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
28857				_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
28858  
28859			} else {
28860  
28861				// FIXME: We don't support !depth !stencil
28862				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
28863  
28864			}
28865  
28866			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
28867  
28868		}
28869  
28870		// Setup resources for a Depth Texture for a FBO (needs an extension)
28871		function setupDepthTexture( framebuffer, renderTarget ) {
28872  
28873			var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
28874			if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
28875  
28876			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
28877  
28878			if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
28879  
28880				throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
28881  
28882			}
28883  
28884			// upload an empty depth texture with framebuffer size
28885			if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
28886					renderTarget.depthTexture.image.width !== renderTarget.width ||
28887					renderTarget.depthTexture.image.height !== renderTarget.height ) {
28888  
28889				renderTarget.depthTexture.image.width = renderTarget.width;
28890				renderTarget.depthTexture.image.height = renderTarget.height;
28891				renderTarget.depthTexture.needsUpdate = true;
28892  
28893			}
28894  
28895			setTexture2D( renderTarget.depthTexture, 0 );
28896  
28897			var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
28898  
28899			if ( renderTarget.depthTexture.format === DepthFormat ) {
28900  
28901				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
28902  
28903			} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
28904  
28905				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
28906  
28907			} else {
28908  
28909				throw new Error( 'Unknown depthTexture format' );
28910  
28911			}
28912  
28913		}
28914  
28915		// Setup GL resources for a non-texture depth buffer
28916		function setupDepthRenderbuffer( renderTarget ) {
28917  
28918			var renderTargetProperties = properties.get( renderTarget );
28919  
28920			var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
28921  
28922			if ( renderTarget.depthTexture ) {
28923  
28924				if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
28925  
28926				setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
28927  
28928			} else {
28929  
28930				if ( isCube ) {
28931  
28932					renderTargetProperties.__webglDepthbuffer = [];
28933  
28934					for ( var i = 0; i < 6; i ++ ) {
28935  
28936						_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
28937						renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
28938						setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
28939  
28940					}
28941  
28942				} else {
28943  
28944					_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
28945					renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
28946					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
28947  
28948				}
28949  
28950			}
28951  
28952			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
28953  
28954		}
28955  
28956		// Set up GL resources for the render target
28957		function setupRenderTarget( renderTarget ) {
28958  
28959			var renderTargetProperties = properties.get( renderTarget );
28960			var textureProperties = properties.get( renderTarget.texture );
28961  
28962			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
28963  
28964			textureProperties.__webglTexture = _gl.createTexture();
28965  
28966			info.memory.textures ++;
28967  
28968			var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
28969			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
28970  
28971			// Setup framebuffer
28972  
28973			if ( isCube ) {
28974  
28975				renderTargetProperties.__webglFramebuffer = [];
28976  
28977				for ( var i = 0; i < 6; i ++ ) {
28978  
28979					renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
28980  
28981				}
28982  
28983			} else {
28984  
28985				renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
28986  
28987			}
28988  
28989			// Setup color buffer
28990  
28991			if ( isCube ) {
28992  
28993				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
28994				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
28995  
28996				for ( var i = 0; i < 6; i ++ ) {
28997  
28998					setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
28999  
29000				}
29001  
29002				if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
29003  
29004					generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
29005  
29006				}
29007  
29008				state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
29009  
29010			} else {
29011  
29012				state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
29013				setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
29014				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
29015  
29016				if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
29017  
29018					generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
29019  
29020				}
29021  
29022				state.bindTexture( _gl.TEXTURE_2D, null );
29023  
29024			}
29025  
29026			// Setup depth and stencil buffers
29027  
29028			if ( renderTarget.depthBuffer ) {
29029  
29030				setupDepthRenderbuffer( renderTarget );
29031  
29032			}
29033  
29034		}
29035  
29036		function updateRenderTargetMipmap( renderTarget ) {
29037  
29038			var texture = renderTarget.texture;
29039			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
29040  
29041			if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
29042  
29043				var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
29044				var webglTexture = properties.get( texture ).__webglTexture;
29045  
29046				state.bindTexture( target, webglTexture );
29047				generateMipmap( target, texture, renderTarget.width, renderTarget.height );
29048				state.bindTexture( target, null );
29049  
29050			}
29051  
29052		}
29053  
29054		function updateVideoTexture( texture ) {
29055  
29056			var id = texture.id;
29057			var frame = info.render.frame;
29058  
29059			// Check the last frame we updated the VideoTexture
29060  
29061			if ( _videoTextures[ id ] !== frame ) {
29062  
29063				_videoTextures[ id ] = frame;
29064				texture.update();
29065  
29066			}
29067  
29068		}
29069  
29070		this.setTexture2D = setTexture2D;
29071		this.setTextureCube = setTextureCube;
29072		this.setTextureCubeDynamic = setTextureCubeDynamic;
29073		this.setupRenderTarget = setupRenderTarget;
29074		this.updateRenderTargetMipmap = updateRenderTargetMipmap;
29075  
29076	}
29077  
29078	/**
29079	 * @author thespite / http://www.twitter.com/thespite
29080	 */
29081  
29082	function WebGLUtils( gl, extensions ) {
29083  
29084		function convert( p ) {
29085  
29086			var extension;
29087  
29088			if ( p === RepeatWrapping ) return gl.REPEAT;
29089			if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE;
29090			if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT;
29091  
29092			if ( p === NearestFilter ) return gl.NEAREST;
29093			if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST;
29094			if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR;
29095  
29096			if ( p === LinearFilter ) return gl.LINEAR;
29097			if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST;
29098			if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR;
29099  
29100			if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
29101			if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
29102			if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
29103			if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;
29104  
29105			if ( p === ByteType ) return gl.BYTE;
29106			if ( p === ShortType ) return gl.SHORT;
29107			if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
29108			if ( p === IntType ) return gl.INT;
29109			if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
29110			if ( p === FloatType ) return gl.FLOAT;
29111  
29112			if ( p === HalfFloatType ) {
29113  
29114				extension = extensions.get( 'OES_texture_half_float' );
29115  
29116				if ( extension !== null ) return extension.HALF_FLOAT_OES;
29117  
29118			}
29119  
29120			if ( p === AlphaFormat ) return gl.ALPHA;
29121			if ( p === RGBFormat ) return gl.RGB;
29122			if ( p === RGBAFormat ) return gl.RGBA;
29123			if ( p === LuminanceFormat ) return gl.LUMINANCE;
29124			if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
29125			if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
29126			if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
29127  
29128			if ( p === AddEquation ) return gl.FUNC_ADD;
29129			if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT;
29130			if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT;
29131  
29132			if ( p === ZeroFactor ) return gl.ZERO;
29133			if ( p === OneFactor ) return gl.ONE;
29134			if ( p === SrcColorFactor ) return gl.SRC_COLOR;
29135			if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR;
29136			if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA;
29137			if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA;
29138			if ( p === DstAlphaFactor ) return gl.DST_ALPHA;
29139			if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA;
29140  
29141			if ( p === DstColorFactor ) return gl.DST_COLOR;
29142			if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR;
29143			if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE;
29144  
29145			if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
29146				p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
29147  
29148				extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
29149  
29150				if ( extension !== null ) {
29151  
29152					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
29153					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
29154					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
29155					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
29156  
29157				}
29158  
29159			}
29160  
29161			if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
29162				p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
29163  
29164				extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
29165  
29166				if ( extension !== null ) {
29167  
29168					if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
29169					if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
29170					if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
29171					if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
29172  
29173				}
29174  
29175			}
29176  
29177			if ( p === RGB_ETC1_Format ) {
29178  
29179				extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
29180  
29181				if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
29182  
29183			}
29184  
29185			if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
29186				p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
29187				p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
29188				p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
29189				p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
29190  
29191				extension = extensions.get( 'WEBGL_compressed_texture_astc' );
29192  
29193				if ( extension !== null ) {
29194  
29195					return p;
29196  
29197				}
29198  
29199			}
29200  
29201			if ( p === MinEquation || p === MaxEquation ) {
29202  
29203				extension = extensions.get( 'EXT_blend_minmax' );
29204  
29205				if ( extension !== null ) {
29206  
29207					if ( p === MinEquation ) return extension.MIN_EXT;
29208					if ( p === MaxEquation ) return extension.MAX_EXT;
29209  
29210				}
29211  
29212			}
29213  
29214			if ( p === UnsignedInt248Type ) {
29215  
29216				extension = extensions.get( 'WEBGL_depth_texture' );
29217  
29218				if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
29219  
29220			}
29221  
29222			return 0;
29223  
29224		}
29225  
29226		return { convert: convert };
29227  
29228	}
29229  
29230	/**
29231	 * @author mrdoob / http://mrdoob.com/
29232	 * @author greggman / http://games.greggman.com/
29233	 * @author zz85 / http://www.lab4games.net/zz85/blog
29234	 * @author tschw
29235	 */
29236  
29237	function PerspectiveCamera( fov, aspect, near, far ) {
29238  
29239		Camera.call( this );
29240  
29241		this.type = 'PerspectiveCamera';
29242  
29243		this.fov = fov !== undefined ? fov : 50;
29244		this.zoom = 1;
29245  
29246		this.near = near !== undefined ? near : 0.1;
29247		this.far = far !== undefined ? far : 2000;
29248		this.focus = 10;
29249  
29250		this.aspect = aspect !== undefined ? aspect : 1;
29251		this.view = null;
29252  
29253		this.filmGauge = 35;	// width of the film (default in millimeters)
29254		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
29255  
29256		this.updateProjectionMatrix();
29257  
29258	}
29259  
29260	PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
29261  
29262		constructor: PerspectiveCamera,
29263  
29264		isPerspectiveCamera: true,
29265  
29266		copy: function ( source, recursive ) {
29267  
29268			Camera.prototype.copy.call( this, source, recursive );
29269  
29270			this.fov = source.fov;
29271			this.zoom = source.zoom;
29272  
29273			this.near = source.near;
29274			this.far = source.far;
29275			this.focus = source.focus;
29276  
29277			this.aspect = source.aspect;
29278			this.view = source.view === null ? null : Object.assign( {}, source.view );
29279  
29280			this.filmGauge = source.filmGauge;
29281			this.filmOffset = source.filmOffset;
29282  
29283			return this;
29284  
29285		},
29286  
vendor: 5,718 bytes, lines 29287-29523
29287		/**
29288		 * Sets the FOV by focal length in respect to the current .filmGauge.
29289		 *
29290		 * The default film gauge is 35, so that the focal length can be specified for
29291		 * a 35mm (full frame) camera.
29292		 *
29293		 * Values for focal length and film gauge must have the same unit.
29294		 */
29295		setFocalLength: function ( focalLength ) {
29296  
29297			// see http://www.bobatkins.com/photography/technical/field_of_view.html
29298			var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
29299  
29300			this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
29301			this.updateProjectionMatrix();
29302  
29303		},
29304  
29305		/**
29306		 * Calculates the focal length from the current .fov and .filmGauge.
29307		 */
29308		getFocalLength: function () {
29309  
29310			var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
29311  
29312			return 0.5 * this.getFilmHeight() / vExtentSlope;
29313  
29314		},
29315  
29316		getEffectiveFOV: function () {
29317  
29318			return _Math.RAD2DEG * 2 * Math.atan(
29319				Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
29320  
29321		},
29322  
29323		getFilmWidth: function () {
29324  
29325			// film not completely covered in portrait format (aspect < 1)
29326			return this.filmGauge * Math.min( this.aspect, 1 );
29327  
29328		},
29329  
29330		getFilmHeight: function () {
29331  
29332			// film not completely covered in landscape format (aspect > 1)
29333			return this.filmGauge / Math.max( this.aspect, 1 );
29334  
29335		},
29336  
29337		/**
29338		 * Sets an offset in a larger frustum. This is useful for multi-window or
29339		 * multi-monitor/multi-machine setups.
29340		 *
29341		 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
29342		 * the monitors are in grid like this
29343		 *
29344		 *   +---+---+---+
29345		 *   | A | B | C |
29346		 *   +---+---+---+
29347		 *   | D | E | F |
29348		 *   +---+---+---+
29349		 *
29350		 * then for each monitor you would call it like this
29351		 *
29352		 *   var w = 1920;
29353		 *   var h = 1080;
29354		 *   var fullWidth = w * 3;
29355		 *   var fullHeight = h * 2;
29356		 *
29357		 *   --A--
29358		 *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
29359		 *   --B--
29360		 *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
29361		 *   --C--
29362		 *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
29363		 *   --D--
29364		 *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
29365		 *   --E--
29366		 *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
29367		 *   --F--
29368		 *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
29369		 *
29370		 *   Note there is no reason monitors have to be the same size or in a grid.
29371		 */
29372		setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
29373  
29374			this.aspect = fullWidth / fullHeight;
29375  
29376			if ( this.view === null ) {
29377  
29378				this.view = {
29379					enabled: true,
29380					fullWidth: 1,
29381					fullHeight: 1,
29382					offsetX: 0,
29383					offsetY: 0,
29384					width: 1,
29385					height: 1
29386				};
29387  
29388			}
29389  
29390			this.view.enabled = true;
29391			this.view.fullWidth = fullWidth;
29392			this.view.fullHeight = fullHeight;
29393			this.view.offsetX = x;
29394			this.view.offsetY = y;
29395			this.view.width = width;
29396			this.view.height = height;
29397  
29398			this.updateProjectionMatrix();
29399  
29400		},
29401  
29402		clearViewOffset: function () {
29403  
29404			if ( this.view !== null ) {
29405  
29406				this.view.enabled = false;
29407  
29408			}
29409  
29410			this.updateProjectionMatrix();
29411  
29412		},
29413  
29414		updateProjectionMatrix: function () {
29415  
29416			var near = this.near,
29417				top = near * Math.tan(
29418					_Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
29419				height = 2 * top,
29420				width = this.aspect * height,
29421				left = - 0.5 * width,
29422				view = this.view;
29423  
29424			if ( this.view !== null && this.view.enabled ) {
29425  
29426				var fullWidth = view.fullWidth,
29427					fullHeight = view.fullHeight;
29428  
29429				left += view.offsetX * width / fullWidth;
29430				top -= view.offsetY * height / fullHeight;
29431				width *= view.width / fullWidth;
29432				height *= view.height / fullHeight;
29433  
29434			}
29435  
29436			var skew = this.filmOffset;
29437			if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
29438  
29439			this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
29440  
29441		},
29442  
29443		toJSON: function ( meta ) {
29444  
29445			var data = Object3D.prototype.toJSON.call( this, meta );
29446  
29447			data.object.fov = this.fov;
29448			data.object.zoom = this.zoom;
29449  
29450			data.object.near = this.near;
29451			data.object.far = this.far;
29452			data.object.focus = this.focus;
29453  
29454			data.object.aspect = this.aspect;
29455  
29456			if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
29457  
29458			data.object.filmGauge = this.filmGauge;
29459			data.object.filmOffset = this.filmOffset;
29460  
29461			return data;
29462  
29463		}
29464  
29465	} );
29466  
29467	/**
29468	 * @author mrdoob / http://mrdoob.com/
29469	 */
29470  
29471	function ArrayCamera( array ) {
29472  
29473		PerspectiveCamera.call( this );
29474  
29475		this.cameras = array || [];
29476  
29477	}
29478  
29479	ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
29480  
29481		constructor: ArrayCamera,
29482  
29483		isArrayCamera: true
29484  
29485	} );
29486  
29487	/**
29488	 * @author mrdoob / http://mrdoob.com/
29489	 */
29490  
29491	function WebVRManager( renderer ) {
29492  
29493		var scope = this;
29494  
29495		var device = null;
29496		var frameData = null;
29497  
29498		var poseTarget = null;
29499  
29500		var standingMatrix = new Matrix4();
29501		var standingMatrixInverse = new Matrix4();
29502  
29503		if ( typeof window !== 'undefined' && 'VRFrameData' in window ) {
29504  
29505			frameData = new window.VRFrameData();
29506			window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
29507  
29508		}
29509  
29510		var matrixWorldInverse = new Matrix4();
29511		var tempQuaternion = new Quaternion();
29512		var tempPosition = new Vector3();
29513  
29514		var cameraL = new PerspectiveCamera();
29515		cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
29516		cameraL.layers.enable( 1 );
29517  
29518		var cameraR = new PerspectiveCamera();
29519		cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
29520		cameraR.layers.enable( 2 );
29521  
29522		var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
29523		cameraVR.layers.enable( 1 );
29524		cameraVR.layers.enable( 2 );
29525  
29526		//
29527  
29528		function isPresenting() {
29529  
29530			return device !== null && device.isPresenting === true;
29531  
29532		}
29533  
29534		var currentSize, currentPixelRatio;
29535  
29536		function onVRDisplayPresentChange() {
29537  
29538			if ( isPresenting() ) {
29539  
29540				var eyeParameters = device.getEyeParameters( 'left' );
29541				var renderWidth = eyeParameters.renderWidth;
29542				var renderHeight = eyeParameters.renderHeight;
29543  
29544				currentPixelRatio = renderer.getPixelRatio();
29545				currentSize = renderer.getSize();
29546  
29547				renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
29548  
29549				animation.start();
29550  
29551			} else if ( scope.enabled ) {
29552  
29553				renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
29554  
29555				animation.stop();
29556  
29557			}
29558  
29559		}
29560  
29561		//
29562  
29563		this.enabled = false;
29564		this.userHeight = 1.6;
29565  
29566		this.getDevice = function () {
29567  
29568			return device;
29569  
29570		};
29571  
29572		this.setDevice = function ( value ) {
29573  
29574			if ( value !== undefined ) device = value;
29575  
29576			animation.setContext( value );
29577  
29578		};
29579  
29580		this.setPoseTarget = function ( object ) {
29581  
29582			if ( object !== undefined ) poseTarget = object;
29583  
29584		};
29585  
29586		this.getCamera = function ( camera ) {
29587  
29588			if ( device === null ) return camera;
29589  
29590			device.depthNear = camera.near;
29591			device.depthFar = camera.far;
29592  
29593			device.getFrameData( frameData );
29594  
29595			//
29596  
29597			var stageParameters = device.stageParameters;
29598  
29599			if ( stageParameters ) {
29600  
29601				standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
29602  
29603			} else {
29604  
29605				standingMatrix.makeTranslation( 0, scope.userHeight, 0 );
29606  
29607			}
29608  
29609  
29610			var pose = frameData.pose;
29611			var poseObject = poseTarget !== null ? poseTarget : camera;
29612  
29613			// We want to manipulate poseObject by its position and quaternion components since users may rely on them.
29614			poseObject.matrix.copy( standingMatrix );
29615			poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );
29616  
29617			if ( pose.orientation !== null ) {
29618  
29619				tempQuaternion.fromArray( pose.orientation );
29620				poseObject.quaternion.multiply( tempQuaternion );
29621  
29622			}
29623  
29624			if ( pose.position !== null ) {
29625  
29626				tempQuaternion.setFromRotationMatrix( standingMatrix );
29627				tempPosition.fromArray( pose.position );
29628				tempPosition.applyQuaternion( tempQuaternion );
29629				poseObject.position.add( tempPosition );
29630  
29631			}
29632  
29633			poseObject.updateMatrixWorld();
29634  
29635			if ( device.isPresenting === false ) return camera;
29636  
29637			//
29638  
29639			cameraL.near = camera.near;
29640			cameraR.near = camera.near;
29641  
29642			cameraL.far = camera.far;
29643			cameraR.far = camera.far;
29644  
29645			cameraVR.matrixWorld.copy( camera.matrixWorld );
29646			cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
29647  
29648			cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
29649			cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
29650  
29651			// TODO (mrdoob) Double check this code
29652  
29653			standingMatrixInverse.getInverse( standingMatrix );
29654  
29655			cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
29656			cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
29657  
29658			var parent = poseObject.parent;
29659  
29660			if ( parent !== null ) {
29661  
29662				matrixWorldInverse.getInverse( parent.matrixWorld );
29663  
29664				cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
29665				cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
29666  
29667			}
29668  
29669			// envMap and Mirror needs camera.matrixWorld
29670  
29671			cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
29672			cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
29673  
29674			cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
29675			cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
29676  
29677			// HACK (mrdoob)
29678			// https://github.com/w3c/webvr/issues/203
29679  
29680			cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
29681  
29682			//
29683  
29684			var layers = device.getLayers();
29685  
29686			if ( layers.length ) {
29687  
29688				var layer = layers[ 0 ];
29689  
29690				if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
29691  
29692					cameraL.bounds.fromArray( layer.leftBounds );
29693  
29694				}
29695  
29696				if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
29697  
29698					cameraR.bounds.fromArray( layer.rightBounds );
29699  
29700				}
29701  
29702			}
29703  
29704			return cameraVR;
29705  
29706		};
29707  
29708		this.getStandingMatrix = function () {
29709  
29710			return standingMatrix;
29711  
29712		};
29713  
29714		this.isPresenting = isPresenting;
29715  
29716		// Animation Loop
29717  
29718		var animation = new WebGLAnimation();
29719  
29720		this.setAnimationLoop = function ( callback ) {
29721  
29722			animation.setAnimationLoop( callback );
29723  
29724		};
29725  
29726		this.submitFrame = function () {
29727  
29728			if ( isPresenting() ) device.submitFrame();
29729  
29730		};
29731  
29732		this.dispose = function () {
29733  
29734			if ( typeof window !== 'undefined' ) {
29735  
29736				window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
29737  
29738			}
29739  
29740		};
29741  
29742	}
29743  
29744	/**
29745	 * @author mrdoob / http://mrdoob.com/
29746	 */
29747  
29748	function WebXRManager( renderer ) {
29749  
29750		var gl = renderer.context;
29751  
29752		var device = null;
29753		var session = null;
29754  
29755		var frameOfRef = null;
29756  
29757		var pose = null;
29758  
29759		function isPresenting() {
29760  
29761			return session !== null && frameOfRef !== null;
29762  
29763		}
29764  
29765		//
29766  
29767		var cameraL = new PerspectiveCamera();
29768		cameraL.layers.enable( 1 );
29769		cameraL.viewport = new Vector4();
29770  
29771		var cameraR = new PerspectiveCamera();
29772		cameraR.layers.enable( 2 );
29773		cameraR.viewport = new Vector4();
29774  
29775		var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
29776		cameraVR.layers.enable( 1 );
29777		cameraVR.layers.enable( 2 );
29778  
29779		//
29780  
29781		this.enabled = false;
29782  
29783		this.getDevice = function () {
29784  
29785			return device;
29786  
29787		};
29788  
29789		this.setDevice = function ( value ) {
29790  
29791			if ( value !== undefined ) device = value;
29792  
29793			gl.setCompatibleXRDevice( value );
29794  
29795		};
29796  
29797		//
29798  
29799		this.setSession = function ( value, options ) {
29800  
29801			session = value;
29802  
29803			if ( session !== null ) {
29804  
29805				session.addEventListener( 'end', function () {
29806  
29807					renderer.setFramebuffer( null );
29808					animation.stop();
29809  
29810				} );
29811  
29812				session.baseLayer = new XRWebGLLayer( session, gl );
29813				session.requestFrameOfReference( options.frameOfReferenceType ).then( function ( value ) {
29814  
29815					frameOfRef = value;
29816  
29817					renderer.setFramebuffer( session.baseLayer.framebuffer );
29818  
29819					animation.setContext( session );
29820					animation.start();
29821  
29822				} );
29823  
29824			}
29825  
29826		};
29827  
29828		function updateCamera( camera, parent ) {
29829  
29830			if ( parent === null ) {
29831  
29832				camera.matrixWorld.copy( camera.matrix );
29833  
29834			} else {
29835  
29836				camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
29837  
29838			}
29839  
29840			camera.matrixWorldInverse.getInverse( camera.matrixWorld );
29841  
29842		}
29843  
29844		this.getCamera = function ( camera ) {
29845  
29846			if ( isPresenting() ) {
29847  
29848				var parent = camera.parent;
29849				var cameras = cameraVR.cameras;
29850  
29851				// apply camera.parent to cameraVR
29852  
29853				updateCamera( cameraVR, parent );
29854  
29855				for ( var i = 0; i < cameras.length; i ++ ) {
29856  
29857					updateCamera( cameras[ i ], parent );
29858  
29859				}
29860  
29861				// update camera and its children
29862  
29863				camera.matrixWorld.copy( cameraVR.matrixWorld );
29864  
29865				var children = camera.children;
29866  
29867				for ( var i = 0, l = children.length; i < l; i ++ ) {
29868  
29869					children[ i ].updateMatrixWorld( true );
29870  
29871				}
29872  
29873				return cameraVR;
29874  
29875			}
29876  
29877			return camera;
29878  
29879		};
29880  
29881		this.isPresenting = isPresenting;
29882  
29883		// Animation Loop
29884  
29885		var onAnimationFrameCallback = null;
29886  
29887		function onAnimationFrame( time, frame ) {
29888  
29889			pose = frame.getDevicePose( frameOfRef );
29890  
29891			var layer = session.baseLayer;
29892			var views = frame.views;
29893  
29894			for ( var i = 0; i < views.length; i ++ ) {
29895  
29896				var view = views[ i ];
29897				var viewport = layer.getViewport( view );
29898				var viewMatrix = pose.getViewMatrix( view );
29899  
29900				var camera = cameraVR.cameras[ i ];
29901				camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
29902				camera.projectionMatrix.fromArray( view.projectionMatrix );
29903				camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
29904  
29905				if ( i === 0 ) {
29906  
29907					cameraVR.matrix.copy( camera.matrix );
29908  
29909					// HACK (mrdoob)
29910					// https://github.com/w3c/webvr/issues/203
29911  
29912					cameraVR.projectionMatrix.copy( camera.projectionMatrix );
29913  
29914				}
29915  
29916			}
29917  
29918			if ( onAnimationFrameCallback ) onAnimationFrameCallback();
29919  
29920		}
29921  
29922		var animation = new WebGLAnimation();
29923		animation.setAnimationLoop( onAnimationFrame );
29924  
29925		this.setAnimationLoop = function ( callback ) {
29926  
29927			onAnimationFrameCallback = callback;
29928  
29929		};
29930  
29931		// DEPRECATED
29932  
29933		this.getStandingMatrix = function () {
29934  
29935			console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
29936			return new THREE.Matrix4();
29937  
29938		};
29939  
29940		this.submitFrame = function () {};
29941  
29942	}
29943  
29944	/**
29945	 * @author supereggbert / http://www.paulbrunt.co.uk/
29946	 * @author mrdoob / http://mrdoob.com/
29947	 * @author alteredq / http://alteredqualia.com/
29948	 * @author szimek / https://github.com/szimek/
29949	 * @author tschw
29950	 */
29951  
29952	function WebGLRenderer( parameters ) {
29953  
29954		console.log( 'THREE.WebGLRenderer', REVISION );
29955  
29956		parameters = parameters || {};
29957  
29958		var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
29959			_context = parameters.context !== undefined ? parameters.context : null,
29960  
29961			_alpha = parameters.alpha !== undefined ? parameters.alpha : false,
29962			_depth = parameters.depth !== undefined ? parameters.depth : true,
29963			_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
29964			_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
29965			_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
29966			_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
29967			_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default';
29968  
29969		var currentRenderList = null;
29970		var currentRenderState = null;
29971  
29972		// public properties
29973  
29974		this.domElement = _canvas;
29975		this.context = null;
29976  
29977		// clearing
29978  
29979		this.autoClear = true;
29980		this.autoClearColor = true;
29981		this.autoClearDepth = true;
29982		this.autoClearStencil = true;
29983  
29984		// scene graph
29985  
29986		this.sortObjects = true;
29987  
29988		// user-defined clipping
29989  
29990		this.clippingPlanes = [];
29991		this.localClippingEnabled = false;
29992  
29993		// physically based shading
29994  
29995		this.gammaFactor = 2.0;	// for backwards compatibility
29996		this.gammaInput = false;
29997		this.gammaOutput = false;
29998  
29999		// physical lights
30000  
30001		this.physicallyCorrectLights = false;
30002  
30003		// tone mapping
30004  
30005		this.toneMapping = LinearToneMapping;
30006		this.toneMappingExposure = 1.0;
30007		this.toneMappingWhitePoint = 1.0;
30008  
30009		// morphs
30010  
30011		this.maxMorphTargets = 8;
30012		this.maxMorphNormals = 4;
30013  
30014		// internal properties
30015  
30016		var _this = this,
30017  
30018			_isContextLost = false,
30019  
30020			// internal state cache
30021  
30022			_framebuffer = null,
30023  
30024			_currentRenderTarget = null,
30025			_currentFramebuffer = null,
30026			_currentMaterialId = - 1,
30027			_currentGeometryProgram = '',
30028  
30029			_currentCamera = null,
30030			_currentArrayCamera = null,
30031  
30032			_currentViewport = new Vector4(),
30033			_currentScissor = new Vector4(),
30034			_currentScissorTest = null,
30035  
30036			//
30037  
30038			_usedTextureUnits = 0,
30039  
30040			//
30041  
30042			_width = _canvas.width,
30043			_height = _canvas.height,
30044  
30045			_pixelRatio = 1,
30046  
30047			_viewport = new Vector4( 0, 0, _width, _height ),
30048			_scissor = new Vector4( 0, 0, _width, _height ),
30049			_scissorTest = false,
30050  
30051			// frustum
30052  
30053			_frustum = new Frustum(),
30054  
30055			// clipping
30056  
30057			_clipping = new WebGLClipping(),
30058			_clippingEnabled = false,
30059			_localClippingEnabled = false,
30060  
30061			// camera matrices cache
30062  
30063			_projScreenMatrix = new Matrix4(),
30064  
30065			_vector3 = new Vector3();
30066  
30067		function getTargetPixelRatio() {
30068  
30069			return _currentRenderTarget === null ? _pixelRatio : 1;
30070  
30071		}
30072  
30073		// initialize
30074  
30075		var _gl;
30076  
30077		try {
30078  
30079			var contextAttributes = {
30080				alpha: _alpha,
30081				depth: _depth,
30082				stencil: _stencil,
30083				antialias: _antialias,
30084				premultipliedAlpha: _premultipliedAlpha,
30085				preserveDrawingBuffer: _preserveDrawingBuffer,
30086				powerPreference: _powerPreference
30087			};
30088  
30089			// event listeners must be registered before WebGL context is created, see #12753
30090  
30091			_canvas.addEventListener( 'webglcontextlost', onContextLost, false );
30092			_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
30093  
30094			_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
30095  
30096			if ( _gl === null ) {
30097  
30098				if ( _canvas.getContext( 'webgl' ) !== null ) {
30099  
30100					throw new Error( 'Error creating WebGL context with your selected attributes.' );
30101  
30102				} else {
30103  
30104					throw new Error( 'Error creating WebGL context.' );
30105  
30106				}
30107  
30108			}
30109  
30110			// Some experimental-webgl implementations do not have getShaderPrecisionFormat
30111  
30112			if ( _gl.getShaderPrecisionFormat === undefined ) {
30113  
30114				_gl.getShaderPrecisionFormat = function () {
30115  
30116					return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
30117  
30118				};
30119  
30120			}
30121  
30122		} catch ( error ) {
30123  
30124			console.error( 'THREE.WebGLRenderer: ' + error.message );
30125  
30126		}
30127  
30128		var extensions, capabilities, state, info;
30129		var properties, textures, attributes, geometries, objects;
30130		var programCache, renderLists, renderStates;
30131  
30132		var background, morphtargets, bufferRenderer, indexedBufferRenderer;
30133		var spriteRenderer;
30134  
30135		var utils;
30136  
30137		function initGLContext() {
30138  
30139			extensions = new WebGLExtensions( _gl );
30140			extensions.get( 'WEBGL_depth_texture' );
30141			extensions.get( 'OES_texture_float' );
30142			extensions.get( 'OES_texture_float_linear' );
30143			extensions.get( 'OES_texture_half_float' );
30144			extensions.get( 'OES_texture_half_float_linear' );
30145			extensions.get( 'OES_standard_derivatives' );
30146			extensions.get( 'OES_element_index_uint' );
30147			extensions.get( 'ANGLE_instanced_arrays' );
30148  
30149			utils = new WebGLUtils( _gl, extensions );
30150  
30151			capabilities = new WebGLCapabilities( _gl, extensions, parameters );
30152  
30153			state = new WebGLState( _gl, extensions, utils );
30154			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
30155			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
30156  
30157			info = new WebGLInfo( _gl );
30158			properties = new WebGLProperties();
30159			textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
30160			attributes = new WebGLAttributes( _gl );
30161			geometries = new WebGLGeometries( _gl, attributes, info );
30162			objects = new WebGLObjects( geometries, info );
30163			morphtargets = new WebGLMorphtargets( _gl );
30164			programCache = new WebGLPrograms( _this, extensions, capabilities );
30165			renderLists = new WebGLRenderLists();
30166			renderStates = new WebGLRenderStates();
30167  
30168			background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
30169  
30170			bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
30171			indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
30172  
30173			spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities );
30174  
30175			info.programs = programCache.programs;
30176  
30177			_this.context = _gl;
30178			_this.capabilities = capabilities;
30179			_this.extensions = extensions;
30180			_this.properties = properties;
30181			_this.renderLists = renderLists;
30182			_this.state = state;
30183			_this.info = info;
30184  
30185		}
30186  
30187		initGLContext();
30188  
30189		// vr
30190  
30191		var vr = ( 'xr' in navigator ) ? new WebXRManager( _this ) : new WebVRManager( _this );
30192  
30193		this.vr = vr;
30194  
30195		// shadow map
30196  
30197		var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
30198  
30199		this.shadowMap = shadowMap;
30200  
30201		// API
30202  
30203		this.getContext = function () {
30204  
30205			return _gl;
30206  
30207		};
30208  
30209		this.getContextAttributes = function () {
30210  
30211			return _gl.getContextAttributes();
30212  
30213		};
30214  
30215		this.forceContextLoss = function () {
30216  
30217			var extension = extensions.get( 'WEBGL_lose_context' );
30218			if ( extension ) extension.loseContext();
30219  
30220		};
30221  
30222		this.forceContextRestore = function () {
30223  
30224			var extension = extensions.get( 'WEBGL_lose_context' );
30225			if ( extension ) extension.restoreContext();
30226  
30227		};
30228  
30229		this.getPixelRatio = function () {
30230  
30231			return _pixelRatio;
30232  
30233		};
30234  
30235		this.setPixelRatio = function ( value ) {
30236  
30237			if ( value === undefined ) return;
30238  
30239			_pixelRatio = value;
30240  
30241			this.setSize( _width, _height, false );
30242  
30243		};
30244  
30245		this.getSize = function () {
30246  
30247			return {
30248				width: _width,
30249				height: _height
30250			};
30251  
30252		};
30253  
30254		this.setSize = function ( width, height, updateStyle ) {
30255  
30256			if ( vr.isPresenting() ) {
30257  
30258				console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
30259				return;
30260  
30261			}
30262  
30263			_width = width;
30264			_height = height;
30265  
30266			_canvas.width = width * _pixelRatio;
30267			_canvas.height = height * _pixelRatio;
30268  
30269			if ( updateStyle !== false ) {
30270  
30271				_canvas.style.width = width + 'px';
30272				_canvas.style.height = height + 'px';
30273  
30274			}
30275  
30276			this.setViewport( 0, 0, width, height );
30277  
30278		};
30279  
30280		this.getDrawingBufferSize = function () {
30281  
30282			return {
30283				width: _width * _pixelRatio,
30284				height: _height * _pixelRatio
30285			};
30286  
30287		};
30288  
30289		this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
30290  
30291			_width = width;
30292			_height = height;
30293  
30294			_pixelRatio = pixelRatio;
30295  
30296			_canvas.width = width * pixelRatio;
30297			_canvas.height = height * pixelRatio;
30298  
30299			this.setViewport( 0, 0, width, height );
30300  
30301		};
30302  
30303		this.getCurrentViewport = function () {
30304  
30305			return _currentViewport;
30306  
30307		};
30308  
30309		this.setViewport = function ( x, y, width, height ) {
30310  
30311			_viewport.set( x, _height - y - height, width, height );
30312			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
30313  
30314		};
30315  
30316		this.setScissor = function ( x, y, width, height ) {
30317  
30318			_scissor.set( x, _height - y - height, width, height );
30319			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
30320  
30321		};
30322  
30323		this.setScissorTest = function ( boolean ) {
30324  
30325			state.setScissorTest( _scissorTest = boolean );
30326  
30327		};
30328  
30329		// Clearing
30330  
30331		this.getClearColor = function () {
30332  
30333			return background.getClearColor();
30334  
30335		};
30336  
30337		this.setClearColor = function () {
30338  
30339			background.setClearColor.apply( background, arguments );
30340  
30341		};
30342  
30343		this.getClearAlpha = function () {
30344  
30345			return background.getClearAlpha();
30346  
30347		};
30348  
30349		this.setClearAlpha = function () {
30350  
30351			background.setClearAlpha.apply( background, arguments );
30352  
30353		};
30354  
30355		this.clear = function ( color, depth, stencil ) {
30356  
30357			var bits = 0;
30358  
30359			if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
30360			if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
30361			if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
30362  
30363			_gl.clear( bits );
30364  
30365		};
30366  
30367		this.clearColor = function () {
30368  
30369			this.clear( true, false, false );
30370  
30371		};
30372  
30373		this.clearDepth = function () {
30374  
30375			this.clear( false, true, false );
30376  
30377		};
30378  
30379		this.clearStencil = function () {
30380  
30381			this.clear( false, false, true );
30382  
30383		};
30384  
30385		this.clearTarget = function ( renderTarget, color, depth, stencil ) {
30386  
30387			this.setRenderTarget( renderTarget );
30388			this.clear( color, depth, stencil );
30389  
30390		};
30391  
30392		//
30393  
30394		this.dispose = function () {
30395  
30396			_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
30397			_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
30398  
30399			renderLists.dispose();
30400			renderStates.dispose();
30401			properties.dispose();
30402			objects.dispose();
30403  
30404			vr.dispose();
30405  
30406			animation.stop();
30407  
30408		};
30409  
30410		// Events
30411  
30412		function onContextLost( event ) {
30413  
30414			event.preventDefault();
30415  
30416			console.log( 'THREE.WebGLRenderer: Context Lost.' );
30417  
30418			_isContextLost = true;
30419  
30420		}
30421  
30422		function onContextRestore( /* event */ ) {
30423  
30424			console.log( 'THREE.WebGLRenderer: Context Restored.' );
30425  
30426			_isContextLost = false;
30427  
30428			initGLContext();
30429  
30430		}
30431  
30432		function onMaterialDispose( event ) {
30433  
30434			var material = event.target;
30435  
30436			material.removeEventListener( 'dispose', onMaterialDispose );
30437  
30438			deallocateMaterial( material );
30439  
30440		}
30441  
30442		// Buffer deallocation
30443  
30444		function deallocateMaterial( material ) {
30445  
30446			releaseMaterialProgramReference( material );
30447  
30448			properties.remove( material );
30449  
30450		}
30451  
30452  
30453		function releaseMaterialProgramReference( material ) {
30454  
30455			var programInfo = properties.get( material ).program;
30456  
30457			material.program = undefined;
30458  
30459			if ( programInfo !== undefined ) {
30460  
30461				programCache.releaseProgram( programInfo );
30462  
30463			}
30464  
30465		}
30466  
30467		// Buffer rendering
30468  
30469		function renderObjectImmediate( object, program, material ) {
30470  
30471			object.render( function ( object ) {
30472  
30473				_this.renderBufferImmediate( object, program, material );
30474  
30475			} );
30476  
30477		}
30478  
30479		this.renderBufferImmediate = function ( object, program, material ) {
30480  
30481			state.initAttributes();
30482  
30483			var buffers = properties.get( object );
30484  
30485			if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
30486			if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
30487			if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
30488			if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
30489  
30490			var programAttributes = program.getAttributes();
30491  
30492			if ( object.hasPositions ) {
30493  
30494				_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
30495				_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
30496  
30497				state.enableAttribute( programAttributes.position );
30498				_gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
30499  
30500			}
30501  
30502			if ( object.hasNormals ) {
30503  
30504				_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
30505  
30506				if ( ! material.isMeshPhongMaterial &&
30507					! material.isMeshStandardMaterial &&
30508					! material.isMeshNormalMaterial &&
30509					material.flatShading === true ) {
30510  
30511					for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
30512  
30513						var array = object.normalArray;
30514  
30515						var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
30516						var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
30517						var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
30518  
30519						array[ i + 0 ] = nx;
30520						array[ i + 1 ] = ny;
30521						array[ i + 2 ] = nz;
30522  
30523						array[ i + 3 ] = nx;
30524						array[ i + 4 ] = ny;
30525						array[ i + 5 ] = nz;
30526  
30527						array[ i + 6 ] = nx;
30528						array[ i + 7 ] = ny;
30529						array[ i + 8 ] = nz;
30530  
30531					}
30532  
30533				}
30534  
30535				_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
30536  
30537				state.enableAttribute( programAttributes.normal );
30538  
30539				_gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
30540  
30541			}
30542  
30543			if ( object.hasUvs && material.map ) {
30544  
30545				_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
30546				_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
30547  
30548				state.enableAttribute( programAttributes.uv );
30549  
30550				_gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );
30551  
30552			}
30553  
30554			if ( object.hasColors && material.vertexColors !== NoColors ) {
30555  
30556				_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
30557				_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
30558  
30559				state.enableAttribute( programAttributes.color );
30560  
30561				_gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
30562  
30563			}
30564  
30565			state.disableUnusedAttributes();
30566  
30567			_gl.drawArrays( _gl.TRIANGLES, 0, object.count );
30568  
30569			object.count = 0;
30570  
30571		};
30572  
30573		this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
30574  
30575			var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
30576  
30577			state.setMaterial( material, frontFaceCW );
30578  
30579			var program = setProgram( camera, fog, material, object );
30580			var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true );
30581  
30582			var updateBuffers = false;
30583  
30584			if ( geometryProgram !== _currentGeometryProgram ) {
30585  
30586				_currentGeometryProgram = geometryProgram;
30587				updateBuffers = true;
30588  
30589			}
30590  
30591			if ( object.morphTargetInfluences ) {
30592  
30593				morphtargets.update( object, geometry, material, program );
30594  
30595				updateBuffers = true;
30596  
30597			}
30598  
30599			//
30600  
30601			var index = geometry.index;
30602			var position = geometry.attributes.position;
30603			var rangeFactor = 1;
30604  
30605			if ( material.wireframe === true ) {
30606  
30607				index = geometries.getWireframeAttribute( geometry );
30608				rangeFactor = 2;
30609  
30610			}
30611  
30612			var attribute;
30613			var renderer = bufferRenderer;
30614  
30615			if ( index !== null ) {
30616  
30617				attribute = attributes.get( index );
30618  
30619				renderer = indexedBufferRenderer;
30620				renderer.setIndex( attribute );
30621  
30622			}
30623  
30624			if ( updateBuffers ) {
30625  
30626				setupVertexAttributes( material, program, geometry );
30627  
30628				if ( index !== null ) {
30629  
30630					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );
30631  
30632				}
30633  
30634			}
30635  
30636			//
30637  
30638			var dataCount = Infinity;
30639  
30640			if ( index !== null ) {
30641  
30642				dataCount = index.count;
30643  
30644			} else if ( position !== undefined ) {
30645  
30646				dataCount = position.count;
30647  
30648			}
30649  
30650			var rangeStart = geometry.drawRange.start * rangeFactor;
30651			var rangeCount = geometry.drawRange.count * rangeFactor;
30652  
30653			var groupStart = group !== null ? group.start * rangeFactor : 0;
30654			var groupCount = group !== null ? group.count * rangeFactor : Infinity;
30655  
30656			var drawStart = Math.max( rangeStart, groupStart );
30657			var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
30658  
30659			var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
30660  
30661			if ( drawCount === 0 ) return;
30662  
30663			//
30664  
30665			if ( object.isMesh ) {
30666  
30667				if ( material.wireframe === true ) {
30668  
30669					state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
30670					renderer.setMode( _gl.LINES );
30671  
30672				} else {
30673  
30674					switch ( object.drawMode ) {
30675  
30676						case TrianglesDrawMode:
30677							renderer.setMode( _gl.TRIANGLES );
30678							break;
30679  
30680						case TriangleStripDrawMode:
30681							renderer.setMode( _gl.TRIANGLE_STRIP );
30682							break;
30683  
30684						case TriangleFanDrawMode:
30685							renderer.setMode( _gl.TRIANGLE_FAN );
30686							break;
30687  
30688					}
30689  
30690				}
30691  
30692  
30693			} else if ( object.isLine ) {
30694  
30695				var lineWidth = material.linewidth;
30696  
30697				if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
30698  
30699				state.setLineWidth( lineWidth * getTargetPixelRatio() );
30700  
30701				if ( object.isLineSegments ) {
30702  
30703					renderer.setMode( _gl.LINES );
30704  
30705				} else if ( object.isLineLoop ) {
30706  
30707					renderer.setMode( _gl.LINE_LOOP );
30708  
30709				} else {
30710  
30711					renderer.setMode( _gl.LINE_STRIP );
30712  
30713				}
30714  
30715			} else if ( object.isPoints ) {
30716  
30717				renderer.setMode( _gl.POINTS );
30718  
30719			}
30720  
30721			if ( geometry && geometry.isInstancedBufferGeometry ) {
30722  
30723				if ( geometry.maxInstancedCount > 0 ) {
30724  
30725					renderer.renderInstances( geometry, drawStart, drawCount );
30726  
30727				}
30728  
30729			} else {
30730  
30731				renderer.render( drawStart, drawCount );
30732  
30733			}
30734  
30735		};
30736  
30737		function setupVertexAttributes( material, program, geometry ) {
30738  
30739			if ( geometry && geometry.isInstancedBufferGeometry ) {
30740  
30741				if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
30742  
30743					console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
30744					return;
30745  
30746				}
30747  
30748			}
30749  
30750			state.initAttributes();
30751  
30752			var geometryAttributes = geometry.attributes;
30753  
30754			var programAttributes = program.getAttributes();
30755  
30756			var materialDefaultAttributeValues = material.defaultAttributeValues;
30757  
30758			for ( var name in programAttributes ) {
30759  
30760				var programAttribute = programAttributes[ name ];
30761  
30762				if ( programAttribute >= 0 ) {
30763  
30764					var geometryAttribute = geometryAttributes[ name ];
30765  
30766					if ( geometryAttribute !== undefined ) {
30767  
30768						var normalized = geometryAttribute.normalized;
30769						var size = geometryAttribute.itemSize;
30770  
30771						var attribute = attributes.get( geometryAttribute );
30772  
30773						// TODO Attribute may not be available on context restore
30774  
30775						if ( attribute === undefined ) continue;
30776  
30777						var buffer = attribute.buffer;
30778						var type = attribute.type;
30779						var bytesPerElement = attribute.bytesPerElement;
30780  
30781						if ( geometryAttribute.isInterleavedBufferAttribute ) {
30782  
30783							var data = geometryAttribute.data;
30784							var stride = data.stride;
30785							var offset = geometryAttribute.offset;
30786  
30787							if ( data && data.isInstancedInterleavedBuffer ) {
30788  
30789								state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
30790  
30791								if ( geometry.maxInstancedCount === undefined ) {
30792  
30793									geometry.maxInstancedCount = data.meshPerAttribute * data.count;
30794  
30795								}
30796  
30797							} else {
30798  
30799								state.enableAttribute( programAttribute );
30800  
30801							}
30802  
30803							_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
30804							_gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
30805  
30806						} else {
30807  
30808							if ( geometryAttribute.isInstancedBufferAttribute ) {
30809  
30810								state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
30811  
30812								if ( geometry.maxInstancedCount === undefined ) {
30813  
30814									geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
30815  
30816								}
30817  
30818							} else {
30819  
30820								state.enableAttribute( programAttribute );
30821  
30822							}
30823  
30824							_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
30825							_gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
30826  
30827						}
30828  
30829					} else if ( materialDefaultAttributeValues !== undefined ) {
30830  
30831						var value = materialDefaultAttributeValues[ name ];
30832  
30833						if ( value !== undefined ) {
30834  
30835							switch ( value.length ) {
30836  
30837								case 2:
30838									_gl.vertexAttrib2fv( programAttribute, value );
30839									break;
30840  
30841								case 3:
30842									_gl.vertexAttrib3fv( programAttribute, value );
30843									break;
30844  
30845								case 4:
30846									_gl.vertexAttrib4fv( programAttribute, value );
30847									break;
30848  
30849								default:
30850									_gl.vertexAttrib1fv( programAttribute, value );
30851  
30852							}
30853  
30854						}
30855  
30856					}
30857  
30858				}
30859  
30860			}
30861  
30862			state.disableUnusedAttributes();
30863  
30864		}
30865  
30866		// Compile
30867  
30868		this.compile = function ( scene, camera ) {
30869  
30870			currentRenderState = renderStates.get( scene, camera );
30871			currentRenderState.init();
30872  
30873			scene.traverse( function ( object ) {
30874  
30875				if ( object.isLight ) {
30876  
30877					currentRenderState.pushLight( object );
30878  
30879					if ( object.castShadow ) {
30880  
30881						currentRenderState.pushShadow( object );
30882  
30883					}
30884  
30885				}
30886  
30887			} );
30888  
30889			currentRenderState.setupLights( camera );
30890  
30891			scene.traverse( function ( object ) {
30892  
30893				if ( object.material ) {
30894  
30895					if ( Array.isArray( object.material ) ) {
30896  
30897						for ( var i = 0; i < object.material.length; i ++ ) {
30898  
30899							initMaterial( object.material[ i ], scene.fog, object );
30900  
30901						}
30902  
30903					} else {
30904  
30905						initMaterial( object.material, scene.fog, object );
30906  
30907					}
30908  
30909				}
30910  
30911			} );
30912  
30913		};
30914  
30915		// Animation Loop
30916  
30917		var onAnimationFrameCallback = null;
30918  
30919		function onAnimationFrame() {
30920  
30921			if ( vr.isPresenting() ) return;
30922			if ( onAnimationFrameCallback ) onAnimationFrameCallback();
30923  
30924		}
30925  
30926		var animation = new WebGLAnimation();
30927		animation.setAnimationLoop( onAnimationFrame );
30928		animation.setContext( window );
30929  
30930		this.setAnimationLoop = function ( callback ) {
30931  
30932			onAnimationFrameCallback = callback;
30933			vr.setAnimationLoop( callback );
30934  
30935			animation.start();
30936  
30937		};
30938  
30939		// Rendering
30940  
30941		this.render = function ( scene, camera, renderTarget, forceClear ) {
30942  
30943			if ( ! ( camera && camera.isCamera ) ) {
30944  
30945				console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
30946				return;
30947  
30948			}
30949  
30950			if ( _isContextLost ) return;
30951  
30952			// reset caching for this frame
30953  
30954			_currentGeometryProgram = '';
30955			_currentMaterialId = - 1;
30956			_currentCamera = null;
30957  
30958			// update scene graph
30959  
30960			if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
30961  
30962			// update camera matrices and frustum
30963  
30964			if ( camera.parent === null ) camera.updateMatrixWorld();
30965  
30966			if ( vr.enabled ) {
30967  
30968				camera = vr.getCamera( camera );
30969  
30970			}
30971  
30972			//
30973  
30974			currentRenderState = renderStates.get( scene, camera );
30975			currentRenderState.init();
30976  
30977			scene.onBeforeRender( _this, scene, camera, renderTarget );
30978  
30979			_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
30980			_frustum.setFromMatrix( _projScreenMatrix );
30981  
30982			_localClippingEnabled = this.localClippingEnabled;
30983			_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
30984  
30985			currentRenderList = renderLists.get( scene, camera );
30986			currentRenderList.init();
30987  
30988			projectObject( scene, camera, _this.sortObjects );
30989  
30990			if ( _this.sortObjects === true ) {
30991  
30992				currentRenderList.sort();
30993  
30994			}
30995  
30996			//
30997  
30998			if ( _clippingEnabled ) _clipping.beginShadows();
30999  
31000			var shadowsArray = currentRenderState.state.shadowsArray;
31001  
31002			shadowMap.render( shadowsArray, scene, camera );
31003  
31004			currentRenderState.setupLights( camera );
31005  
31006			if ( _clippingEnabled ) _clipping.endShadows();
31007  
31008			//
31009  
31010			if ( this.info.autoReset ) this.info.reset();
31011  
31012			if ( renderTarget === undefined ) {
31013  
31014				renderTarget = null;
31015  
31016			}
31017  
31018			this.setRenderTarget( renderTarget );
31019  
31020			//
31021  
31022			background.render( currentRenderList, scene, camera, forceClear );
31023  
31024			// render scene
31025  
31026			var opaqueObjects = currentRenderList.opaque;
31027			var transparentObjects = currentRenderList.transparent;
31028  
31029			if ( scene.overrideMaterial ) {
31030  
31031				var overrideMaterial = scene.overrideMaterial;
31032  
31033				if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
31034				if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
31035  
31036			} else {
31037  
31038				// opaque pass (front-to-back order)
31039  
31040				if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
31041  
31042				// transparent pass (back-to-front order)
31043  
31044				if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
31045  
31046			}
31047  
31048			// custom renderers
31049  
31050			var spritesArray = currentRenderState.state.spritesArray;
31051  
31052			spriteRenderer.render( spritesArray, scene, camera );
31053  
31054			// Generate mipmap if we're using any kind of mipmap filtering
31055  
31056			if ( renderTarget ) {
31057  
31058				textures.updateRenderTargetMipmap( renderTarget );
31059  
31060			}
31061  
31062			// Ensure depth buffer writing is enabled so it can be cleared on next render
31063  
31064			state.buffers.depth.setTest( true );
31065			state.buffers.depth.setMask( true );
31066			state.buffers.color.setMask( true );
31067  
31068			state.setPolygonOffset( false );
31069  
31070			scene.onAfterRender( _this, scene, camera );
31071  
31072			if ( vr.enabled ) {
31073  
31074				vr.submitFrame();
31075  
31076			}
31077  
31078			// _gl.finish();
31079  
31080			currentRenderList = null;
31081			currentRenderState = null;
31082  
31083		};
31084  
31085		/*
31086		// TODO Duplicated code (Frustum)
31087  
31088		var _sphere = new Sphere();
31089  
31090		function isObjectViewable( object ) {
31091  
31092			var geometry = object.geometry;
31093  
31094			if ( geometry.boundingSphere === null )
31095				geometry.computeBoundingSphere();
31096  
31097			_sphere.copy( geometry.boundingSphere ).
31098			applyMatrix4( object.matrixWorld );
31099  
31100			return isSphereViewable( _sphere );
31101  
31102		}
31103  
31104		function isSpriteViewable( sprite ) {
31105  
31106			_sphere.center.set( 0, 0, 0 );
31107			_sphere.radius = 0.7071067811865476;
31108			_sphere.applyMatrix4( sprite.matrixWorld );
31109  
31110			return isSphereViewable( _sphere );
31111  
31112		}
31113  
31114		function isSphereViewable( sphere ) {
31115  
31116			if ( ! _frustum.intersectsSphere( sphere ) ) return false;
31117  
31118			var numPlanes = _clipping.numPlanes;
31119  
31120			if ( numPlanes === 0 ) return true;
31121  
31122			var planes = _this.clippingPlanes,
31123  
31124				center = sphere.center,
31125				negRad = - sphere.radius,
31126				i = 0;
31127  
31128			do {
31129  
31130				// out when deeper than radius in the negative halfspace
31131				if ( planes[ i ].distanceToPoint( center ) < negRad ) return false;
31132  
31133			} while ( ++ i !== numPlanes );
31134  
31135			return true;
31136  
31137		}
31138		*/
31139  
31140		function projectObject( object, camera, sortObjects ) {
31141  
31142			if ( object.visible === false ) return;
31143  
31144			var visible = object.layers.test( camera.layers );
31145  
31146			if ( visible ) {
31147  
31148				if ( object.isLight ) {
31149  
31150					currentRenderState.pushLight( object );
31151  
31152					if ( object.castShadow ) {
31153  
31154						currentRenderState.pushShadow( object );
31155  
31156					}
31157  
31158				} else if ( object.isSprite ) {
31159  
31160					if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
31161  
31162						currentRenderState.pushSprite( object );
31163  
31164					}
31165  
31166				} else if ( object.isImmediateRenderObject ) {
31167  
31168					if ( sortObjects ) {
31169  
31170						_vector3.setFromMatrixPosition( object.matrixWorld )
31171							.applyMatrix4( _projScreenMatrix );
31172  
31173					}
31174  
31175					currentRenderList.push( object, null, object.material, _vector3.z, null );
31176  
31177				} else if ( object.isMesh || object.isLine || object.isPoints ) {
31178  
31179					if ( object.isSkinnedMesh ) {
31180  
31181						object.skeleton.update();
31182  
31183					}
31184  
31185					if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
31186  
31187						if ( sortObjects ) {
31188  
31189							_vector3.setFromMatrixPosition( object.matrixWorld )
31190								.applyMatrix4( _projScreenMatrix );
31191  
31192						}
31193  
31194						var geometry = objects.update( object );
31195						var material = object.material;
31196  
31197						if ( Array.isArray( material ) ) {
31198  
31199							var groups = geometry.groups;
31200  
31201							for ( var i = 0, l = groups.length; i < l; i ++ ) {
31202  
31203								var group = groups[ i ];
31204								var groupMaterial = material[ group.materialIndex ];
31205  
31206								if ( groupMaterial && groupMaterial.visible ) {
31207  
31208									currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
31209  
31210								}
31211  
31212							}
31213  
31214						} else if ( material.visible ) {
31215  
31216							currentRenderList.push( object, geometry, material, _vector3.z, null );
31217  
31218						}
31219  
31220					}
31221  
31222				}
31223  
31224			}
31225  
31226			var children = object.children;
31227  
31228			for ( var i = 0, l = children.length; i < l; i ++ ) {
31229  
31230				projectObject( children[ i ], camera, sortObjects );
31231  
31232			}
31233  
31234		}
31235  
31236		function renderObjects( renderList, scene, camera, overrideMaterial ) {
31237  
31238			for ( var i = 0, l = renderList.length; i < l; i ++ ) {
31239  
31240				var renderItem = renderList[ i ];
31241  
31242				var object = renderItem.object;
31243				var geometry = renderItem.geometry;
31244				var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
31245				var group = renderItem.group;
31246  
31247				if ( camera.isArrayCamera ) {
31248  
31249					_currentArrayCamera = camera;
31250  
31251					var cameras = camera.cameras;
31252  
31253					for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
31254  
31255						var camera2 = cameras[ j ];
31256  
31257						if ( object.layers.test( camera2.layers ) ) {
31258  
31259							if ( 'viewport' in camera2 ) { // XR
31260  
31261								state.viewport( _currentViewport.copy( camera2.viewport ) );
31262  
31263							} else {
31264  
31265								var bounds = camera2.bounds;
31266  
31267								var x = bounds.x * _width;
31268								var y = bounds.y * _height;
31269								var width = bounds.z * _width;
31270								var height = bounds.w * _height;
31271  
31272								state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
31273  
31274							}
31275  
31276							renderObject( object, scene, camera2, geometry, material, group );
31277  
31278						}
31279  
31280					}
31281  
31282				} else {
31283  
31284					_currentArrayCamera = null;
31285  
31286					renderObject( object, scene, camera, geometry, material, group );
31287  
31288				}
31289  
31290			}
31291  
31292		}
31293  
31294		function renderObject( object, scene, camera, geometry, material, group ) {
31295  
31296			object.onBeforeRender( _this, scene, camera, geometry, material, group );
31297			currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
31298  
31299			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
31300			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
31301  
31302			if ( object.isImmediateRenderObject ) {
31303  
31304				var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
31305  
31306				state.setMaterial( material, frontFaceCW );
31307  
31308				var program = setProgram( camera, scene.fog, material, object );
31309  
31310				_currentGeometryProgram = '';
31311  
31312				renderObjectImmediate( object, program, material );
31313  
31314			} else {
31315  
31316				_this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );
31317  
31318			}
31319  
31320			object.onAfterRender( _this, scene, camera, geometry, material, group );
31321			currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
31322  
31323		}
31324  
31325		function initMaterial( material, fog, object ) {
31326  
31327			var materialProperties = properties.get( material );
31328  
31329			var lights = currentRenderState.state.lights;
31330			var shadowsArray = currentRenderState.state.shadowsArray;
31331  
31332			var parameters = programCache.getParameters(
31333				material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
31334  
31335			var code = programCache.getProgramCode( material, parameters );
31336  
31337			var program = materialProperties.program;
31338			var programChange = true;
31339  
31340			if ( program === undefined ) {
31341  
31342				// new material
31343				material.addEventListener( 'dispose', onMaterialDispose );
31344  
31345			} else if ( program.code !== code ) {
31346  
31347				// changed glsl or parameters
31348				releaseMaterialProgramReference( material );
31349  
31350			} else if ( materialProperties.lightsHash !== lights.state.hash ) {
31351  
31352				properties.update( material, 'lightsHash', lights.state.hash );
31353				programChange = false;
31354  
31355			} else if ( parameters.shaderID !== undefined ) {
31356  
31357				// same glsl and uniform list
31358				return;
31359  
31360			} else {
31361  
31362				// only rebuild uniform list
31363				programChange = false;
31364  
31365			}
31366  
31367			if ( programChange ) {
31368  
31369				if ( parameters.shaderID ) {
31370  
31371					var shader = ShaderLib[ parameters.shaderID ];
31372  
31373					materialProperties.shader = {
31374						name: material.type,
31375						uniforms: UniformsUtils.clone( shader.uniforms ),
31376						vertexShader: shader.vertexShader,
31377						fragmentShader: shader.fragmentShader
31378					};
31379  
31380				} else {
31381  
31382					materialProperties.shader = {
31383						name: material.type,
31384						uniforms: material.uniforms,
31385						vertexShader: material.vertexShader,
31386						fragmentShader: material.fragmentShader
31387					};
31388  
31389				}
31390  
31391				material.onBeforeCompile( materialProperties.shader, _this );
31392  
31393				program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
31394  
31395				materialProperties.program = program;
31396				material.program = program;
31397  
31398			}
31399  
31400			var programAttributes = program.getAttributes();
31401  
31402			if ( material.morphTargets ) {
31403  
31404				material.numSupportedMorphTargets = 0;
31405  
31406				for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
31407  
31408					if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
31409  
31410						material.numSupportedMorphTargets ++;
31411  
31412					}
31413  
31414				}
31415  
31416			}
31417  
31418			if ( material.morphNormals ) {
31419  
31420				material.numSupportedMorphNormals = 0;
31421  
31422				for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
31423  
31424					if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
31425  
31426						material.numSupportedMorphNormals ++;
31427  
31428					}
31429  
31430				}
31431  
31432			}
31433  
31434			var uniforms = materialProperties.shader.uniforms;
31435  
31436			if ( ! material.isShaderMaterial &&
31437				! material.isRawShaderMaterial ||
31438				material.clipping === true ) {
31439  
31440				materialProperties.numClippingPlanes = _clipping.numPlanes;
31441				materialProperties.numIntersection = _clipping.numIntersection;
31442				uniforms.clippingPlanes = _clipping.uniform;
31443  
31444			}
31445  
31446			materialProperties.fog = fog;
31447  
31448			// store the light setup it was created for
31449  
31450			materialProperties.lightsHash = lights.state.hash;
31451  
31452			if ( material.lights ) {
31453  
31454				// wire up the material to this renderer's lighting state
31455  
31456				uniforms.ambientLightColor.value = lights.state.ambient;
31457				uniforms.directionalLights.value = lights.state.directional;
31458				uniforms.spotLights.value = lights.state.spot;
31459				uniforms.rectAreaLights.value = lights.state.rectArea;
31460				uniforms.pointLights.value = lights.state.point;
31461				uniforms.hemisphereLights.value = lights.state.hemi;
31462  
31463				uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
31464				uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
31465				uniforms.spotShadowMap.value = lights.state.spotShadowMap;
31466				uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
31467				uniforms.pointShadowMap.value = lights.state.pointShadowMap;
31468				uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
31469				// TODO (abelnation): add area lights shadow info to uniforms
31470  
31471			}
31472  
31473			var progUniforms = materialProperties.program.getUniforms(),
31474				uniformsList =
31475					WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
31476  
31477			materialProperties.uniformsList = uniformsList;
31478  
31479		}
31480  
31481		function setProgram( camera, fog, material, object ) {
31482  
31483			_usedTextureUnits = 0;
31484  
31485			var materialProperties = properties.get( material );
31486			var lights = currentRenderState.state.lights;
31487  
31488			if ( _clippingEnabled ) {
31489  
31490				if ( _localClippingEnabled || camera !== _currentCamera ) {
31491  
31492					var useCache =
31493						camera === _currentCamera &&
31494						material.id === _currentMaterialId;
31495  
31496					// we might want to call this function with some ClippingGroup
31497					// object instead of the material, once it becomes feasible
31498					// (#8465, #8379)
31499					_clipping.setState(
31500						material.clippingPlanes, material.clipIntersection, material.clipShadows,
31501						camera, materialProperties, useCache );
31502  
31503				}
31504  
31505			}
31506  
31507			if ( material.needsUpdate === false ) {
31508  
31509				if ( materialProperties.program === undefined ) {
31510  
31511					material.needsUpdate = true;
31512  
31513				} else if ( material.fog && materialProperties.fog !== fog ) {
31514  
31515					material.needsUpdate = true;
31516  
31517				} else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) {
31518  
31519					material.needsUpdate = true;
31520  
31521				} else if ( materialProperties.numClippingPlanes !== undefined &&
31522					( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
31523					materialProperties.numIntersection !== _clipping.numIntersection ) ) {
31524  
31525					material.needsUpdate = true;
31526  
31527				}
31528  
31529			}
31530  
31531			if ( material.needsUpdate ) {
31532  
31533				initMaterial( material, fog, object );
31534				material.needsUpdate = false;
31535  
31536			}
31537  
31538			var refreshProgram = false;
31539			var refreshMaterial = false;
31540			var refreshLights = false;
31541  
31542			var program = materialProperties.program,
31543				p_uniforms = program.getUniforms(),
31544				m_uniforms = materialProperties.shader.uniforms;
31545  
31546			if ( state.useProgram( program.program ) ) {
31547  
31548				refreshProgram = true;
31549				refreshMaterial = true;
31550				refreshLights = true;
31551  
31552			}
31553  
31554			if ( material.id !== _currentMaterialId ) {
31555  
31556				_currentMaterialId = material.id;
31557  
31558				refreshMaterial = true;
31559  
31560			}
31561  
31562			if ( refreshProgram || camera !== _currentCamera ) {
31563  
31564				p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
31565  
31566				if ( capabilities.logarithmicDepthBuffer ) {
31567  
31568					p_uniforms.setValue( _gl, 'logDepthBufFC',
31569						2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
31570  
31571				}
31572  
31573				// Avoid unneeded uniform updates per ArrayCamera's sub-camera
31574  
31575				if ( _currentCamera !== ( _currentArrayCamera || camera ) ) {
31576  
31577					_currentCamera = ( _currentArrayCamera || camera );
31578  
31579					// lighting uniforms depend on the camera so enforce an update
31580					// now, in case this material supports lights - or later, when
31581					// the next material that does gets activated:
31582  
31583					refreshMaterial = true;		// set to true on material change
31584					refreshLights = true;		// remains set until update done
31585  
31586				}
31587  
31588				// load material specific uniforms
31589				// (shader material also gets them for the sake of genericity)
31590  
31591				if ( material.isShaderMaterial ||
31592					material.isMeshPhongMaterial ||
31593					material.isMeshStandardMaterial ||
31594					material.envMap ) {
31595  
31596					var uCamPos = p_uniforms.map.cameraPosition;
31597  
31598					if ( uCamPos !== undefined ) {
31599  
31600						uCamPos.setValue( _gl,
31601							_vector3.setFromMatrixPosition( camera.matrixWorld ) );
31602  
31603					}
31604  
31605				}
31606  
31607				if ( material.isMeshPhongMaterial ||
31608					material.isMeshLambertMaterial ||
31609					material.isMeshBasicMaterial ||
31610					material.isMeshStandardMaterial ||
31611					material.isShaderMaterial ||
31612					material.skinning ) {
31613  
31614					p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
31615  
31616				}
31617  
31618			}
31619  
31620			// skinning uniforms must be set even if material didn't change
31621			// auto-setting of texture unit for bone texture must go before other textures
31622			// not sure why, but otherwise weird things happen
31623  
31624			if ( material.skinning ) {
31625  
31626				p_uniforms.setOptional( _gl, object, 'bindMatrix' );
31627				p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
31628  
31629				var skeleton = object.skeleton;
31630  
31631				if ( skeleton ) {
31632  
31633					var bones = skeleton.bones;
31634  
31635					if ( capabilities.floatVertexTextures ) {
31636  
31637						if ( skeleton.boneTexture === undefined ) {
31638  
31639							// layout (1 matrix = 4 pixels)
31640							//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
31641							//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
31642							//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
31643							//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
31644							//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
31645  
31646  
31647							var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
vendor: 4,185 bytes, lines 31648-31801
31648							size = _Math.ceilPowerOfTwo( size );
31649							size = Math.max( size, 4 );
31650  
31651							var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
31652							boneMatrices.set( skeleton.boneMatrices ); // copy current values
31653  
31654							var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
31655							boneTexture.needsUpdate = true;
31656  
31657							skeleton.boneMatrices = boneMatrices;
31658							skeleton.boneTexture = boneTexture;
31659							skeleton.boneTextureSize = size;
31660  
31661						}
31662  
31663						p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture );
31664						p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
31665  
31666					} else {
31667  
31668						p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
31669  
31670					}
31671  
31672				}
31673  
31674			}
31675  
31676			if ( refreshMaterial ) {
31677  
31678				p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
31679				p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
31680  
31681				if ( material.lights ) {
31682  
31683					// the current material requires lighting info
31684  
31685					// note: all lighting uniforms are always set correctly
31686					// they simply reference the renderer's state for their
31687					// values
31688					//
31689					// use the current material's .needsUpdate flags to set
31690					// the GL state when required
31691  
31692					markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
31693  
31694				}
31695  
31696				// refresh uniforms common to several materials
31697  
31698				if ( fog && material.fog ) {
31699  
31700					refreshUniformsFog( m_uniforms, fog );
31701  
31702				}
31703  
31704				if ( material.isMeshBasicMaterial ) {
31705  
31706					refreshUniformsCommon( m_uniforms, material );
31707  
31708				} else if ( material.isMeshLambertMaterial ) {
31709  
31710					refreshUniformsCommon( m_uniforms, material );
31711					refreshUniformsLambert( m_uniforms, material );
31712  
31713				} else if ( material.isMeshPhongMaterial ) {
31714  
31715					refreshUniformsCommon( m_uniforms, material );
31716  
31717					if ( material.isMeshToonMaterial ) {
31718  
31719						refreshUniformsToon( m_uniforms, material );
31720  
31721					} else {
31722  
31723						refreshUniformsPhong( m_uniforms, material );
31724  
31725					}
31726  
31727				} else if ( material.isMeshStandardMaterial ) {
31728  
31729					refreshUniformsCommon( m_uniforms, material );
31730  
31731					if ( material.isMeshPhysicalMaterial ) {
31732  
31733						refreshUniformsPhysical( m_uniforms, material );
31734  
31735					} else {
31736  
31737						refreshUniformsStandard( m_uniforms, material );
31738  
31739					}
31740  
31741				} else if ( material.isMeshDepthMaterial ) {
31742  
31743					refreshUniformsCommon( m_uniforms, material );
31744					refreshUniformsDepth( m_uniforms, material );
31745  
31746				} else if ( material.isMeshDistanceMaterial ) {
31747  
31748					refreshUniformsCommon( m_uniforms, material );
31749					refreshUniformsDistance( m_uniforms, material );
31750  
31751				} else if ( material.isMeshNormalMaterial ) {
31752  
31753					refreshUniformsCommon( m_uniforms, material );
31754					refreshUniformsNormal( m_uniforms, material );
31755  
31756				} else if ( material.isLineBasicMaterial ) {
31757  
31758					refreshUniformsLine( m_uniforms, material );
31759  
31760					if ( material.isLineDashedMaterial ) {
31761  
31762						refreshUniformsDash( m_uniforms, material );
31763  
31764					}
31765  
31766				} else if ( material.isPointsMaterial ) {
31767  
31768					refreshUniformsPoints( m_uniforms, material );
31769  
31770				} else if ( material.isShadowMaterial ) {
31771  
31772					m_uniforms.color.value = material.color;
31773					m_uniforms.opacity.value = material.opacity;
31774  
31775				}
31776  
31777				// RectAreaLight Texture
31778				// TODO (mrdoob): Find a nicer implementation
31779  
31780				if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;
31781				if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;
31782  
31783				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
31784  
31785			}
31786  
31787			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
31788  
31789				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
31790				material.uniformsNeedUpdate = false;
31791  
31792			}
31793  
31794			// common matrices
31795  
31796			p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
31797			p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
31798			p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
31799  
31800			return program;
31801  
31802		}
31803  
31804		// Uniforms (refresh uniforms objects)
31805  
31806		function refreshUniformsCommon( uniforms, material ) {
31807  
31808			uniforms.opacity.value = material.opacity;
31809  
31810			if ( material.color ) {
31811  
31812				uniforms.diffuse.value = material.color;
31813  
31814			}
31815  
31816			if ( material.emissive ) {
31817  
31818				uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
31819  
31820			}
31821  
31822			if ( material.map ) {
31823  
31824				uniforms.map.value = material.map;
31825  
31826			}
31827  
31828			if ( material.alphaMap ) {
31829  
31830				uniforms.alphaMap.value = material.alphaMap;
31831  
31832			}
31833  
31834			if ( material.specularMap ) {
31835  
31836				uniforms.specularMap.value = material.specularMap;
31837  
31838			}
31839  
31840			if ( material.envMap ) {
31841  
31842				uniforms.envMap.value = material.envMap;
31843  
31844				// don't flip CubeTexture envMaps, flip everything else:
31845				//  WebGLRenderTargetCube will be flipped for backwards compatibility
31846				//  WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
31847				// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
31848				uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1;
31849  
31850				uniforms.reflectivity.value = material.reflectivity;
31851				uniforms.refractionRatio.value = material.refractionRatio;
31852  
31853				uniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;
31854  
31855			}
31856  
31857			if ( material.lightMap ) {
31858  
31859				uniforms.lightMap.value = material.lightMap;
31860				uniforms.lightMapIntensity.value = material.lightMapIntensity;
31861  
31862			}
31863  
31864			if ( material.aoMap ) {
31865  
31866				uniforms.aoMap.value = material.aoMap;
31867				uniforms.aoMapIntensity.value = material.aoMapIntensity;
31868  
31869			}
31870  
31871			// uv repeat and offset setting priorities
31872			// 1. color map
31873			// 2. specular map
31874			// 3. normal map
31875			// 4. bump map
31876			// 5. alpha map
31877			// 6. emissive map
31878  
31879			var uvScaleMap;
31880  
31881			if ( material.map ) {
31882  
31883				uvScaleMap = material.map;
31884  
31885			} else if ( material.specularMap ) {
31886  
31887				uvScaleMap = material.specularMap;
31888  
31889			} else if ( material.displacementMap ) {
31890  
31891				uvScaleMap = material.displacementMap;
31892  
31893			} else if ( material.normalMap ) {
31894  
31895				uvScaleMap = material.normalMap;
31896  
31897			} else if ( material.bumpMap ) {
31898  
31899				uvScaleMap = material.bumpMap;
31900  
31901			} else if ( material.roughnessMap ) {
31902  
31903				uvScaleMap = material.roughnessMap;
31904  
31905			} else if ( material.metalnessMap ) {
31906  
31907				uvScaleMap = material.metalnessMap;
31908  
31909			} else if ( material.alphaMap ) {
31910  
31911				uvScaleMap = material.alphaMap;
31912  
31913			} else if ( material.emissiveMap ) {
31914  
31915				uvScaleMap = material.emissiveMap;
31916  
31917			}
31918  
31919			if ( uvScaleMap !== undefined ) {
31920  
31921				// backwards compatibility
31922				if ( uvScaleMap.isWebGLRenderTarget ) {
31923  
31924					uvScaleMap = uvScaleMap.texture;
31925  
31926				}
31927  
31928				if ( uvScaleMap.matrixAutoUpdate === true ) {
31929  
31930					uvScaleMap.updateMatrix();
31931  
31932				}
31933  
31934				uniforms.uvTransform.value.copy( uvScaleMap.matrix );
31935  
31936			}
31937  
31938		}
31939  
31940		function refreshUniformsLine( uniforms, material ) {
31941  
31942			uniforms.diffuse.value = material.color;
31943			uniforms.opacity.value = material.opacity;
31944  
31945		}
31946  
31947		function refreshUniformsDash( uniforms, material ) {
31948  
31949			uniforms.dashSize.value = material.dashSize;
31950			uniforms.totalSize.value = material.dashSize + material.gapSize;
31951			uniforms.scale.value = material.scale;
31952  
31953		}
31954  
31955		function refreshUniformsPoints( uniforms, material ) {
31956  
31957			uniforms.diffuse.value = material.color;
31958			uniforms.opacity.value = material.opacity;
31959			uniforms.size.value = material.size * _pixelRatio;
31960			uniforms.scale.value = _height * 0.5;
31961  
31962			uniforms.map.value = material.map;
31963  
31964			if ( material.map !== null ) {
31965  
31966				if ( material.map.matrixAutoUpdate === true ) {
31967  
31968					material.map.updateMatrix();
31969  
31970				}
31971  
31972				uniforms.uvTransform.value.copy( material.map.matrix );
31973  
31974			}
31975  
31976		}
31977  
31978		function refreshUniformsFog( uniforms, fog ) {
31979  
31980			uniforms.fogColor.value = fog.color;
31981  
31982			if ( fog.isFog ) {
31983  
31984				uniforms.fogNear.value = fog.near;
31985				uniforms.fogFar.value = fog.far;
31986  
31987			} else if ( fog.isFogExp2 ) {
31988  
31989				uniforms.fogDensity.value = fog.density;
31990  
31991			}
31992  
31993		}
31994  
31995		function refreshUniformsLambert( uniforms, material ) {
31996  
31997			if ( material.emissiveMap ) {
31998  
31999				uniforms.emissiveMap.value = material.emissiveMap;
32000  
32001			}
32002  
32003		}
32004  
32005		function refreshUniformsPhong( uniforms, material ) {
32006  
32007			uniforms.specular.value = material.specular;
32008			uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
32009  
32010			if ( material.emissiveMap ) {
32011  
32012				uniforms.emissiveMap.value = material.emissiveMap;
32013  
32014			}
32015  
32016			if ( material.bumpMap ) {
32017  
32018				uniforms.bumpMap.value = material.bumpMap;
32019				uniforms.bumpScale.value = material.bumpScale;
32020				if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
32021  
32022			}
32023  
32024			if ( material.normalMap ) {
32025  
32026				uniforms.normalMap.value = material.normalMap;
32027				uniforms.normalScale.value.copy( material.normalScale );
32028				if ( material.side === BackSide ) uniforms.normalScale.value.negate();
32029  
32030			}
32031  
32032			if ( material.displacementMap ) {
32033  
32034				uniforms.displacementMap.value = material.displacementMap;
32035				uniforms.displacementScale.value = material.displacementScale;
32036				uniforms.displacementBias.value = material.displacementBias;
32037  
32038			}
32039  
32040		}
32041  
32042		function refreshUniformsToon( uniforms, material ) {
32043  
32044			refreshUniformsPhong( uniforms, material );
32045  
32046			if ( material.gradientMap ) {
32047  
32048				uniforms.gradientMap.value = material.gradientMap;
32049  
32050			}
32051  
32052		}
32053  
32054		function refreshUniformsStandard( uniforms, material ) {
32055  
32056			uniforms.roughness.value = material.roughness;
32057			uniforms.metalness.value = material.metalness;
32058  
32059			if ( material.roughnessMap ) {
32060  
32061				uniforms.roughnessMap.value = material.roughnessMap;
32062  
32063			}
32064  
32065			if ( material.metalnessMap ) {
32066  
32067				uniforms.metalnessMap.value = material.metalnessMap;
32068  
32069			}
32070  
32071			if ( material.emissiveMap ) {
32072  
32073				uniforms.emissiveMap.value = material.emissiveMap;
32074  
32075			}
32076  
32077			if ( material.bumpMap ) {
32078  
32079				uniforms.bumpMap.value = material.bumpMap;
32080				uniforms.bumpScale.value = material.bumpScale;
32081				if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
32082  
32083			}
32084  
32085			if ( material.normalMap ) {
32086  
32087				uniforms.normalMap.value = material.normalMap;
32088				uniforms.normalScale.value.copy( material.normalScale );
32089				if ( material.side === BackSide ) uniforms.normalScale.value.negate();
32090  
32091			}
32092  
32093			if ( material.displacementMap ) {
32094  
32095				uniforms.displacementMap.value = material.displacementMap;
32096				uniforms.displacementScale.value = material.displacementScale;
32097				uniforms.displacementBias.value = material.displacementBias;
32098  
32099			}
32100  
32101			if ( material.envMap ) {
32102  
32103				//uniforms.envMap.value = material.envMap; // part of uniforms common
32104				uniforms.envMapIntensity.value = material.envMapIntensity;
32105  
32106			}
32107  
32108		}
32109  
32110		function refreshUniformsPhysical( uniforms, material ) {
32111  
32112			uniforms.clearCoat.value = material.clearCoat;
32113			uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
32114  
32115			refreshUniformsStandard( uniforms, material );
32116  
32117		}
32118  
32119		function refreshUniformsDepth( uniforms, material ) {
32120  
32121			if ( material.displacementMap ) {
32122  
32123				uniforms.displacementMap.value = material.displacementMap;
32124				uniforms.displacementScale.value = material.displacementScale;
32125				uniforms.displacementBias.value = material.displacementBias;
32126  
32127			}
32128  
32129		}
32130  
32131		function refreshUniformsDistance( uniforms, material ) {
32132  
32133			if ( material.displacementMap ) {
32134  
32135				uniforms.displacementMap.value = material.displacementMap;
32136				uniforms.displacementScale.value = material.displacementScale;
32137				uniforms.displacementBias.value = material.displacementBias;
32138  
32139			}
32140  
32141			uniforms.referencePosition.value.copy( material.referencePosition );
32142			uniforms.nearDistance.value = material.nearDistance;
32143			uniforms.farDistance.value = material.farDistance;
32144  
32145		}
32146  
32147		function refreshUniformsNormal( uniforms, material ) {
32148  
32149			if ( material.bumpMap ) {
32150  
32151				uniforms.bumpMap.value = material.bumpMap;
32152				uniforms.bumpScale.value = material.bumpScale;
32153				if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
32154  
32155			}
32156  
32157			if ( material.normalMap ) {
32158  
32159				uniforms.normalMap.value = material.normalMap;
32160				uniforms.normalScale.value.copy( material.normalScale );
32161				if ( material.side === BackSide ) uniforms.normalScale.value.negate();
32162  
32163			}
32164  
32165			if ( material.displacementMap ) {
32166  
32167				uniforms.displacementMap.value = material.displacementMap;
32168				uniforms.displacementScale.value = material.displacementScale;
32169				uniforms.displacementBias.value = material.displacementBias;
32170  
32171			}
32172  
32173		}
32174  
32175		// If uniforms are marked as clean, they don't need to be loaded to the GPU.
32176  
32177		function markUniformsLightsNeedsUpdate( uniforms, value ) {
32178  
32179			uniforms.ambientLightColor.needsUpdate = value;
32180  
32181			uniforms.directionalLights.needsUpdate = value;
32182			uniforms.pointLights.needsUpdate = value;
32183			uniforms.spotLights.needsUpdate = value;
32184			uniforms.rectAreaLights.needsUpdate = value;
32185			uniforms.hemisphereLights.needsUpdate = value;
32186  
32187		}
32188  
32189		// Textures
32190  
32191		function allocTextureUnit() {
32192  
32193			var textureUnit = _usedTextureUnits;
32194  
32195			if ( textureUnit >= capabilities.maxTextures ) {
32196  
32197				console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
32198  
32199			}
32200  
32201			_usedTextureUnits += 1;
32202  
32203			return textureUnit;
32204  
32205		}
32206  
32207		this.allocTextureUnit = allocTextureUnit;
32208  
32209		// this.setTexture2D = setTexture2D;
32210		this.setTexture2D = ( function () {
32211  
32212			var warned = false;
32213  
32214			// backwards compatibility: peel texture.texture
32215			return function setTexture2D( texture, slot ) {
32216  
32217				if ( texture && texture.isWebGLRenderTarget ) {
32218  
32219					if ( ! warned ) {
32220  
32221						console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
32222						warned = true;
32223  
32224					}
32225  
32226					texture = texture.texture;
32227  
32228				}
32229  
32230				textures.setTexture2D( texture, slot );
32231  
32232			};
32233  
32234		}() );
32235  
32236		this.setTexture = ( function () {
32237  
32238			var warned = false;
32239  
32240			return function setTexture( texture, slot ) {
32241  
32242				if ( ! warned ) {
32243  
32244					console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
32245					warned = true;
32246  
32247				}
32248  
32249				textures.setTexture2D( texture, slot );
32250  
32251			};
32252  
32253		}() );
32254  
32255		this.setTextureCube = ( function () {
32256  
32257			var warned = false;
32258  
32259			return function setTextureCube( texture, slot ) {
32260  
32261				// backwards compatibility: peel texture.texture
32262				if ( texture && texture.isWebGLRenderTargetCube ) {
32263  
32264					if ( ! warned ) {
32265  
32266						console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
32267						warned = true;
32268  
32269					}
32270  
32271					texture = texture.texture;
32272  
32273				}
32274  
32275				// currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
32276				// TODO: unify these code paths
32277				if ( ( texture && texture.isCubeTexture ) ||
32278					( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
32279  
32280					// CompressedTexture can have Array in image :/
32281  
32282					// this function alone should take care of cube textures
32283					textures.setTextureCube( texture, slot );
32284  
32285				} else {
32286  
32287					// assumed: texture property of THREE.WebGLRenderTargetCube
32288  
32289					textures.setTextureCubeDynamic( texture, slot );
32290  
32291				}
32292  
32293			};
32294  
32295		}() );
32296  
32297		//
32298  
32299		this.setFramebuffer = function ( value ) {
32300  
32301			_framebuffer = value;
32302  
32303		};
32304  
32305		this.getRenderTarget = function () {
32306  
32307			return _currentRenderTarget;
32308  
32309		};
32310  
32311		this.setRenderTarget = function ( renderTarget ) {
32312  
32313			_currentRenderTarget = renderTarget;
32314  
32315			if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
32316  
32317				textures.setupRenderTarget( renderTarget );
32318  
32319			}
32320  
32321			var framebuffer = _framebuffer;
32322			var isCube = false;
32323  
32324			if ( renderTarget ) {
32325  
32326				var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
32327  
32328				if ( renderTarget.isWebGLRenderTargetCube ) {
32329  
32330					framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ];
32331					isCube = true;
32332  
32333				} else {
32334  
32335					framebuffer = __webglFramebuffer;
32336  
32337				}
32338  
32339				_currentViewport.copy( renderTarget.viewport );
32340				_currentScissor.copy( renderTarget.scissor );
32341				_currentScissorTest = renderTarget.scissorTest;
32342  
32343			} else {
32344  
32345				_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
32346				_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
32347				_currentScissorTest = _scissorTest;
32348  
32349			}
32350  
32351			if ( _currentFramebuffer !== framebuffer ) {
32352  
32353				_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
32354				_currentFramebuffer = framebuffer;
32355  
32356			}
32357  
32358			state.viewport( _currentViewport );
32359			state.scissor( _currentScissor );
32360			state.setScissorTest( _currentScissorTest );
32361  
32362			if ( isCube ) {
32363  
32364				var textureProperties = properties.get( renderTarget.texture );
32365				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel );
32366  
32367			}
32368  
32369		};
32370  
32371		this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
32372  
32373			if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
32374  
32375				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
32376				return;
32377  
32378			}
32379  
32380			var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
32381  
32382			if ( framebuffer ) {
32383  
32384				var restore = false;
32385  
32386				if ( framebuffer !== _currentFramebuffer ) {
32387  
32388					_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
32389  
32390					restore = true;
32391  
32392				}
32393  
32394				try {
32395  
32396					var texture = renderTarget.texture;
32397					var textureFormat = texture.format;
32398					var textureType = texture.type;
32399  
32400					if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
32401  
32402						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
32403						return;
32404  
32405					}
32406  
32407					if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
32408						! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
32409						! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
32410  
32411						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
32412						return;
32413  
32414					}
32415  
32416					if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
32417  
32418						// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
32419  
32420						if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
32421  
32422							_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
32423  
32424						}
32425  
32426					} else {
32427  
32428						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
32429  
32430					}
32431  
32432				} finally {
32433  
32434					if ( restore ) {
32435  
32436						_gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
32437  
32438					}
32439  
32440				}
32441  
32442			}
32443  
32444		};
32445  
32446		this.copyFramebufferToTexture = function ( position, texture, level ) {
32447  
32448			var width = texture.image.width;
32449			var height = texture.image.height;
32450			var glFormat = utils.convert( texture.format );
32451  
32452			this.setTexture2D( texture, 0 );
32453  
32454			_gl.copyTexImage2D( _gl.TEXTURE_2D, level || 0, glFormat, position.x, position.y, width, height, 0 );
32455  
32456		};
32457  
32458		this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {
32459  
32460			var width = srcTexture.image.width;
32461			var height = srcTexture.image.height;
32462			var glFormat = utils.convert( dstTexture.format );
32463			var glType = utils.convert( dstTexture.type );
32464  
32465			this.setTexture2D( dstTexture, 0 );
32466  
32467			if ( srcTexture.isDataTexture ) {
32468  
32469				_gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
32470  
32471			} else {
32472  
32473				_gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, glFormat, glType, srcTexture.image );
32474  
32475			}
32476  
32477		};
32478  
32479	}
32480  
32481	/**
32482	 * @author mrdoob / http://mrdoob.com/
32483	 * @author alteredq / http://alteredqualia.com/
32484	 */
32485  
32486	function FogExp2( color, density ) {
32487  
32488		this.name = '';
32489  
32490		this.color = new Color( color );
32491		this.density = ( density !== undefined ) ? density : 0.00025;
32492  
32493	}
32494  
32495	FogExp2.prototype.isFogExp2 = true;
32496  
32497	FogExp2.prototype.clone = function () {
32498  
32499		return new FogExp2( this.color, this.density );
32500  
32501	};
32502  
32503	FogExp2.prototype.toJSON = function ( /* meta */ ) {
32504  
32505		return {
32506			type: 'FogExp2',
32507			color: this.color.getHex(),
32508			density: this.density
32509		};
32510  
32511	};
32512  
32513	/**
32514	 * @author mrdoob / http://mrdoob.com/
32515	 * @author alteredq / http://alteredqualia.com/
32516	 */
32517  
32518	function Fog( color, near, far ) {
32519  
32520		this.name = '';
32521  
32522		this.color = new Color( color );
32523  
32524		this.near = ( near !== undefined ) ? near : 1;
32525		this.far = ( far !== undefined ) ? far : 1000;
32526  
32527	}
32528  
32529	Fog.prototype.isFog = true;
32530  
32531	Fog.prototype.clone = function () {
32532  
32533		return new Fog( this.color, this.near, this.far );
32534  
32535	};
32536  
32537	Fog.prototype.toJSON = function ( /* meta */ ) {
32538  
32539		return {
32540			type: 'Fog',
32541			color: this.color.getHex(),
32542			near: this.near,
32543			far: this.far
32544		};
32545  
32546	};
32547  
32548	/**
32549	 * @author mrdoob / http://mrdoob.com/
32550	 */
32551  
32552	function Scene() {
32553  
32554		Object3D.call( this );
32555  
32556		this.type = 'Scene';
32557  
32558		this.background = null;
32559		this.fog = null;
32560		this.overrideMaterial = null;
32561  
32562		this.autoUpdate = true; // checked by the renderer
32563  
32564	}
32565  
32566	Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
32567  
32568		constructor: Scene,
32569  
32570		copy: function ( source, recursive ) {
32571  
32572			Object3D.prototype.copy.call( this, source, recursive );
32573  
32574			if ( source.background !== null ) this.background = source.background.clone();
32575			if ( source.fog !== null ) this.fog = source.fog.clone();
32576			if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
32577  
32578			this.autoUpdate = source.autoUpdate;
32579			this.matrixAutoUpdate = source.matrixAutoUpdate;
32580  
32581			return this;
32582  
32583		},
32584  
32585		toJSON: function ( meta ) {
32586  
32587			var data = Object3D.prototype.toJSON.call( this, meta );
32588  
32589			if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
32590			if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
32591  
32592			return data;
32593  
32594		}
32595  
32596	} );
32597  
32598	/**
32599	 * @author alteredq / http://alteredqualia.com/
32600	 *
32601	 * parameters = {
32602	 *  color: <hex>,
32603	 *  opacity: <float>,
32604	 *  map: new THREE.Texture( <Image> ),
32605	 *
32606	 *	uvOffset: new THREE.Vector2(),
32607	 *	uvScale: new THREE.Vector2()
32608	 * }
32609	 */
32610  
32611	function SpriteMaterial( parameters ) {
32612  
32613		Material.call( this );
32614  
32615		this.type = 'SpriteMaterial';
32616  
32617		this.color = new Color( 0xffffff );
32618		this.map = null;
32619  
32620		this.rotation = 0;
32621  
32622		this.fog = false;
32623		this.lights = false;
32624  
32625		this.setValues( parameters );
32626  
32627	}
32628  
32629	SpriteMaterial.prototype = Object.create( Material.prototype );
32630	SpriteMaterial.prototype.constructor = SpriteMaterial;
32631	SpriteMaterial.prototype.isSpriteMaterial = true;
32632  
32633	SpriteMaterial.prototype.copy = function ( source ) {
32634  
32635		Material.prototype.copy.call( this, source );
32636  
32637		this.color.copy( source.color );
32638		this.map = source.map;
32639  
32640		this.rotation = source.rotation;
32641  
32642		return this;
32643  
32644	};
32645  
32646	/**
32647	 * @author mikael emtinger / http://gomo.se/
32648	 * @author alteredq / http://alteredqualia.com/
32649	 */
32650  
32651	function Sprite( material ) {
32652  
32653		Object3D.call( this );
32654  
32655		this.type = 'Sprite';
32656  
32657		this.material = ( material !== undefined ) ? material : new SpriteMaterial();
32658  
32659		this.center = new Vector2( 0.5, 0.5 );
32660  
32661	}
32662  
32663	Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
32664  
32665		constructor: Sprite,
32666  
32667		isSprite: true,
32668  
32669		raycast: ( function () {
32670  
32671			var intersectPoint = new Vector3();
32672			var worldPosition = new Vector3();
32673			var worldScale = new Vector3();
32674  
32675			return function raycast( raycaster, intersects ) {
32676  
32677				worldPosition.setFromMatrixPosition( this.matrixWorld );
32678				raycaster.ray.closestPointToPoint( worldPosition, intersectPoint );
32679  
32680				worldScale.setFromMatrixScale( this.matrixWorld );
32681				var guessSizeSq = worldScale.x * worldScale.y / 4;
32682  
32683				if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return;
32684  
32685				var distance = raycaster.ray.origin.distanceTo( intersectPoint );
32686  
32687				if ( distance < raycaster.near || distance > raycaster.far ) return;
32688  
32689				intersects.push( {
32690  
32691					distance: distance,
32692					point: intersectPoint.clone(),
32693					face: null,
32694					object: this
32695  
32696				} );
32697  
32698			};
32699  
32700		}() ),
32701  
32702		clone: function () {
32703  
32704			return new this.constructor( this.material ).copy( this );
32705  
32706		},
32707  
32708		copy: function ( source ) {
32709  
32710			Object3D.prototype.copy.call( this, source );
32711  
32712			if ( source.center !== undefined ) this.center.copy( source.center );
32713  
32714			return this;
32715  
32716		}
32717  
32718  
32719	} );
32720  
32721	/**
32722	 * @author mikael emtinger / http://gomo.se/
32723	 * @author alteredq / http://alteredqualia.com/
32724	 * @author mrdoob / http://mrdoob.com/
32725	 */
32726  
32727	function LOD() {
32728  
32729		Object3D.call( this );
32730  
32731		this.type = 'LOD';
32732  
32733		Object.defineProperties( this, {
32734			levels: {
32735				enumerable: true,
32736				value: []
32737			}
32738		} );
32739  
32740	}
32741  
32742	LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
32743  
32744		constructor: LOD,
32745  
32746		copy: function ( source ) {
32747  
32748			Object3D.prototype.copy.call( this, source, false );
32749  
32750			var levels = source.levels;
32751  
32752			for ( var i = 0, l = levels.length; i < l; i ++ ) {
32753  
32754				var level = levels[ i ];
32755  
32756				this.addLevel( level.object.clone(), level.distance );
32757  
32758			}
32759  
32760			return this;
32761  
32762		},
32763  
32764		addLevel: function ( object, distance ) {
32765  
32766			if ( distance === undefined ) distance = 0;
32767  
32768			distance = Math.abs( distance );
32769  
32770			var levels = this.levels;
32771  
32772			for ( var l = 0; l < levels.length; l ++ ) {
32773  
32774				if ( distance < levels[ l ].distance ) {
32775  
32776					break;
32777  
32778				}
32779  
32780			}
32781  
32782			levels.splice( l, 0, { distance: distance, object: object } );
32783  
32784			this.add( object );
32785  
32786		},
32787  
32788		getObjectForDistance: function ( distance ) {
32789  
32790			var levels = this.levels;
32791  
32792			for ( var i = 1, l = levels.length; i < l; i ++ ) {
32793  
32794				if ( distance < levels[ i ].distance ) {
32795  
32796					break;
32797  
32798				}
32799  
32800			}
32801  
32802			return levels[ i - 1 ].object;
32803  
32804		},
32805  
32806		raycast: ( function () {
32807  
32808			var matrixPosition = new Vector3();
32809  
32810			return function raycast( raycaster, intersects ) {
32811  
32812				matrixPosition.setFromMatrixPosition( this.matrixWorld );
32813  
32814				var distance = raycaster.ray.origin.distanceTo( matrixPosition );
32815  
32816				this.getObjectForDistance( distance ).raycast( raycaster, intersects );
32817  
32818			};
32819  
32820		}() ),
32821  
32822		update: function () {
32823  
32824			var v1 = new Vector3();
32825			var v2 = new Vector3();
32826  
32827			return function update( camera ) {
32828  
32829				var levels = this.levels;
32830  
32831				if ( levels.length > 1 ) {
32832  
32833					v1.setFromMatrixPosition( camera.matrixWorld );
32834					v2.setFromMatrixPosition( this.matrixWorld );
32835  
32836					var distance = v1.distanceTo( v2 );
32837  
32838					levels[ 0 ].object.visible = true;
32839  
32840					for ( var i = 1, l = levels.length; i < l; i ++ ) {
32841  
32842						if ( distance >= levels[ i ].distance ) {
32843  
32844							levels[ i - 1 ].object.visible = false;
32845							levels[ i ].object.visible = true;
32846  
32847						} else {
32848  
32849							break;
32850  
32851						}
32852  
32853					}
32854  
32855					for ( ; i < l; i ++ ) {
32856  
32857						levels[ i ].object.visible = false;
32858  
32859					}
32860  
32861				}
32862  
32863			};
32864  
32865		}(),
32866  
32867		toJSON: function ( meta ) {
32868  
32869			var data = Object3D.prototype.toJSON.call( this, meta );
32870  
32871			data.object.levels = [];
32872  
32873			var levels = this.levels;
32874  
32875			for ( var i = 0, l = levels.length; i < l; i ++ ) {
32876  
32877				var level = levels[ i ];
32878  
32879				data.object.levels.push( {
32880					object: level.object.uuid,
32881					distance: level.distance
32882				} );
32883  
32884			}
32885  
32886			return data;
32887  
32888		}
32889  
32890	} );
32891  
32892	/**
32893	 * @author mikael emtinger / http://gomo.se/
32894	 * @author alteredq / http://alteredqualia.com/
32895	 * @author michael guerrero / http://realitymeltdown.com
32896	 * @author ikerr / http://verold.com
32897	 */
32898  
32899	function Skeleton( bones, boneInverses ) {
32900  
32901		// copy the bone array
32902  
32903		bones = bones || [];
32904  
32905		this.bones = bones.slice( 0 );
32906		this.boneMatrices = new Float32Array( this.bones.length * 16 );
32907  
32908		// use the supplied bone inverses or calculate the inverses
32909  
32910		if ( boneInverses === undefined ) {
32911  
32912			this.calculateInverses();
32913  
32914		} else {
32915  
32916			if ( this.bones.length === boneInverses.length ) {
32917  
32918				this.boneInverses = boneInverses.slice( 0 );
32919  
32920			} else {
32921  
32922				console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
32923  
32924				this.boneInverses = [];
32925  
32926				for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
32927  
32928					this.boneInverses.push( new Matrix4() );
32929  
32930				}
32931  
32932			}
32933  
32934		}
32935  
32936	}
32937  
32938	Object.assign( Skeleton.prototype, {
32939  
32940		calculateInverses: function () {
32941  
32942			this.boneInverses = [];
32943  
32944			for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
32945  
32946				var inverse = new Matrix4();
32947  
32948				if ( this.bones[ i ] ) {
32949  
32950					inverse.getInverse( this.bones[ i ].matrixWorld );
32951  
32952				}
32953  
32954				this.boneInverses.push( inverse );
32955  
32956			}
32957  
32958		},
32959  
32960		pose: function () {
32961  
32962			var bone, i, il;
32963  
32964			// recover the bind-time world matrices
32965  
32966			for ( i = 0, il = this.bones.length; i < il; i ++ ) {
32967  
32968				bone = this.bones[ i ];
32969  
32970				if ( bone ) {
32971  
32972					bone.matrixWorld.getInverse( this.boneInverses[ i ] );
32973  
32974				}
32975  
32976			}
32977  
32978			// compute the local matrices, positions, rotations and scales
32979  
32980			for ( i = 0, il = this.bones.length; i < il; i ++ ) {
32981  
32982				bone = this.bones[ i ];
32983  
32984				if ( bone ) {
32985  
32986					if ( bone.parent && bone.parent.isBone ) {
32987  
32988						bone.matrix.getInverse( bone.parent.matrixWorld );
32989						bone.matrix.multiply( bone.matrixWorld );
32990  
32991					} else {
32992  
32993						bone.matrix.copy( bone.matrixWorld );
32994  
32995					}
32996  
32997					bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
32998  
32999				}
33000  
33001			}
33002  
33003		},
33004  
33005		update: ( function () {
33006  
33007			var offsetMatrix = new Matrix4();
33008			var identityMatrix = new Matrix4();
33009  
33010			return function update() {
33011  
33012				var bones = this.bones;
33013				var boneInverses = this.boneInverses;
33014				var boneMatrices = this.boneMatrices;
33015				var boneTexture = this.boneTexture;
33016  
33017				// flatten bone matrices to array
33018  
33019				for ( var i = 0, il = bones.length; i < il; i ++ ) {
33020  
33021					// compute the offset between the current and the original transform
33022  
33023					var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
33024  
33025					offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
33026					offsetMatrix.toArray( boneMatrices, i * 16 );
33027  
33028				}
33029  
33030				if ( boneTexture !== undefined ) {
33031  
33032					boneTexture.needsUpdate = true;
33033  
33034				}
33035  
33036			};
33037  
33038		} )(),
33039  
33040		clone: function () {
33041  
33042			return new Skeleton( this.bones, this.boneInverses );
33043  
33044		},
33045  
33046		getBoneByName: function ( name ) {
33047  
33048			for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
33049  
33050				var bone = this.bones[ i ];
33051  
33052				if ( bone.name === name ) {
33053  
33054					return bone;
33055  
33056				}
33057  
33058			}
33059  
33060			return undefined;
33061  
33062		}
33063  
33064	} );
33065  
33066	/**
33067	 * @author mikael emtinger / http://gomo.se/
33068	 * @author alteredq / http://alteredqualia.com/
33069	 * @author ikerr / http://verold.com
33070	 */
33071  
33072	function Bone() {
33073  
33074		Object3D.call( this );
33075  
33076		this.type = 'Bone';
33077  
33078	}
33079  
33080	Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
33081  
33082		constructor: Bone,
33083  
33084		isBone: true
33085  
33086	} );
33087  
33088	/**
33089	 * @author mikael emtinger / http://gomo.se/
33090	 * @author alteredq / http://alteredqualia.com/
33091	 * @author ikerr / http://verold.com
33092	 */
33093  
33094	function SkinnedMesh( geometry, material ) {
33095  
33096		Mesh.call( this, geometry, material );
33097  
33098		this.type = 'SkinnedMesh';
33099  
33100		this.bindMode = 'attached';
33101		this.bindMatrix = new Matrix4();
33102		this.bindMatrixInverse = new Matrix4();
33103  
33104		var bones = this.initBones();
33105		var skeleton = new Skeleton( bones );
33106  
33107		this.bind( skeleton, this.matrixWorld );
33108  
33109		this.normalizeSkinWeights();
33110  
33111	}
33112  
33113	SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
33114  
33115		constructor: SkinnedMesh,
33116  
33117		isSkinnedMesh: true,
33118  
33119		initBones: function () {
33120  
33121			var bones = [], bone, gbone;
33122			var i, il;
33123  
33124			if ( this.geometry && this.geometry.bones !== undefined ) {
33125  
33126				// first, create array of 'Bone' objects from geometry data
33127  
33128				for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
33129  
33130					gbone = this.geometry.bones[ i ];
33131  
33132					// create new 'Bone' object
33133  
33134					bone = new Bone();
33135					bones.push( bone );
33136  
33137					// apply values
33138  
33139					bone.name = gbone.name;
33140					bone.position.fromArray( gbone.pos );
33141					bone.quaternion.fromArray( gbone.rotq );
33142					if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
33143  
33144				}
33145  
33146				// second, create bone hierarchy
33147  
33148				for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
33149  
33150					gbone = this.geometry.bones[ i ];
33151  
33152					if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
33153  
33154						// subsequent bones in the hierarchy
33155  
33156						bones[ gbone.parent ].add( bones[ i ] );
33157  
33158					} else {
33159  
33160						// topmost bone, immediate child of the skinned mesh
33161  
33162						this.add( bones[ i ] );
33163  
33164					}
33165  
33166				}
33167  
33168			}
33169  
33170			// now the bones are part of the scene graph and children of the skinned mesh.
33171			// let's update the corresponding matrices
33172  
33173			this.updateMatrixWorld( true );
33174  
33175			return bones;
33176  
33177		},
33178  
33179		bind: function ( skeleton, bindMatrix ) {
33180  
33181			this.skeleton = skeleton;
33182  
33183			if ( bindMatrix === undefined ) {
33184  
33185				this.updateMatrixWorld( true );
33186  
33187				this.skeleton.calculateInverses();
33188  
33189				bindMatrix = this.matrixWorld;
33190  
33191			}
33192  
33193			this.bindMatrix.copy( bindMatrix );
33194			this.bindMatrixInverse.getInverse( bindMatrix );
33195  
33196		},
33197  
33198		pose: function () {
33199  
33200			this.skeleton.pose();
33201  
33202		},
33203  
33204		normalizeSkinWeights: function () {
33205  
33206			var scale, i;
33207  
33208			if ( this.geometry && this.geometry.isGeometry ) {
33209  
33210				for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
33211  
33212					var sw = this.geometry.skinWeights[ i ];
33213  
33214					scale = 1.0 / sw.manhattanLength();
33215  
33216					if ( scale !== Infinity ) {
33217  
33218						sw.multiplyScalar( scale );
33219  
33220					} else {
33221  
33222						sw.set( 1, 0, 0, 0 );
vendor: 11,272 bytes, lines 33222-33711
33222 // do something reasonable
33223  
33224					}
33225  
33226				}
33227  
33228			} else if ( this.geometry && this.geometry.isBufferGeometry ) {
33229  
33230				var vec = new Vector4();
33231  
33232				var skinWeight = this.geometry.attributes.skinWeight;
33233  
33234				for ( i = 0; i < skinWeight.count; i ++ ) {
33235  
33236					vec.x = skinWeight.getX( i );
33237					vec.y = skinWeight.getY( i );
33238					vec.z = skinWeight.getZ( i );
33239					vec.w = skinWeight.getW( i );
33240  
33241					scale = 1.0 / vec.manhattanLength();
33242  
33243					if ( scale !== Infinity ) {
33244  
33245						vec.multiplyScalar( scale );
33246  
33247					} else {
33248  
33249						vec.set( 1, 0, 0, 0 ); // do something reasonable
33250  
33251					}
33252  
33253					skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
33254  
33255				}
33256  
33257			}
33258  
33259		},
33260  
33261		updateMatrixWorld: function ( force ) {
33262  
33263			Mesh.prototype.updateMatrixWorld.call( this, force );
33264  
33265			if ( this.bindMode === 'attached' ) {
33266  
33267				this.bindMatrixInverse.getInverse( this.matrixWorld );
33268  
33269			} else if ( this.bindMode === 'detached' ) {
33270  
33271				this.bindMatrixInverse.getInverse( this.bindMatrix );
33272  
33273			} else {
33274  
33275				console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
33276  
33277			}
33278  
33279		},
33280  
33281		clone: function () {
33282  
33283			return new this.constructor( this.geometry, this.material ).copy( this );
33284  
33285		}
33286  
33287	} );
33288  
33289	/**
33290	 * @author mrdoob / http://mrdoob.com/
33291	 * @author alteredq / http://alteredqualia.com/
33292	 *
33293	 * parameters = {
33294	 *  color: <hex>,
33295	 *  opacity: <float>,
33296	 *
33297	 *  linewidth: <float>,
33298	 *  linecap: "round",
33299	 *  linejoin: "round"
33300	 * }
33301	 */
33302  
33303	function LineBasicMaterial( parameters ) {
33304  
33305		Material.call( this );
33306  
33307		this.type = 'LineBasicMaterial';
33308  
33309		this.color = new Color( 0xffffff );
33310  
33311		this.linewidth = 1;
33312		this.linecap = 'round';
33313		this.linejoin = 'round';
33314  
33315		this.lights = false;
33316  
33317		this.setValues( parameters );
33318  
33319	}
33320  
33321	LineBasicMaterial.prototype = Object.create( Material.prototype );
33322	LineBasicMaterial.prototype.constructor = LineBasicMaterial;
33323  
33324	LineBasicMaterial.prototype.isLineBasicMaterial = true;
33325  
33326	LineBasicMaterial.prototype.copy = function ( source ) {
33327  
33328		Material.prototype.copy.call( this, source );
33329  
33330		this.color.copy( source.color );
33331  
33332		this.linewidth = source.linewidth;
33333		this.linecap = source.linecap;
33334		this.linejoin = source.linejoin;
33335  
33336		return this;
33337  
33338	};
33339  
33340	/**
33341	 * @author mrdoob / http://mrdoob.com/
33342	 */
33343  
33344	function Line( geometry, material, mode ) {
33345  
33346		if ( mode === 1 ) {
33347  
33348			console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
33349			return new LineSegments( geometry, material );
33350  
33351		}
33352  
33353		Object3D.call( this );
33354  
33355		this.type = 'Line';
33356  
33357		this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
33358		this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
33359  
33360	}
33361  
33362	Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
33363  
33364		constructor: Line,
33365  
33366		isLine: true,
33367  
33368		computeLineDistances: ( function () {
33369  
33370			var start = new Vector3();
33371			var end = new Vector3();
33372  
33373			return function computeLineDistances() {
33374  
33375				var geometry = this.geometry;
33376  
33377				if ( geometry.isBufferGeometry ) {
33378  
33379					// we assume non-indexed geometry
33380  
33381					if ( geometry.index === null ) {
33382  
33383						var positionAttribute = geometry.attributes.position;
33384						var lineDistances = [ 0 ];
33385  
33386						for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
33387  
33388							start.fromBufferAttribute( positionAttribute, i - 1 );
33389							end.fromBufferAttribute( positionAttribute, i );
33390  
33391							lineDistances[ i ] = lineDistances[ i - 1 ];
33392							lineDistances[ i ] += start.distanceTo( end );
33393  
33394						}
33395  
33396						geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
33397  
33398					} else {
33399  
33400						console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
33401  
33402					}
33403  
33404				} else if ( geometry.isGeometry ) {
33405  
33406					var vertices = geometry.vertices;
33407					var lineDistances = geometry.lineDistances;
33408  
33409					lineDistances[ 0 ] = 0;
33410  
33411					for ( var i = 1, l = vertices.length; i < l; i ++ ) {
33412  
33413						lineDistances[ i ] = lineDistances[ i - 1 ];
33414						lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
33415  
33416					}
33417  
33418				}
33419  
33420				return this;
33421  
33422			};
33423  
33424		}() ),
33425  
33426		raycast: ( function () {
33427  
33428			var inverseMatrix = new Matrix4();
33429			var ray = new Ray();
33430			var sphere = new Sphere();
33431  
33432			return function raycast( raycaster, intersects ) {
33433  
33434				var precision = raycaster.linePrecision;
33435				var precisionSq = precision * precision;
33436  
33437				var geometry = this.geometry;
33438				var matrixWorld = this.matrixWorld;
33439  
33440				// Checking boundingSphere distance to ray
33441  
33442				if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
33443  
33444				sphere.copy( geometry.boundingSphere );
33445				sphere.applyMatrix4( matrixWorld );
33446  
33447				if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
33448  
33449				//
33450  
33451				inverseMatrix.getInverse( matrixWorld );
33452				ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
33453  
33454				var vStart = new Vector3();
33455				var vEnd = new Vector3();
33456				var interSegment = new Vector3();
33457				var interRay = new Vector3();
33458				var step = ( this && this.isLineSegments ) ? 2 : 1;
33459  
33460				if ( geometry.isBufferGeometry ) {
33461  
33462					var index = geometry.index;
33463					var attributes = geometry.attributes;
33464					var positions = attributes.position.array;
33465  
33466					if ( index !== null ) {
33467  
33468						var indices = index.array;
33469  
33470						for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
33471  
33472							var a = indices[ i ];
33473							var b = indices[ i + 1 ];
33474  
33475							vStart.fromArray( positions, a * 3 );
33476							vEnd.fromArray( positions, b * 3 );
33477  
33478							var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
33479  
33480							if ( distSq > precisionSq ) continue;
33481  
33482							interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
33483  
33484							var distance = raycaster.ray.origin.distanceTo( interRay );
33485  
33486							if ( distance < raycaster.near || distance > raycaster.far ) continue;
33487  
33488							intersects.push( {
33489  
33490								distance: distance,
33491								// What do we want? intersection point on the ray or on the segment??
33492								// point: raycaster.ray.at( distance ),
33493								point: interSegment.clone().applyMatrix4( this.matrixWorld ),
33494								index: i,
33495								face: null,
33496								faceIndex: null,
33497								object: this
33498  
33499							} );
33500  
33501						}
33502  
33503					} else {
33504  
33505						for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
33506  
33507							vStart.fromArray( positions, 3 * i );
33508							vEnd.fromArray( positions, 3 * i + 3 );
33509  
33510							var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
33511  
33512							if ( distSq > precisionSq ) continue;
33513  
33514							interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
33515  
33516							var distance = raycaster.ray.origin.distanceTo( interRay );
33517  
33518							if ( distance < raycaster.near || distance > raycaster.far ) continue;
33519  
33520							intersects.push( {
33521  
33522								distance: distance,
33523								// What do we want? intersection point on the ray or on the segment??
33524								// point: raycaster.ray.at( distance ),
33525								point: interSegment.clone().applyMatrix4( this.matrixWorld ),
33526								index: i,
33527								face: null,
33528								faceIndex: null,
33529								object: this
33530  
33531							} );
33532  
33533						}
33534  
33535					}
33536  
33537				} else if ( geometry.isGeometry ) {
33538  
33539					var vertices = geometry.vertices;
33540					var nbVertices = vertices.length;
33541  
33542					for ( var i = 0; i < nbVertices - 1; i += step ) {
33543  
33544						var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
33545  
33546						if ( distSq > precisionSq ) continue;
33547  
33548						interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
33549  
33550						var distance = raycaster.ray.origin.distanceTo( interRay );
33551  
33552						if ( distance < raycaster.near || distance > raycaster.far ) continue;
33553  
33554						intersects.push( {
33555  
33556							distance: distance,
33557							// What do we want? intersection point on the ray or on the segment??
33558							// point: raycaster.ray.at( distance ),
33559							point: interSegment.clone().applyMatrix4( this.matrixWorld ),
33560							index: i,
33561							face: null,
33562							faceIndex: null,
33563							object: this
33564  
33565						} );
33566  
33567					}
33568  
33569				}
33570  
33571			};
33572  
33573		}() ),
33574  
33575		clone: function () {
33576  
33577			return new this.constructor( this.geometry, this.material ).copy( this );
33578  
33579		}
33580  
33581	} );
33582  
33583	/**
33584	 * @author mrdoob / http://mrdoob.com/
33585	 */
33586  
33587	function LineSegments( geometry, material ) {
33588  
33589		Line.call( this, geometry, material );
33590  
33591		this.type = 'LineSegments';
33592  
33593	}
33594  
33595	LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
33596  
33597		constructor: LineSegments,
33598  
33599		isLineSegments: true,
33600  
33601		computeLineDistances: ( function () {
33602  
33603			var start = new Vector3();
33604			var end = new Vector3();
33605  
33606			return function computeLineDistances() {
33607  
33608				var geometry = this.geometry;
33609  
33610				if ( geometry.isBufferGeometry ) {
33611  
33612					// we assume non-indexed geometry
33613  
33614					if ( geometry.index === null ) {
33615  
33616						var positionAttribute = geometry.attributes.position;
33617						var lineDistances = [];
33618  
33619						for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
33620  
33621							start.fromBufferAttribute( positionAttribute, i );
33622							end.fromBufferAttribute( positionAttribute, i + 1 );
33623  
33624							lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
33625							lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
33626  
33627						}
33628  
33629						geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
33630  
33631					} else {
33632  
33633						console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
33634  
33635					}
33636  
33637				} else if ( geometry.isGeometry ) {
33638  
33639					var vertices = geometry.vertices;
33640					var lineDistances = geometry.lineDistances;
33641  
33642					for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
33643  
33644						start.copy( vertices[ i ] );
33645						end.copy( vertices[ i + 1 ] );
33646  
33647						lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
33648						lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
33649  
33650					}
33651  
33652				}
33653  
33654				return this;
33655  
33656			};
33657  
33658		}() )
33659  
33660	} );
33661  
33662	/**
33663	 * @author mgreter / http://github.com/mgreter
33664	 */
33665  
33666	function LineLoop( geometry, material ) {
33667  
33668		Line.call( this, geometry, material );
33669  
33670		this.type = 'LineLoop';
33671  
33672	}
33673  
33674	LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
33675  
33676		constructor: LineLoop,
33677  
33678		isLineLoop: true,
33679  
33680	} );
33681  
33682	/**
33683	 * @author mrdoob / http://mrdoob.com/
33684	 * @author alteredq / http://alteredqualia.com/
33685	 *
33686	 * parameters = {
33687	 *  color: <hex>,
33688	 *  opacity: <float>,
33689	 *  map: new THREE.Texture( <Image> ),
33690	 *
33691	 *  size: <float>,
33692	 *  sizeAttenuation: <bool>
33693	 *
33694	 *  morphTargets: <bool>
33695	 * }
33696	 */
33697  
33698	function PointsMaterial( parameters ) {
33699  
33700		Material.call( this );
33701  
33702		this.type = 'PointsMaterial';
33703  
33704		this.color = new Color( 0xffffff );
33705  
33706		this.map = null;
33707  
33708		this.size = 1;
33709		this.sizeAttenuation = true;
33710  
33711		this.morphTargets = false;
33712  
33713		this.lights = false;
33714  
33715		this.setValues( parameters );
33716  
33717	}
33718  
33719	PointsMaterial.prototype = Object.create( Material.prototype );
33720	PointsMaterial.prototype.constructor = PointsMaterial;
33721  
33722	PointsMaterial.prototype.isPointsMaterial = true;
33723  
33724	PointsMaterial.prototype.copy = function ( source ) {
33725  
33726		Material.prototype.copy.call( this, source );
33727  
33728		this.color.copy( source.color );
33729  
33730		this.map = source.map;
33731  
33732		this.size = source.size;
33733		this.sizeAttenuation = source.sizeAttenuation;
33734  
33735		this.morphTargets = source.morphTargets;
33736  
33737		return this;
33738  
33739	};
33740  
33741	/**
33742	 * @author alteredq / http://alteredqualia.com/
33743	 */
33744  
33745	function Points( geometry, material ) {
33746  
33747		Object3D.call( this );
33748  
33749		this.type = 'Points';
33750  
33751		this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
33752		this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
33753  
33754	}
33755  
33756	Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
33757  
33758		constructor: Points,
33759  
33760		isPoints: true,
33761  
33762		raycast: ( function () {
33763  
33764			var inverseMatrix = new Matrix4();
33765			var ray = new Ray();
33766			var sphere = new Sphere();
33767  
33768			return function raycast( raycaster, intersects ) {
33769  
33770				var object = this;
33771				var geometry = this.geometry;
33772				var matrixWorld = this.matrixWorld;
33773				var threshold = raycaster.params.Points.threshold;
33774  
33775				// Checking boundingSphere distance to ray
33776  
33777				if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
33778  
33779				sphere.copy( geometry.boundingSphere );
33780				sphere.applyMatrix4( matrixWorld );
33781				sphere.radius += threshold;
33782  
33783				if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
33784  
33785				//
33786  
33787				inverseMatrix.getInverse( matrixWorld );
33788				ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
33789  
33790				var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
33791				var localThresholdSq = localThreshold * localThreshold;
33792				var position = new Vector3();
33793				var intersectPoint = new Vector3();
33794  
33795				function testPoint( point, index ) {
33796  
33797					var rayPointDistanceSq = ray.distanceSqToPoint( point );
33798  
33799					if ( rayPointDistanceSq < localThresholdSq ) {
33800  
33801						ray.closestPointToPoint( point, intersectPoint );
33802						intersectPoint.applyMatrix4( matrixWorld );
33803  
33804						var distance = raycaster.ray.origin.distanceTo( intersectPoint );
33805  
33806						if ( distance < raycaster.near || distance > raycaster.far ) return;
33807  
33808						intersects.push( {
33809  
33810							distance: distance,
33811							distanceToRay: Math.sqrt( rayPointDistanceSq ),
33812							point: intersectPoint.clone(),
33813							index: index,
33814							face: null,
33815							object: object
33816  
33817						} );
33818  
33819					}
33820  
33821				}
33822  
33823				if ( geometry.isBufferGeometry ) {
33824  
33825					var index = geometry.index;
33826					var attributes = geometry.attributes;
33827					var positions = attributes.position.array;
33828  
33829					if ( index !== null ) {
33830  
33831						var indices = index.array;
33832  
33833						for ( var i = 0, il = indices.length; i < il; i ++ ) {
33834  
33835							var a = indices[ i ];
33836  
33837							position.fromArray( positions, a * 3 );
33838  
33839							testPoint( position, a );
33840  
33841						}
33842  
33843					} else {
33844  
33845						for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
33846  
33847							position.fromArray( positions, i * 3 );
33848  
33849							testPoint( position, i );
33850  
33851						}
33852  
33853					}
33854  
33855				} else {
33856  
33857					var vertices = geometry.vertices;
33858  
33859					for ( var i = 0, l = vertices.length; i < l; i ++ ) {
33860  
33861						testPoint( vertices[ i ], i );
33862  
33863					}
33864  
33865				}
33866  
33867			};
33868  
33869		}() ),
33870  
33871		clone: function () {
33872  
33873			return new this.constructor( this.geometry, this.material ).copy( this );
33874  
33875		}
33876  
33877	} );
33878  
33879	/**
33880	 * @author mrdoob / http://mrdoob.com/
33881	 */
33882  
33883	function Group() {
33884  
33885		Object3D.call( this );
33886  
33887		this.type = 'Group';
33888  
33889	}
33890  
33891	Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
33892  
33893		constructor: Group,
33894  
33895		isGroup: true
33896  
33897	} );
33898  
33899	/**
33900	 * @author mrdoob / http://mrdoob.com/
33901	 */
33902  
33903	function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
33904  
33905		Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
33906  
33907		this.generateMipmaps = false;
vendor: 36,999 bytes, lines 33908-35504
33908  
33909	}
33910  
33911	VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
33912  
33913		constructor: VideoTexture,
33914  
33915		isVideoTexture: true,
33916  
33917		update: function () {
33918  
33919			var video = this.image;
33920  
33921			if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
33922  
33923				this.needsUpdate = true;
33924  
33925			}
33926  
33927		}
33928  
33929	} );
33930  
33931	/**
33932	 * @author alteredq / http://alteredqualia.com/
33933	 */
33934  
33935	function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
33936  
33937		Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
33938  
33939		this.image = { width: width, height: height };
33940		this.mipmaps = mipmaps;
33941  
33942		// no flipping for cube textures
33943		// (also flipping doesn't work for compressed textures )
33944  
33945		this.flipY = false;
33946  
33947		// can't generate mipmaps for compressed textures
33948		// mips must be embedded in DDS files
33949  
33950		this.generateMipmaps = false;
33951  
33952	}
33953  
33954	CompressedTexture.prototype = Object.create( Texture.prototype );
33955	CompressedTexture.prototype.constructor = CompressedTexture;
33956  
33957	CompressedTexture.prototype.isCompressedTexture = true;
33958  
33959	/**
33960	 * @author Matt DesLauriers / @mattdesl
33961	 * @author atix / arthursilber.de
33962	 */
33963  
33964	function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
33965  
33966		format = format !== undefined ? format : DepthFormat;
33967  
33968		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
33969  
33970			throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
33971  
33972		}
33973  
33974		if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
33975		if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
33976  
33977		Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
33978  
33979		this.image = { width: width, height: height };
33980  
33981		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
33982		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
33983  
33984		this.flipY = false;
33985		this.generateMipmaps	= false;
33986  
33987	}
33988  
33989	DepthTexture.prototype = Object.create( Texture.prototype );
33990	DepthTexture.prototype.constructor = DepthTexture;
33991	DepthTexture.prototype.isDepthTexture = true;
33992  
33993	/**
33994	 * @author mrdoob / http://mrdoob.com/
33995	 * @author Mugen87 / https://github.com/Mugen87
33996	 */
33997  
33998	function WireframeGeometry( geometry ) {
33999  
34000		BufferGeometry.call( this );
34001  
34002		this.type = 'WireframeGeometry';
34003  
34004		// buffer
34005  
34006		var vertices = [];
34007  
34008		// helper variables
34009  
34010		var i, j, l, o, ol;
34011		var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
34012		var key, keys = [ 'a', 'b', 'c' ];
34013		var vertex;
34014  
34015		// different logic for Geometry and BufferGeometry
34016  
34017		if ( geometry && geometry.isGeometry ) {
34018  
34019			// create a data structure that contains all edges without duplicates
34020  
34021			var faces = geometry.faces;
34022  
34023			for ( i = 0, l = faces.length; i < l; i ++ ) {
34024  
34025				var face = faces[ i ];
34026  
34027				for ( j = 0; j < 3; j ++ ) {
34028  
34029					edge1 = face[ keys[ j ] ];
34030					edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
34031					edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
34032					edge[ 1 ] = Math.max( edge1, edge2 );
34033  
34034					key = edge[ 0 ] + ',' + edge[ 1 ];
34035  
34036					if ( edges[ key ] === undefined ) {
34037  
34038						edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
34039  
34040					}
34041  
34042				}
34043  
34044			}
34045  
34046			// generate vertices
34047  
34048			for ( key in edges ) {
34049  
34050				e = edges[ key ];
34051  
34052				vertex = geometry.vertices[ e.index1 ];
34053				vertices.push( vertex.x, vertex.y, vertex.z );
34054  
34055				vertex = geometry.vertices[ e.index2 ];
34056				vertices.push( vertex.x, vertex.y, vertex.z );
34057  
34058			}
34059  
34060		} else if ( geometry && geometry.isBufferGeometry ) {
34061  
34062			var position, indices, groups;
34063			var group, start, count;
34064			var index1, index2;
34065  
34066			vertex = new Vector3();
34067  
34068			if ( geometry.index !== null ) {
34069  
34070				// indexed BufferGeometry
34071  
34072				position = geometry.attributes.position;
34073				indices = geometry.index;
34074				groups = geometry.groups;
34075  
34076				if ( groups.length === 0 ) {
34077  
34078					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
34079  
34080				}
34081  
34082				// create a data structure that contains all eges without duplicates
34083  
34084				for ( o = 0, ol = groups.length; o < ol; ++ o ) {
34085  
34086					group = groups[ o ];
34087  
34088					start = group.start;
34089					count = group.count;
34090  
34091					for ( i = start, l = ( start + count ); i < l; i += 3 ) {
34092  
34093						for ( j = 0; j < 3; j ++ ) {
34094  
34095							edge1 = indices.getX( i + j );
34096							edge2 = indices.getX( i + ( j + 1 ) % 3 );
34097							edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
34098							edge[ 1 ] = Math.max( edge1, edge2 );
34099  
34100							key = edge[ 0 ] + ',' + edge[ 1 ];
34101  
34102							if ( edges[ key ] === undefined ) {
34103  
34104								edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
34105  
34106							}
34107  
34108						}
34109  
34110					}
34111  
34112				}
34113  
34114				// generate vertices
34115  
34116				for ( key in edges ) {
34117  
34118					e = edges[ key ];
34119  
34120					vertex.fromBufferAttribute( position, e.index1 );
34121					vertices.push( vertex.x, vertex.y, vertex.z );
34122  
34123					vertex.fromBufferAttribute( position, e.index2 );
34124					vertices.push( vertex.x, vertex.y, vertex.z );
34125  
34126				}
34127  
34128			} else {
34129  
34130				// non-indexed BufferGeometry
34131  
34132				position = geometry.attributes.position;
34133  
34134				for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
34135  
34136					for ( j = 0; j < 3; j ++ ) {
34137  
34138						// three edges per triangle, an edge is represented as (index1, index2)
34139						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
34140  
34141						index1 = 3 * i + j;
34142						vertex.fromBufferAttribute( position, index1 );
34143						vertices.push( vertex.x, vertex.y, vertex.z );
34144  
34145						index2 = 3 * i + ( ( j + 1 ) % 3 );
34146						vertex.fromBufferAttribute( position, index2 );
34147						vertices.push( vertex.x, vertex.y, vertex.z );
34148  
34149					}
34150  
34151				}
34152  
34153			}
34154  
34155		}
34156  
34157		// build geometry
34158  
34159		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
34160  
34161	}
34162  
34163	WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
34164	WireframeGeometry.prototype.constructor = WireframeGeometry;
34165  
34166	/**
34167	 * @author zz85 / https://github.com/zz85
34168	 * @author Mugen87 / https://github.com/Mugen87
34169	 *
34170	 * Parametric Surfaces Geometry
34171	 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
34172	 */
34173  
34174	// ParametricGeometry
34175  
34176	function ParametricGeometry( func, slices, stacks ) {
34177  
34178		Geometry.call( this );
34179  
34180		this.type = 'ParametricGeometry';
34181  
34182		this.parameters = {
34183			func: func,
34184			slices: slices,
34185			stacks: stacks
34186		};
34187  
34188		this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
34189		this.mergeVertices();
34190  
34191	}
34192  
34193	ParametricGeometry.prototype = Object.create( Geometry.prototype );
34194	ParametricGeometry.prototype.constructor = ParametricGeometry;
34195  
34196	// ParametricBufferGeometry
34197  
34198	function ParametricBufferGeometry( func, slices, stacks ) {
34199  
34200		BufferGeometry.call( this );
34201  
34202		this.type = 'ParametricBufferGeometry';
34203  
34204		this.parameters = {
34205			func: func,
34206			slices: slices,
34207			stacks: stacks
34208		};
34209  
34210		// buffers
34211  
34212		var indices = [];
34213		var vertices = [];
34214		var normals = [];
34215		var uvs = [];
34216  
34217		var EPS = 0.00001;
34218  
34219		var normal = new Vector3();
34220  
34221		var p0 = new Vector3(), p1 = new Vector3();
34222		var pu = new Vector3(), pv = new Vector3();
34223  
34224		var i, j;
34225  
34226		if ( func.length < 3 ) {
34227  
34228			console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
34229  
34230		}
34231  
34232		// generate vertices, normals and uvs
34233  
34234		var sliceCount = slices + 1;
34235  
34236		for ( i = 0; i <= stacks; i ++ ) {
34237  
34238			var v = i / stacks;
34239  
34240			for ( j = 0; j <= slices; j ++ ) {
34241  
34242				var u = j / slices;
34243  
34244				// vertex
34245  
34246				func( u, v, p0 );
34247				vertices.push( p0.x, p0.y, p0.z );
34248  
34249				// normal
34250  
34251				// approximate tangent vectors via finite differences
34252  
34253				if ( u - EPS >= 0 ) {
34254  
34255					func( u - EPS, v, p1 );
34256					pu.subVectors( p0, p1 );
34257  
34258				} else {
34259  
34260					func( u + EPS, v, p1 );
34261					pu.subVectors( p1, p0 );
34262  
34263				}
34264  
34265				if ( v - EPS >= 0 ) {
34266  
34267					func( u, v - EPS, p1 );
34268					pv.subVectors( p0, p1 );
34269  
34270				} else {
34271  
34272					func( u, v + EPS, p1 );
34273					pv.subVectors( p1, p0 );
34274  
34275				}
34276  
34277				// cross product of tangent vectors returns surface normal
34278  
34279				normal.crossVectors( pu, pv ).normalize();
34280				normals.push( normal.x, normal.y, normal.z );
34281  
34282				// uv
34283  
34284				uvs.push( u, v );
34285  
34286			}
34287  
34288		}
34289  
34290		// generate indices
34291  
34292		for ( i = 0; i < stacks; i ++ ) {
34293  
34294			for ( j = 0; j < slices; j ++ ) {
34295  
34296				var a = i * sliceCount + j;
34297				var b = i * sliceCount + j + 1;
34298				var c = ( i + 1 ) * sliceCount + j + 1;
34299				var d = ( i + 1 ) * sliceCount + j;
34300  
34301				// faces one and two
34302  
34303				indices.push( a, b, d );
34304				indices.push( b, c, d );
34305  
34306			}
34307  
34308		}
34309  
34310		// build geometry
34311  
34312		this.setIndex( indices );
34313		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
34314		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
34315		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
34316  
34317	}
34318  
34319	ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
34320	ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
34321  
34322	/**
34323	 * @author clockworkgeek / https://github.com/clockworkgeek
34324	 * @author timothypratley / https://github.com/timothypratley
34325	 * @author WestLangley / http://github.com/WestLangley
34326	 * @author Mugen87 / https://github.com/Mugen87
34327	 */
34328  
34329	// PolyhedronGeometry
34330  
34331	function PolyhedronGeometry( vertices, indices, radius, detail ) {
34332  
34333		Geometry.call( this );
34334  
34335		this.type = 'PolyhedronGeometry';
34336  
34337		this.parameters = {
34338			vertices: vertices,
34339			indices: indices,
34340			radius: radius,
34341			detail: detail
34342		};
34343  
34344		this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
34345		this.mergeVertices();
34346  
34347	}
34348  
34349	PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
34350	PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
34351  
34352	// PolyhedronBufferGeometry
34353  
34354	function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
34355  
34356		BufferGeometry.call( this );
34357  
34358		this.type = 'PolyhedronBufferGeometry';
34359  
34360		this.parameters = {
34361			vertices: vertices,
34362			indices: indices,
34363			radius: radius,
34364			detail: detail
34365		};
34366  
34367		radius = radius || 1;
34368		detail = detail || 0;
34369  
34370		// default buffer data
34371  
34372		var vertexBuffer = [];
34373		var uvBuffer = [];
34374  
34375		// the subdivision creates the vertex buffer data
34376  
34377		subdivide( detail );
34378  
34379		// all vertices should lie on a conceptual sphere with a given radius
34380  
34381		appplyRadius( radius );
34382  
34383		// finally, create the uv data
34384  
34385		generateUVs();
34386  
34387		// build non-indexed geometry
34388  
34389		this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
34390		this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
34391		this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
34392  
34393		if ( detail === 0 ) {
34394  
34395			this.computeVertexNormals(); // flat normals
34396  
34397		} else {
34398  
34399			this.normalizeNormals(); // smooth normals
34400  
34401		}
34402  
34403		// helper functions
34404  
34405		function subdivide( detail ) {
34406  
34407			var a = new Vector3();
34408			var b = new Vector3();
34409			var c = new Vector3();
34410  
34411			// iterate over all faces and apply a subdivison with the given detail value
34412  
34413			for ( var i = 0; i < indices.length; i += 3 ) {
34414  
34415				// get the vertices of the face
34416  
34417				getVertexByIndex( indices[ i + 0 ], a );
34418				getVertexByIndex( indices[ i + 1 ], b );
34419				getVertexByIndex( indices[ i + 2 ], c );
34420  
34421				// perform subdivision
34422  
34423				subdivideFace( a, b, c, detail );
34424  
34425			}
34426  
34427		}
34428  
34429		function subdivideFace( a, b, c, detail ) {
34430  
34431			var cols = Math.pow( 2, detail );
34432  
34433			// we use this multidimensional array as a data structure for creating the subdivision
34434  
34435			var v = [];
34436  
34437			var i, j;
34438  
34439			// construct all of the vertices for this subdivision
34440  
34441			for ( i = 0; i <= cols; i ++ ) {
34442  
34443				v[ i ] = [];
34444  
34445				var aj = a.clone().lerp( c, i / cols );
34446				var bj = b.clone().lerp( c, i / cols );
34447  
34448				var rows = cols - i;
34449  
34450				for ( j = 0; j <= rows; j ++ ) {
34451  
34452					if ( j === 0 && i === cols ) {
34453  
34454						v[ i ][ j ] = aj;
34455  
34456					} else {
34457  
34458						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
34459  
34460					}
34461  
34462				}
34463  
34464			}
34465  
34466			// construct all of the faces
34467  
34468			for ( i = 0; i < cols; i ++ ) {
34469  
34470				for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
34471  
34472					var k = Math.floor( j / 2 );
34473  
34474					if ( j % 2 === 0 ) {
34475  
34476						pushVertex( v[ i ][ k + 1 ] );
34477						pushVertex( v[ i + 1 ][ k ] );
34478						pushVertex( v[ i ][ k ] );
34479  
34480					} else {
34481  
34482						pushVertex( v[ i ][ k + 1 ] );
34483						pushVertex( v[ i + 1 ][ k + 1 ] );
34484						pushVertex( v[ i + 1 ][ k ] );
34485  
34486					}
34487  
34488				}
34489  
34490			}
34491  
34492		}
34493  
34494		function appplyRadius( radius ) {
34495  
34496			var vertex = new Vector3();
34497  
34498			// iterate over the entire buffer and apply the radius to each vertex
34499  
34500			for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
34501  
34502				vertex.x = vertexBuffer[ i + 0 ];
34503				vertex.y = vertexBuffer[ i + 1 ];
34504				vertex.z = vertexBuffer[ i + 2 ];
34505  
34506				vertex.normalize().multiplyScalar( radius );
34507  
34508				vertexBuffer[ i + 0 ] = vertex.x;
34509				vertexBuffer[ i + 1 ] = vertex.y;
34510				vertexBuffer[ i + 2 ] = vertex.z;
34511  
34512			}
34513  
34514		}
34515  
34516		function generateUVs() {
34517  
34518			var vertex = new Vector3();
34519  
34520			for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
34521  
34522				vertex.x = vertexBuffer[ i + 0 ];
34523				vertex.y = vertexBuffer[ i + 1 ];
34524				vertex.z = vertexBuffer[ i + 2 ];
34525  
34526				var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
34527				var v = inclination( vertex ) / Math.PI + 0.5;
34528				uvBuffer.push( u, 1 - v );
34529  
34530			}
34531  
34532			correctUVs();
34533  
34534			correctSeam();
34535  
34536		}
34537  
34538		function correctSeam() {
34539  
34540			// handle case when face straddles the seam, see #3269
34541  
34542			for ( var i = 0; i < uvBuffer.length; i += 6 ) {
34543  
34544				// uv data of a single face
34545  
34546				var x0 = uvBuffer[ i + 0 ];
34547				var x1 = uvBuffer[ i + 2 ];
34548				var x2 = uvBuffer[ i + 4 ];
34549  
34550				var max = Math.max( x0, x1, x2 );
34551				var min = Math.min( x0, x1, x2 );
34552  
34553				// 0.9 is somewhat arbitrary
34554  
34555				if ( max > 0.9 && min < 0.1 ) {
34556  
34557					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
34558					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
34559					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
34560  
34561				}
34562  
34563			}
34564  
34565		}
34566  
34567		function pushVertex( vertex ) {
34568  
34569			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
34570  
34571		}
34572  
34573		function getVertexByIndex( index, vertex ) {
34574  
34575			var stride = index * 3;
34576  
34577			vertex.x = vertices[ stride + 0 ];
34578			vertex.y = vertices[ stride + 1 ];
34579			vertex.z = vertices[ stride + 2 ];
34580  
34581		}
34582  
34583		function correctUVs() {
34584  
34585			var a = new Vector3();
34586			var b = new Vector3();
34587			var c = new Vector3();
34588  
34589			var centroid = new Vector3();
34590  
34591			var uvA = new Vector2();
34592			var uvB = new Vector2();
34593			var uvC = new Vector2();
34594  
34595			for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
34596  
34597				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
34598				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
34599				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
34600  
34601				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
34602				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
34603				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
34604  
34605				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
34606  
34607				var azi = azimuth( centroid );
34608  
34609				correctUV( uvA, j + 0, a, azi );
34610				correctUV( uvB, j + 2, b, azi );
34611				correctUV( uvC, j + 4, c, azi );
34612  
34613			}
34614  
34615		}
34616  
34617		function correctUV( uv, stride, vector, azimuth ) {
34618  
34619			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
34620  
34621				uvBuffer[ stride ] = uv.x - 1;
34622  
34623			}
34624  
34625			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
34626  
34627				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
34628  
34629			}
34630  
34631		}
34632  
34633		// Angle around the Y axis, counter-clockwise when looking from above.
34634  
34635		function azimuth( vector ) {
34636  
34637			return Math.atan2( vector.z, - vector.x );
34638  
34639		}
34640  
34641  
34642		// Angle above the XZ plane.
34643  
34644		function inclination( vector ) {
34645  
34646			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
34647  
34648		}
34649  
34650	}
34651  
34652	PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
34653	PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
34654  
34655	/**
34656	 * @author timothypratley / https://github.com/timothypratley
34657	 * @author Mugen87 / https://github.com/Mugen87
34658	 */
34659  
34660	// TetrahedronGeometry
34661  
34662	function TetrahedronGeometry( radius, detail ) {
34663  
34664		Geometry.call( this );
34665  
34666		this.type = 'TetrahedronGeometry';
34667  
34668		this.parameters = {
34669			radius: radius,
34670			detail: detail
34671		};
34672  
34673		this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
34674		this.mergeVertices();
34675  
34676	}
34677  
34678	TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
34679	TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
34680  
34681	// TetrahedronBufferGeometry
34682  
34683	function TetrahedronBufferGeometry( radius, detail ) {
34684  
34685		var vertices = [
34686			1, 1, 1, 	- 1, - 1, 1, 	- 1, 1, - 1, 	1, - 1, - 1
34687		];
34688  
34689		var indices = [
34690			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
34691		];
34692  
34693		PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
34694  
34695		this.type = 'TetrahedronBufferGeometry';
34696  
34697		this.parameters = {
34698			radius: radius,
34699			detail: detail
34700		};
34701  
34702	}
34703  
34704	TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
34705	TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
34706  
34707	/**
34708	 * @author timothypratley / https://github.com/timothypratley
34709	 * @author Mugen87 / https://github.com/Mugen87
34710	 */
34711  
34712	// OctahedronGeometry
34713  
34714	function OctahedronGeometry( radius, detail ) {
34715  
34716		Geometry.call( this );
34717  
34718		this.type = 'OctahedronGeometry';
34719  
34720		this.parameters = {
34721			radius: radius,
34722			detail: detail
34723		};
34724  
34725		this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
34726		this.mergeVertices();
34727  
34728	}
34729  
34730	OctahedronGeometry.prototype = Object.create( Geometry.prototype );
34731	OctahedronGeometry.prototype.constructor = OctahedronGeometry;
34732  
34733	// OctahedronBufferGeometry
34734  
34735	function OctahedronBufferGeometry( radius, detail ) {
34736  
34737		var vertices = [
34738			1, 0, 0, 	- 1, 0, 0,	0, 1, 0,
34739			0, - 1, 0, 	0, 0, 1,	0, 0, - 1
34740		];
34741  
34742		var indices = [
34743			0, 2, 4,	0, 4, 3,	0, 3, 5,
34744			0, 5, 2,	1, 2, 5,	1, 5, 3,
34745			1, 3, 4,	1, 4, 2
34746		];
34747  
34748		PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
34749  
34750		this.type = 'OctahedronBufferGeometry';
34751  
34752		this.parameters = {
34753			radius: radius,
34754			detail: detail
34755		};
34756  
34757	}
34758  
34759	OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
34760	OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
34761  
34762	/**
34763	 * @author timothypratley / https://github.com/timothypratley
34764	 * @author Mugen87 / https://github.com/Mugen87
34765	 */
34766  
34767	// IcosahedronGeometry
34768  
34769	function IcosahedronGeometry( radius, detail ) {
34770  
34771		Geometry.call( this );
34772  
34773		this.type = 'IcosahedronGeometry';
34774  
34775		this.parameters = {
34776			radius: radius,
34777			detail: detail
34778		};
34779  
34780		this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
34781		this.mergeVertices();
34782  
34783	}
34784  
34785	IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
34786	IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
34787  
34788	// IcosahedronBufferGeometry
34789  
34790	function IcosahedronBufferGeometry( radius, detail ) {
34791  
34792		var t = ( 1 + Math.sqrt( 5 ) ) / 2;
34793  
34794		var vertices = [
34795			- 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
34796			 0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
34797			 t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
34798		];
34799  
34800		var indices = [
34801			 0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
34802			 1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
34803			 3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
34804			 4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
34805		];
34806  
34807		PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
34808  
34809		this.type = 'IcosahedronBufferGeometry';
34810  
34811		this.parameters = {
34812			radius: radius,
34813			detail: detail
34814		};
34815  
34816	}
34817  
34818	IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
34819	IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
34820  
34821	/**
34822	 * @author Abe Pazos / https://hamoid.com
34823	 * @author Mugen87 / https://github.com/Mugen87
34824	 */
34825  
34826	// DodecahedronGeometry
34827  
34828	function DodecahedronGeometry( radius, detail ) {
34829  
34830		Geometry.call( this );
34831  
34832		this.type = 'DodecahedronGeometry';
34833  
34834		this.parameters = {
34835			radius: radius,
34836			detail: detail
34837		};
34838  
34839		this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
34840		this.mergeVertices();
34841  
34842	}
34843  
34844	DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
34845	DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
34846  
34847	// DodecahedronBufferGeometry
34848  
34849	function DodecahedronBufferGeometry( radius, detail ) {
34850  
34851		var t = ( 1 + Math.sqrt( 5 ) ) / 2;
34852		var r = 1 / t;
34853  
34854		var vertices = [
34855  
34856			// (±1, ±1, ±1)
34857			- 1, - 1, - 1,	- 1, - 1, 1,
34858			- 1, 1, - 1, - 1, 1, 1,
34859			1, - 1, - 1, 1, - 1, 1,
34860			1, 1, - 1, 1, 1, 1,
34861  
34862			// (0, ±1/φ, ±φ)
34863			 0, - r, - t, 0, - r, t,
34864			 0, r, - t, 0, r, t,
34865  
34866			// (±1/φ, ±φ, 0)
34867			- r, - t, 0, - r, t, 0,
34868			 r, - t, 0, r, t, 0,
34869  
34870			// (±φ, 0, ±1/φ)
34871			- t, 0, - r, t, 0, - r,
34872			- t, 0, r, t, 0, r
34873		];
34874  
34875		var indices = [
34876			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
34877			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
34878			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
34879			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
34880			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
34881			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
34882			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
34883			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
34884			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
34885			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
34886			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
34887			1, 12, 14, 	1, 14, 5, 	1, 5, 9
34888		];
34889  
34890		PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
34891  
34892		this.type = 'DodecahedronBufferGeometry';
34893  
34894		this.parameters = {
34895			radius: radius,
34896			detail: detail
34897		};
34898  
34899	}
34900  
34901	DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
34902	DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
34903  
34904	/**
34905	 * @author oosmoxiecode / https://github.com/oosmoxiecode
34906	 * @author WestLangley / https://github.com/WestLangley
34907	 * @author zz85 / https://github.com/zz85
34908	 * @author miningold / https://github.com/miningold
34909	 * @author jonobr1 / https://github.com/jonobr1
34910	 * @author Mugen87 / https://github.com/Mugen87
34911	 *
34912	 */
34913  
34914	// TubeGeometry
34915  
34916	function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
34917  
34918		Geometry.call( this );
34919  
34920		this.type = 'TubeGeometry';
34921  
34922		this.parameters = {
34923			path: path,
34924			tubularSegments: tubularSegments,
34925			radius: radius,
34926			radialSegments: radialSegments,
34927			closed: closed
34928		};
34929  
34930		if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
34931  
34932		var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
34933  
34934		// expose internals
34935  
34936		this.tangents = bufferGeometry.tangents;
34937		this.normals = bufferGeometry.normals;
34938		this.binormals = bufferGeometry.binormals;
34939  
34940		// create geometry
34941  
34942		this.fromBufferGeometry( bufferGeometry );
34943		this.mergeVertices();
34944  
34945	}
34946  
34947	TubeGeometry.prototype = Object.create( Geometry.prototype );
34948	TubeGeometry.prototype.constructor = TubeGeometry;
34949  
34950	// TubeBufferGeometry
34951  
34952	function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
34953  
34954		BufferGeometry.call( this );
34955  
34956		this.type = 'TubeBufferGeometry';
34957  
34958		this.parameters = {
34959			path: path,
34960			tubularSegments: tubularSegments,
34961			radius: radius,
34962			radialSegments: radialSegments,
34963			closed: closed
34964		};
34965  
34966		tubularSegments = tubularSegments || 64;
34967		radius = radius || 1;
34968		radialSegments = radialSegments || 8;
34969		closed = closed || false;
34970  
34971		var frames = path.computeFrenetFrames( tubularSegments, closed );
34972  
34973		// expose internals
34974  
34975		this.tangents = frames.tangents;
34976		this.normals = frames.normals;
34977		this.binormals = frames.binormals;
34978  
34979		// helper variables
34980  
34981		var vertex = new Vector3();
34982		var normal = new Vector3();
34983		var uv = new Vector2();
34984		var P = new Vector3();
34985  
34986		var i, j;
34987  
34988		// buffer
34989  
34990		var vertices = [];
34991		var normals = [];
34992		var uvs = [];
34993		var indices = [];
34994  
34995		// create buffer data
34996  
34997		generateBufferData();
34998  
34999		// build geometry
35000  
35001		this.setIndex( indices );
35002		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35003		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35004		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35005  
35006		// functions
35007  
35008		function generateBufferData() {
35009  
35010			for ( i = 0; i < tubularSegments; i ++ ) {
35011  
35012				generateSegment( i );
35013  
35014			}
35015  
35016			// if the geometry is not closed, generate the last row of vertices and normals
35017			// at the regular position on the given path
35018			//
35019			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
35020  
35021			generateSegment( ( closed === false ) ? tubularSegments : 0 );
35022  
35023			// uvs are generated in a separate function.
35024			// this makes it easy compute correct values for closed geometries
35025  
35026			generateUVs();
35027  
35028			// finally create faces
35029  
35030			generateIndices();
35031  
35032		}
35033  
35034		function generateSegment( i ) {
35035  
35036			// we use getPointAt to sample evenly distributed points from the given path
35037  
35038			P = path.getPointAt( i / tubularSegments, P );
35039  
35040			// retrieve corresponding normal and binormal
35041  
35042			var N = frames.normals[ i ];
35043			var B = frames.binormals[ i ];
35044  
35045			// generate normals and vertices for the current segment
35046  
35047			for ( j = 0; j <= radialSegments; j ++ ) {
35048  
35049				var v = j / radialSegments * Math.PI * 2;
35050  
35051				var sin = Math.sin( v );
35052				var cos = - Math.cos( v );
35053  
35054				// normal
35055  
35056				normal.x = ( cos * N.x + sin * B.x );
35057				normal.y = ( cos * N.y + sin * B.y );
35058				normal.z = ( cos * N.z + sin * B.z );
35059				normal.normalize();
35060  
35061				normals.push( normal.x, normal.y, normal.z );
35062  
35063				// vertex
35064  
35065				vertex.x = P.x + radius * normal.x;
35066				vertex.y = P.y + radius * normal.y;
35067				vertex.z = P.z + radius * normal.z;
35068  
35069				vertices.push( vertex.x, vertex.y, vertex.z );
35070  
35071			}
35072  
35073		}
35074  
35075		function generateIndices() {
35076  
35077			for ( j = 1; j <= tubularSegments; j ++ ) {
35078  
35079				for ( i = 1; i <= radialSegments; i ++ ) {
35080  
35081					var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
35082					var b = ( radialSegments + 1 ) * j + ( i - 1 );
35083					var c = ( radialSegments + 1 ) * j + i;
35084					var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
35085  
35086					// faces
35087  
35088					indices.push( a, b, d );
35089					indices.push( b, c, d );
35090  
35091				}
35092  
35093			}
35094  
35095		}
35096  
35097		function generateUVs() {
35098  
35099			for ( i = 0; i <= tubularSegments; i ++ ) {
35100  
35101				for ( j = 0; j <= radialSegments; j ++ ) {
35102  
35103					uv.x = i / tubularSegments;
35104					uv.y = j / radialSegments;
35105  
35106					uvs.push( uv.x, uv.y );
35107  
35108				}
35109  
35110			}
35111  
35112		}
35113  
35114	}
35115  
35116	TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
35117	TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
35118  
35119	/**
35120	 * @author oosmoxiecode
35121	 * @author Mugen87 / https://github.com/Mugen87
35122	 *
35123	 * based on http://www.blackpawn.com/texts/pqtorus/
35124	 */
35125  
35126	// TorusKnotGeometry
35127  
35128	function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
35129  
35130		Geometry.call( this );
35131  
35132		this.type = 'TorusKnotGeometry';
35133  
35134		this.parameters = {
35135			radius: radius,
35136			tube: tube,
35137			tubularSegments: tubularSegments,
35138			radialSegments: radialSegments,
35139			p: p,
35140			q: q
35141		};
35142  
35143		if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
35144  
35145		this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
35146		this.mergeVertices();
35147  
35148	}
35149  
35150	TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
35151	TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
35152  
35153	// TorusKnotBufferGeometry
35154  
35155	function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
35156  
35157		BufferGeometry.call( this );
35158  
35159		this.type = 'TorusKnotBufferGeometry';
35160  
35161		this.parameters = {
35162			radius: radius,
35163			tube: tube,
35164			tubularSegments: tubularSegments,
35165			radialSegments: radialSegments,
35166			p: p,
35167			q: q
35168		};
35169  
35170		radius = radius || 1;
35171		tube = tube || 0.4;
35172		tubularSegments = Math.floor( tubularSegments ) || 64;
35173		radialSegments = Math.floor( radialSegments ) || 8;
35174		p = p || 2;
35175		q = q || 3;
35176  
35177		// buffers
35178  
35179		var indices = [];
35180		var vertices = [];
35181		var normals = [];
35182		var uvs = [];
35183  
35184		// helper variables
35185  
35186		var i, j;
35187  
35188		var vertex = new Vector3();
35189		var normal = new Vector3();
35190  
35191		var P1 = new Vector3();
35192		var P2 = new Vector3();
35193  
35194		var B = new Vector3();
35195		var T = new Vector3();
35196		var N = new Vector3();
35197  
35198		// generate vertices, normals and uvs
35199  
35200		for ( i = 0; i <= tubularSegments; ++ i ) {
35201  
35202			// the radian "u" is used to calculate the position on the torus curve of the current tubular segement
35203  
35204			var u = i / tubularSegments * p * Math.PI * 2;
35205  
35206			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
35207			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
35208  
35209			calculatePositionOnCurve( u, p, q, radius, P1 );
35210			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
35211  
35212			// calculate orthonormal basis
35213  
35214			T.subVectors( P2, P1 );
35215			N.addVectors( P2, P1 );
35216			B.crossVectors( T, N );
35217			N.crossVectors( B, T );
35218  
35219			// normalize B, N. T can be ignored, we don't use it
35220  
35221			B.normalize();
35222			N.normalize();
35223  
35224			for ( j = 0; j <= radialSegments; ++ j ) {
35225  
35226				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
35227				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
35228  
35229				var v = j / radialSegments * Math.PI * 2;
35230				var cx = - tube * Math.cos( v );
35231				var cy = tube * Math.sin( v );
35232  
35233				// now calculate the final vertex position.
35234				// first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
35235  
35236				vertex.x = P1.x + ( cx * N.x + cy * B.x );
35237				vertex.y = P1.y + ( cx * N.y + cy * B.y );
35238				vertex.z = P1.z + ( cx * N.z + cy * B.z );
35239  
35240				vertices.push( vertex.x, vertex.y, vertex.z );
35241  
35242				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
35243  
35244				normal.subVectors( vertex, P1 ).normalize();
35245  
35246				normals.push( normal.x, normal.y, normal.z );
35247  
35248				// uv
35249  
35250				uvs.push( i / tubularSegments );
35251				uvs.push( j / radialSegments );
35252  
35253			}
35254  
35255		}
35256  
35257		// generate indices
35258  
35259		for ( j = 1; j <= tubularSegments; j ++ ) {
35260  
35261			for ( i = 1; i <= radialSegments; i ++ ) {
35262  
35263				// indices
35264  
35265				var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
35266				var b = ( radialSegments + 1 ) * j + ( i - 1 );
35267				var c = ( radialSegments + 1 ) * j + i;
35268				var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
35269  
35270				// faces
35271  
35272				indices.push( a, b, d );
35273				indices.push( b, c, d );
35274  
35275			}
35276  
35277		}
35278  
35279		// build geometry
35280  
35281		this.setIndex( indices );
35282		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35283		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35284		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35285  
35286		// this function calculates the current position on the torus curve
35287  
35288		function calculatePositionOnCurve( u, p, q, radius, position ) {
35289  
35290			var cu = Math.cos( u );
35291			var su = Math.sin( u );
35292			var quOverP = q / p * u;
35293			var cs = Math.cos( quOverP );
35294  
35295			position.x = radius * ( 2 + cs ) * 0.5 * cu;
35296			position.y = radius * ( 2 + cs ) * su * 0.5;
35297			position.z = radius * Math.sin( quOverP ) * 0.5;
35298  
35299		}
35300  
35301	}
35302  
35303	TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
35304	TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
35305  
35306	/**
35307	 * @author oosmoxiecode
35308	 * @author mrdoob / http://mrdoob.com/
35309	 * @author Mugen87 / https://github.com/Mugen87
35310	 */
35311  
35312	// TorusGeometry
35313  
35314	function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
35315  
35316		Geometry.call( this );
35317  
35318		this.type = 'TorusGeometry';
35319  
35320		this.parameters = {
35321			radius: radius,
35322			tube: tube,
35323			radialSegments: radialSegments,
35324			tubularSegments: tubularSegments,
35325			arc: arc
35326		};
35327  
35328		this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
35329		this.mergeVertices();
35330  
35331	}
35332  
35333	TorusGeometry.prototype = Object.create( Geometry.prototype );
35334	TorusGeometry.prototype.constructor = TorusGeometry;
35335  
35336	// TorusBufferGeometry
35337  
35338	function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
35339  
35340		BufferGeometry.call( this );
35341  
35342		this.type = 'TorusBufferGeometry';
35343  
35344		this.parameters = {
35345			radius: radius,
35346			tube: tube,
35347			radialSegments: radialSegments,
35348			tubularSegments: tubularSegments,
35349			arc: arc
35350		};
35351  
35352		radius = radius || 1;
35353		tube = tube || 0.4;
35354		radialSegments = Math.floor( radialSegments ) || 8;
35355		tubularSegments = Math.floor( tubularSegments ) || 6;
35356		arc = arc || Math.PI * 2;
35357  
35358		// buffers
35359  
35360		var indices = [];
35361		var vertices = [];
35362		var normals = [];
35363		var uvs = [];
35364  
35365		// helper variables
35366  
35367		var center = new Vector3();
35368		var vertex = new Vector3();
35369		var normal = new Vector3();
35370  
35371		var j, i;
35372  
35373		// generate vertices, normals and uvs
35374  
35375		for ( j = 0; j <= radialSegments; j ++ ) {
35376  
35377			for ( i = 0; i <= tubularSegments; i ++ ) {
35378  
35379				var u = i / tubularSegments * arc;
35380				var v = j / radialSegments * Math.PI * 2;
35381  
35382				// vertex
35383  
35384				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
35385				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
35386				vertex.z = tube * Math.sin( v );
35387  
35388				vertices.push( vertex.x, vertex.y, vertex.z );
35389  
35390				// normal
35391  
35392				center.x = radius * Math.cos( u );
35393				center.y = radius * Math.sin( u );
35394				normal.subVectors( vertex, center ).normalize();
35395  
35396				normals.push( normal.x, normal.y, normal.z );
35397  
35398				// uv
35399  
35400				uvs.push( i / tubularSegments );
35401				uvs.push( j / radialSegments );
35402  
35403			}
35404  
35405		}
35406  
35407		// generate indices
35408  
35409		for ( j = 1; j <= radialSegments; j ++ ) {
35410  
35411			for ( i = 1; i <= tubularSegments; i ++ ) {
35412  
35413				// indices
35414  
35415				var a = ( tubularSegments + 1 ) * j + i - 1;
35416				var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
35417				var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
35418				var d = ( tubularSegments + 1 ) * j + i;
35419  
35420				// faces
35421  
35422				indices.push( a, b, d );
35423				indices.push( b, c, d );
35424  
35425			}
35426  
35427		}
35428  
35429		// build geometry
35430  
35431		this.setIndex( indices );
35432		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35433		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35434		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35435  
35436	}
35437  
35438	TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
35439	TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
35440  
35441	/**
35442	 * @author Mugen87 / https://github.com/Mugen87
35443	 * Port from https://github.com/mapbox/earcut (v2.1.2)
35444	 */
35445  
35446	var Earcut = {
35447  
35448		triangulate: function ( data, holeIndices, dim ) {
35449  
35450			dim = dim || 2;
35451  
35452			var hasHoles = holeIndices && holeIndices.length,
35453				outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,
35454				outerNode = linkedList( data, 0, outerLen, dim, true ),
35455				triangles = [];
35456  
35457			if ( ! outerNode ) return triangles;
35458  
35459			var minX, minY, maxX, maxY, x, y, invSize;
35460  
35461			if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
35462  
35463			// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
35464  
35465			if ( data.length > 80 * dim ) {
35466  
35467				minX = maxX = data[ 0 ];
35468				minY = maxY = data[ 1 ];
35469  
35470				for ( var i = dim; i < outerLen; i += dim ) {
35471  
35472					x = data[ i ];
35473					y = data[ i + 1 ];
35474					if ( x < minX ) minX = x;
35475					if ( y < minY ) minY = y;
35476					if ( x > maxX ) maxX = x;
35477					if ( y > maxY ) maxY = y;
35478  
35479				}
35480  
35481				// minX, minY and invSize are later used to transform coords into integers for z-order calculation
35482  
35483				invSize = Math.max( maxX - minX, maxY - minY );
35484				invSize = invSize !== 0 ? 1 / invSize : 0;
35485  
35486			}
35487  
35488			earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
35489  
35490			return triangles;
35491  
35492		}
35493  
35494	};
35495  
35496	// create a circular doubly linked list from polygon points in the specified winding order
35497  
35498	function linkedList( data, start, end, dim, clockwise ) {
35499  
35500		var i, last;
35501  
35502		if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
35503  
35504			for ( i = start; i < end;
vendor: 12,853 bytes, lines 35504-36132
35504 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
35505  
35506		} else {
35507  
35508			for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
35509  
35510		}
35511  
35512		if ( last && equals( last, last.next ) ) {
35513  
35514			removeNode( last );
35515			last = last.next;
35516  
35517		}
35518  
35519		return last;
35520  
35521	}
35522  
35523	// eliminate colinear or duplicate points
35524  
35525	function filterPoints( start, end ) {
35526  
35527		if ( ! start ) return start;
35528		if ( ! end ) end = start;
35529  
35530		var p = start, again;
35531  
35532		do {
35533  
35534			again = false;
35535  
35536			if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
35537  
35538				removeNode( p );
35539				p = end = p.prev;
35540				if ( p === p.next ) break;
35541				again = true;
35542  
35543			} else {
35544  
35545				p = p.next;
35546  
35547			}
35548  
35549		} while ( again || p !== end );
35550  
35551		return end;
35552  
35553	}
35554  
35555	// main ear slicing loop which triangulates a polygon (given as a linked list)
35556  
35557	function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
35558  
35559		if ( ! ear ) return;
35560  
35561		// interlink polygon nodes in z-order
35562  
35563		if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
35564  
35565		var stop = ear, prev, next;
35566  
35567		// iterate through ears, slicing them one by one
35568  
35569		while ( ear.prev !== ear.next ) {
35570  
35571			prev = ear.prev;
35572			next = ear.next;
35573  
35574			if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
35575  
35576				// cut off the triangle
35577				triangles.push( prev.i / dim );
35578				triangles.push( ear.i / dim );
35579				triangles.push( next.i / dim );
35580  
35581				removeNode( ear );
35582  
35583				// skipping the next vertice leads to less sliver triangles
35584				ear = next.next;
35585				stop = next.next;
35586  
35587				continue;
35588  
35589			}
35590  
35591			ear = next;
35592  
35593			// if we looped through the whole remaining polygon and can't find any more ears
35594  
35595			if ( ear === stop ) {
35596  
35597				// try filtering points and slicing again
35598  
35599				if ( ! pass ) {
35600  
35601					earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
35602  
35603					// if this didn't work, try curing all small self-intersections locally
35604  
35605				} else if ( pass === 1 ) {
35606  
35607					ear = cureLocalIntersections( ear, triangles, dim );
35608					earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
35609  
35610				// as a last resort, try splitting the remaining polygon into two
35611  
35612				} else if ( pass === 2 ) {
35613  
35614					splitEarcut( ear, triangles, dim, minX, minY, invSize );
35615  
35616				}
35617  
35618				break;
35619  
35620			}
35621  
35622		}
35623  
35624	}
35625  
35626	// check whether a polygon node forms a valid ear with adjacent nodes
35627  
35628	function isEar( ear ) {
35629  
35630		var a = ear.prev,
35631			b = ear,
35632			c = ear.next;
35633  
35634		if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
35635  
35636		// now make sure we don't have other points inside the potential ear
35637		var p = ear.next.next;
35638  
35639		while ( p !== ear.prev ) {
35640  
35641			if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) {
35642  
35643				return false;
35644  
35645			}
35646  
35647			p = p.next;
35648  
35649		}
35650  
35651		return true;
35652  
35653	}
35654  
35655	function isEarHashed( ear, minX, minY, invSize ) {
35656  
35657		var a = ear.prev,
35658			b = ear,
35659			c = ear.next;
35660  
35661		if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
35662  
35663		// triangle bbox; min & max are calculated like this for speed
35664  
35665		var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
35666			minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
35667			maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
35668			maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
35669  
35670		// z-order range for the current triangle bbox;
35671  
35672		var minZ = zOrder( minTX, minTY, minX, minY, invSize ),
35673			maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
35674  
35675		// first look for points inside the triangle in increasing z-order
35676  
35677		var p = ear.nextZ;
35678  
35679		while ( p && p.z <= maxZ ) {
35680  
35681			if ( p !== ear.prev && p !== ear.next &&
35682					pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
35683					area( p.prev, p, p.next ) >= 0 ) return false;
35684			p = p.nextZ;
35685  
35686		}
35687  
35688		// then look for points in decreasing z-order
35689  
35690		p = ear.prevZ;
35691  
35692		while ( p && p.z >= minZ ) {
35693  
35694			if ( p !== ear.prev && p !== ear.next &&
35695					pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
35696					area( p.prev, p, p.next ) >= 0 ) return false;
35697  
35698			p = p.prevZ;
35699  
35700		}
35701  
35702		return true;
35703  
35704	}
35705  
35706	// go through all polygon nodes and cure small local self-intersections
35707  
35708	function cureLocalIntersections( start, triangles, dim ) {
35709  
35710		var p = start;
35711  
35712		do {
35713  
35714			var a = p.prev, b = p.next.next;
35715  
35716			if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
35717  
35718				triangles.push( a.i / dim );
35719				triangles.push( p.i / dim );
35720				triangles.push( b.i / dim );
35721  
35722				// remove two nodes involved
35723  
35724				removeNode( p );
35725				removeNode( p.next );
35726  
35727				p = start = b;
35728  
35729			}
35730  
35731			p = p.next;
35732  
35733		} while ( p !== start );
35734  
35735		return p;
35736  
35737	}
35738  
35739	// try splitting polygon into two and triangulate them independently
35740  
35741	function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
35742  
35743		// look for a valid diagonal that divides the polygon into two
35744  
35745		var a = start;
35746  
35747		do {
35748  
35749			var b = a.next.next;
35750  
35751			while ( b !== a.prev ) {
35752  
35753				if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
35754  
35755					// split the polygon in two by the diagonal
35756  
35757					var c = splitPolygon( a, b );
35758  
35759					// filter colinear points around the cuts
35760  
35761					a = filterPoints( a, a.next );
35762					c = filterPoints( c, c.next );
35763  
35764					// run earcut on each half
35765  
35766					earcutLinked( a, triangles, dim, minX, minY, invSize );
35767					earcutLinked( c, triangles, dim, minX, minY, invSize );
35768					return;
35769  
35770				}
35771  
35772				b = b.next;
35773  
35774			}
35775  
35776			a = a.next;
35777  
35778		} while ( a !== start );
35779  
35780	}
35781  
35782	// link every hole into the outer loop, producing a single-ring polygon without holes
35783  
35784	function eliminateHoles( data, holeIndices, outerNode, dim ) {
35785  
35786		var queue = [], i, len, start, end, list;
35787  
35788		for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
35789  
35790			start = holeIndices[ i ] * dim;
35791			end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
35792			list = linkedList( data, start, end, dim, false );
35793			if ( list === list.next ) list.steiner = true;
35794			queue.push( getLeftmost( list ) );
35795  
35796		}
35797  
35798		queue.sort( compareX );
35799  
35800		// process holes from left to right
35801  
35802		for ( i = 0; i < queue.length; i ++ ) {
35803  
35804			eliminateHole( queue[ i ], outerNode );
35805			outerNode = filterPoints( outerNode, outerNode.next );
35806  
35807		}
35808  
35809		return outerNode;
35810  
35811	}
35812  
35813	function compareX( a, b ) {
35814  
35815		return a.x - b.x;
35816  
35817	}
35818  
35819	// find a bridge between vertices that connects hole with an outer ring and and link it
35820  
35821	function eliminateHole( hole, outerNode ) {
35822  
35823		outerNode = findHoleBridge( hole, outerNode );
35824  
35825		if ( outerNode ) {
35826  
35827			var b = splitPolygon( outerNode, hole );
35828  
35829			filterPoints( b, b.next );
35830  
35831		}
35832  
35833	}
35834  
35835	// David Eberly's algorithm for finding a bridge between hole and outer polygon
35836  
35837	function findHoleBridge( hole, outerNode ) {
35838  
35839		var p = outerNode,
35840			hx = hole.x,
35841			hy = hole.y,
35842			qx = - Infinity,
35843			m;
35844  
35845		// find a segment intersected by a ray from the hole's leftmost point to the left;
35846		// segment's endpoint with lesser x will be potential connection point
35847  
35848		do {
35849  
35850			if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
35851  
35852				var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
35853  
35854				if ( x <= hx && x > qx ) {
35855  
35856					qx = x;
35857  
35858					if ( x === hx ) {
35859  
35860						if ( hy === p.y ) return p;
35861						if ( hy === p.next.y ) return p.next;
35862  
35863					}
35864  
35865					m = p.x < p.next.x ? p : p.next;
35866  
35867				}
35868  
35869			}
35870  
35871			p = p.next;
35872  
35873		} while ( p !== outerNode );
35874  
35875		if ( ! m ) return null;
35876  
35877		if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint
35878  
35879		// look for points inside the triangle of hole point, segment intersection and endpoint;
35880		// if there are no points found, we have a valid connection;
35881		// otherwise choose the point of the minimum angle with the ray as connection point
35882  
35883		var stop = m,
35884			mx = m.x,
35885			my = m.y,
35886			tanMin = Infinity,
35887			tan;
35888  
35889		p = m.next;
35890  
35891		while ( p !== stop ) {
35892  
35893			if ( hx >= p.x && p.x >= mx && hx !== p.x &&
35894							pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
35895  
35896				tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
35897  
35898				if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {
35899  
35900					m = p;
35901					tanMin = tan;
35902  
35903				}
35904  
35905			}
35906  
35907			p = p.next;
35908  
35909		}
35910  
35911		return m;
35912  
35913	}
35914  
35915	// interlink polygon nodes in z-order
35916  
35917	function indexCurve( start, minX, minY, invSize ) {
35918  
35919		var p = start;
35920  
35921		do {
35922  
35923			if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
35924			p.prevZ = p.prev;
35925			p.nextZ = p.next;
35926			p = p.next;
35927  
35928		} while ( p !== start );
35929  
35930		p.prevZ.nextZ = null;
35931		p.prevZ = null;
35932  
35933		sortLinked( p );
35934  
35935	}
35936  
35937	// Simon Tatham's linked list merge sort algorithm
35938	// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
35939  
35940	function sortLinked( list ) {
35941  
35942		var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
35943  
35944		do {
35945  
35946			p = list;
35947			list = null;
35948			tail = null;
35949			numMerges = 0;
35950  
35951			while ( p ) {
35952  
35953				numMerges ++;
35954				q = p;
35955				pSize = 0;
35956  
35957				for ( i = 0; i < inSize; i ++ ) {
35958  
35959					pSize ++;
35960					q = q.nextZ;
35961					if ( ! q ) break;
35962  
35963				}
35964  
35965				qSize = inSize;
35966  
35967				while ( pSize > 0 || ( qSize > 0 && q ) ) {
35968  
35969					if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
35970  
35971						e = p;
35972						p = p.nextZ;
35973						pSize --;
35974  
35975					} else {
35976  
35977						e = q;
35978						q = q.nextZ;
35979						qSize --;
35980  
35981					}
35982  
35983					if ( tail ) tail.nextZ = e;
35984					else list = e;
35985  
35986					e.prevZ = tail;
35987					tail = e;
35988  
35989				}
35990  
35991				p = q;
35992  
35993			}
35994  
35995			tail.nextZ = null;
35996			inSize *= 2;
35997  
35998		} while ( numMerges > 1 );
35999  
36000		return list;
36001  
36002	}
36003  
36004	// z-order of a point given coords and inverse of the longer side of data bbox
36005  
36006	function zOrder( x, y, minX, minY, invSize ) {
36007  
36008		// coords are transformed into non-negative 15-bit integer range
36009  
36010		x = 32767 * ( x - minX ) * invSize;
36011		y = 32767 * ( y - minY ) * invSize;
36012  
36013		x = ( x | ( x << 8 ) ) & 0x00FF00FF;
36014		x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
36015		x = ( x | ( x << 2 ) ) & 0x33333333;
36016		x = ( x | ( x << 1 ) ) & 0x55555555;
36017  
36018		y = ( y | ( y << 8 ) ) & 0x00FF00FF;
36019		y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
36020		y = ( y | ( y << 2 ) ) & 0x33333333;
36021		y = ( y | ( y << 1 ) ) & 0x55555555;
36022  
36023		return x | ( y << 1 );
36024  
36025	}
36026  
36027	// find the leftmost node of a polygon ring
36028  
36029	function getLeftmost( start ) {
36030  
36031		var p = start, leftmost = start;
36032  
36033		do {
36034  
36035			if ( p.x < leftmost.x ) leftmost = p;
36036			p = p.next;
36037  
36038		} while ( p !== start );
36039  
36040		return leftmost;
36041  
36042	}
36043  
36044	// check if a point lies within a convex triangle
36045  
36046	function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
36047  
36048		return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
36049		 ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
36050		 ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
36051  
36052	}
36053  
36054	// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
36055  
36056	function isValidDiagonal( a, b ) {
36057  
36058		return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&
36059			locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );
36060  
36061	}
36062  
36063	// signed area of a triangle
36064  
36065	function area( p, q, r ) {
36066  
36067		return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
36068  
36069	}
36070  
36071	// check if two points are equal
36072  
36073	function equals( p1, p2 ) {
36074  
36075		return p1.x === p2.x && p1.y === p2.y;
36076  
36077	}
36078  
36079	// check if two segments intersect
36080  
36081	function intersects( p1, q1, p2, q2 ) {
36082  
36083		if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) ||
36084				( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true;
36085  
36086		return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&
36087					 area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;
36088  
36089	}
36090  
36091	// check if a polygon diagonal intersects any polygon segments
36092  
36093	function intersectsPolygon( a, b ) {
36094  
36095		var p = a;
36096  
36097		do {
36098  
36099			if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
36100							intersects( p, p.next, a, b ) ) {
36101  
36102				return true;
36103  
36104			}
36105  
36106			p = p.next;
36107  
36108		} while ( p !== a );
36109  
36110		return false;
36111  
36112	}
36113  
36114	// check if a polygon diagonal is locally inside the polygon
36115  
36116	function locallyInside( a, b ) {
36117  
36118		return area( a.prev, a, a.next ) < 0 ?
36119			area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
36120			area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
36121  
36122	}
36123  
36124	// check if the middle point of a polygon diagonal is inside the polygon
36125  
36126	function middleInside( a, b ) {
36127  
36128		var p = a,
36129			inside = false,
36130			px = ( a.x + b.x ) / 2,
36131			py = ( a.y + b.y ) / 2;
36132  
vendor: 56,222 bytes, lines 36133-38626
36133		do {
36134  
36135			if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
36136							( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) {
36137  
36138				inside = ! inside;
36139  
36140			}
36141  
36142			p = p.next;
36143  
36144		} while ( p !== a );
36145  
36146		return inside;
36147  
36148	}
36149  
36150	// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
36151	// if one belongs to the outer ring and another to a hole, it merges it into a single ring
36152  
36153	function splitPolygon( a, b ) {
36154  
36155		var a2 = new Node( a.i, a.x, a.y ),
36156			b2 = new Node( b.i, b.x, b.y ),
36157			an = a.next,
36158			bp = b.prev;
36159  
36160		a.next = b;
36161		b.prev = a;
36162  
36163		a2.next = an;
36164		an.prev = a2;
36165  
36166		b2.next = a2;
36167		a2.prev = b2;
36168  
36169		bp.next = b2;
36170		b2.prev = bp;
36171  
36172		return b2;
36173  
36174	}
36175  
36176	// create a node and optionally link it with previous one (in a circular doubly linked list)
36177  
36178	function insertNode( i, x, y, last ) {
36179  
36180		var p = new Node( i, x, y );
36181  
36182		if ( ! last ) {
36183  
36184			p.prev = p;
36185			p.next = p;
36186  
36187		} else {
36188  
36189			p.next = last.next;
36190			p.prev = last;
36191			last.next.prev = p;
36192			last.next = p;
36193  
36194		}
36195  
36196		return p;
36197  
36198	}
36199  
36200	function removeNode( p ) {
36201  
36202		p.next.prev = p.prev;
36203		p.prev.next = p.next;
36204  
36205		if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
36206		if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
36207  
36208	}
36209  
36210	function Node( i, x, y ) {
36211  
36212		// vertice index in coordinates array
36213		this.i = i;
36214  
36215		// vertex coordinates
36216		this.x = x;
36217		this.y = y;
36218  
36219		// previous and next vertice nodes in a polygon ring
36220		this.prev = null;
36221		this.next = null;
36222  
36223		// z-order curve value
36224		this.z = null;
36225  
36226		// previous and next nodes in z-order
36227		this.prevZ = null;
36228		this.nextZ = null;
36229  
36230		// indicates whether this is a steiner point
36231		this.steiner = false;
36232  
36233	}
36234  
36235	function signedArea( data, start, end, dim ) {
36236  
36237		var sum = 0;
36238  
36239		for ( var i = start, j = end - dim; i < end; i += dim ) {
36240  
36241			sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
36242			j = i;
36243  
36244		}
36245  
36246		return sum;
36247  
36248	}
36249  
36250	/**
36251	 * @author zz85 / http://www.lab4games.net/zz85/blog
36252	 */
36253  
36254	var ShapeUtils = {
36255  
36256		// calculate area of the contour polygon
36257  
36258		area: function ( contour ) {
36259  
36260			var n = contour.length;
36261			var a = 0.0;
36262  
36263			for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
36264  
36265				a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
36266  
36267			}
36268  
36269			return a * 0.5;
36270  
36271		},
36272  
36273		isClockWise: function ( pts ) {
36274  
36275			return ShapeUtils.area( pts ) < 0;
36276  
36277		},
36278  
36279		triangulateShape: function ( contour, holes ) {
36280  
36281			var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
36282			var holeIndices = []; // array of hole indices
36283			var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
36284  
36285			removeDupEndPts( contour );
36286			addContour( vertices, contour );
36287  
36288			//
36289  
36290			var holeIndex = contour.length;
36291  
36292			holes.forEach( removeDupEndPts );
36293  
36294			for ( var i = 0; i < holes.length; i ++ ) {
36295  
36296				holeIndices.push( holeIndex );
36297				holeIndex += holes[ i ].length;
36298				addContour( vertices, holes[ i ] );
36299  
36300			}
36301  
36302			//
36303  
36304			var triangles = Earcut.triangulate( vertices, holeIndices );
36305  
36306			//
36307  
36308			for ( var i = 0; i < triangles.length; i += 3 ) {
36309  
36310				faces.push( triangles.slice( i, i + 3 ) );
36311  
36312			}
36313  
36314			return faces;
36315  
36316		}
36317  
36318	};
36319  
36320	function removeDupEndPts( points ) {
36321  
36322		var l = points.length;
36323  
36324		if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
36325  
36326			points.pop();
36327  
36328		}
36329  
36330	}
36331  
36332	function addContour( vertices, contour ) {
36333  
36334		for ( var i = 0; i < contour.length; i ++ ) {
36335  
36336			vertices.push( contour[ i ].x );
36337			vertices.push( contour[ i ].y );
36338  
36339		}
36340  
36341	}
36342  
36343	/**
36344	 * @author zz85 / http://www.lab4games.net/zz85/blog
36345	 *
36346	 * Creates extruded geometry from a path shape.
36347	 *
36348	 * parameters = {
36349	 *
36350	 *  curveSegments: <int>, // number of points on the curves
36351	 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
36352	 *  depth: <float>, // Depth to extrude the shape
36353	 *
36354	 *  bevelEnabled: <bool>, // turn on bevel
36355	 *  bevelThickness: <float>, // how deep into the original shape bevel goes
36356	 *  bevelSize: <float>, // how far from shape outline is bevel
36357	 *  bevelSegments: <int>, // number of bevel layers
36358	 *
36359	 *  extrudePath: <THREE.Curve> // curve to extrude shape along
36360	 *
36361	 *  UVGenerator: <Object> // object that provides UV generator functions
36362	 *
36363	 * }
36364	 */
36365  
36366	// ExtrudeGeometry
36367  
36368	function ExtrudeGeometry( shapes, options ) {
36369  
36370		Geometry.call( this );
36371  
36372		this.type = 'ExtrudeGeometry';
36373  
36374		this.parameters = {
36375			shapes: shapes,
36376			options: options
36377		};
36378  
36379		this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
36380		this.mergeVertices();
36381  
36382	}
36383  
36384	ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
36385	ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
36386  
36387	ExtrudeGeometry.prototype.toJSON = function () {
36388  
36389		var data = Geometry.prototype.toJSON.call( this );
36390  
36391		var shapes = this.parameters.shapes;
36392		var options = this.parameters.options;
36393  
36394		return toJSON( shapes, options, data );
36395  
36396	};
36397  
36398	// ExtrudeBufferGeometry
36399  
36400	function ExtrudeBufferGeometry( shapes, options ) {
36401  
36402		BufferGeometry.call( this );
36403  
36404		this.type = 'ExtrudeBufferGeometry';
36405  
36406		this.parameters = {
36407			shapes: shapes,
36408			options: options
36409		};
36410  
36411		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
36412  
36413		var scope = this;
36414  
36415		var verticesArray = [];
36416		var uvArray = [];
36417  
36418		for ( var i = 0, l = shapes.length; i < l; i ++ ) {
36419  
36420			var shape = shapes[ i ];
36421			addShape( shape );
36422  
36423		}
36424  
36425		// build geometry
36426  
36427		this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
36428		this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
36429  
36430		this.computeVertexNormals();
36431  
36432		// functions
36433  
36434		function addShape( shape ) {
36435  
36436			var placeholder = [];
36437  
36438			// options
36439  
36440			var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
36441			var steps = options.steps !== undefined ? options.steps : 1;
36442			var depth = options.depth !== undefined ? options.depth : 100;
36443  
36444			var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
36445			var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
36446			var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
36447			var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
36448  
36449			var extrudePath = options.extrudePath;
36450  
36451			var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
36452  
36453			// deprecated options
36454  
36455			if ( options.amount !== undefined ) {
36456  
36457				console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
36458				depth = options.amount;
36459  
36460			}
36461  
36462			//
36463  
36464			var extrudePts, extrudeByPath = false;
36465			var splineTube, binormal, normal, position2;
36466  
36467			if ( extrudePath ) {
36468  
36469				extrudePts = extrudePath.getSpacedPoints( steps );
36470  
36471				extrudeByPath = true;
36472				bevelEnabled = false; // bevels not supported for path extrusion
36473  
36474				// SETUP TNB variables
36475  
36476				// TODO1 - have a .isClosed in spline?
36477  
36478				splineTube = extrudePath.computeFrenetFrames( steps, false );
36479  
36480				// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
36481  
36482				binormal = new Vector3();
36483				normal = new Vector3();
36484				position2 = new Vector3();
36485  
36486			}
36487  
36488			// Safeguards if bevels are not enabled
36489  
36490			if ( ! bevelEnabled ) {
36491  
36492				bevelSegments = 0;
36493				bevelThickness = 0;
36494				bevelSize = 0;
36495  
36496			}
36497  
36498			// Variables initialization
36499  
36500			var ahole, h, hl; // looping of holes
36501  
36502			var shapePoints = shape.extractPoints( curveSegments );
36503  
36504			var vertices = shapePoints.shape;
36505			var holes = shapePoints.holes;
36506  
36507			var reverse = ! ShapeUtils.isClockWise( vertices );
36508  
36509			if ( reverse ) {
36510  
36511				vertices = vertices.reverse();
36512  
36513				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
36514  
36515				for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36516  
36517					ahole = holes[ h ];
36518  
36519					if ( ShapeUtils.isClockWise( ahole ) ) {
36520  
36521						holes[ h ] = ahole.reverse();
36522  
36523					}
36524  
36525				}
36526  
36527			}
36528  
36529  
36530			var faces = ShapeUtils.triangulateShape( vertices, holes );
36531  
36532			/* Vertices */
36533  
36534			var contour = vertices; // vertices has all points but contour has only points of circumference
36535  
36536			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36537  
36538				ahole = holes[ h ];
36539  
36540				vertices = vertices.concat( ahole );
36541  
36542			}
36543  
36544  
36545			function scalePt2( pt, vec, size ) {
36546  
36547				if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
36548  
36549				return vec.clone().multiplyScalar( size ).add( pt );
36550  
36551			}
36552  
36553			var b, bs, t, z,
36554				vert, vlen = vertices.length,
36555				face, flen = faces.length;
36556  
36557  
36558			// Find directions for point movement
36559  
36560  
36561			function getBevelVec( inPt, inPrev, inNext ) {
36562  
36563				// computes for inPt the corresponding point inPt' on a new contour
36564				//   shifted by 1 unit (length of normalized vector) to the left
36565				// if we walk along contour clockwise, this new contour is outside the old one
36566				//
36567				// inPt' is the intersection of the two lines parallel to the two
36568				//  adjacent edges of inPt at a distance of 1 unit on the left side.
36569  
36570				var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
36571  
36572				// good reading for geometry algorithms (here: line-line intersection)
36573				// http://geomalgorithms.com/a05-_intersect-1.html
36574  
36575				var v_prev_x = inPt.x - inPrev.x,
36576					v_prev_y = inPt.y - inPrev.y;
36577				var v_next_x = inNext.x - inPt.x,
36578					v_next_y = inNext.y - inPt.y;
36579  
36580				var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
36581  
36582				// check for collinear edges
36583				var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
36584  
36585				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
36586  
36587					// not collinear
36588  
36589					// length of vectors for normalizing
36590  
36591					var v_prev_len = Math.sqrt( v_prev_lensq );
36592					var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
36593  
36594					// shift adjacent points by unit vectors to the left
36595  
36596					var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
36597					var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
36598  
36599					var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
36600					var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
36601  
36602					// scaling factor for v_prev to intersection point
36603  
36604					var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
36605							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
36606						( v_prev_x * v_next_y - v_prev_y * v_next_x );
36607  
36608					// vector from inPt to intersection point
36609  
36610					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
36611					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
36612  
36613					// Don't normalize!, otherwise sharp corners become ugly
36614					//  but prevent crazy spikes
36615					var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
36616					if ( v_trans_lensq <= 2 ) {
36617  
36618						return new Vector2( v_trans_x, v_trans_y );
36619  
36620					} else {
36621  
36622						shrink_by = Math.sqrt( v_trans_lensq / 2 );
36623  
36624					}
36625  
36626				} else {
36627  
36628					// handle special case of collinear edges
36629  
36630					var direction_eq = false; // assumes: opposite
36631					if ( v_prev_x > Number.EPSILON ) {
36632  
36633						if ( v_next_x > Number.EPSILON ) {
36634  
36635							direction_eq = true;
36636  
36637						}
36638  
36639					} else {
36640  
36641						if ( v_prev_x < - Number.EPSILON ) {
36642  
36643							if ( v_next_x < - Number.EPSILON ) {
36644  
36645								direction_eq = true;
36646  
36647							}
36648  
36649						} else {
36650  
36651							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
36652  
36653								direction_eq = true;
36654  
36655							}
36656  
36657						}
36658  
36659					}
36660  
36661					if ( direction_eq ) {
36662  
36663						// console.log("Warning: lines are a straight sequence");
36664						v_trans_x = - v_prev_y;
36665						v_trans_y = v_prev_x;
36666						shrink_by = Math.sqrt( v_prev_lensq );
36667  
36668					} else {
36669  
36670						// console.log("Warning: lines are a straight spike");
36671						v_trans_x = v_prev_x;
36672						v_trans_y = v_prev_y;
36673						shrink_by = Math.sqrt( v_prev_lensq / 2 );
36674  
36675					}
36676  
36677				}
36678  
36679				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
36680  
36681			}
36682  
36683  
36684			var contourMovements = [];
36685  
36686			for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
36687  
36688				if ( j === il ) j = 0;
36689				if ( k === il ) k = 0;
36690  
36691				//  (j)---(i)---(k)
36692				// console.log('i,j,k', i, j , k)
36693  
36694				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
36695  
36696			}
36697  
36698			var holesMovements = [],
36699				oneHoleMovements, verticesMovements = contourMovements.concat();
36700  
36701			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36702  
36703				ahole = holes[ h ];
36704  
36705				oneHoleMovements = [];
36706  
36707				for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
36708  
36709					if ( j === il ) j = 0;
36710					if ( k === il ) k = 0;
36711  
36712					//  (j)---(i)---(k)
36713					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
36714  
36715				}
36716  
36717				holesMovements.push( oneHoleMovements );
36718				verticesMovements = verticesMovements.concat( oneHoleMovements );
36719  
36720			}
36721  
36722  
36723			// Loop bevelSegments, 1 for the front, 1 for the back
36724  
36725			for ( b = 0; b < bevelSegments; b ++ ) {
36726  
36727				//for ( b = bevelSegments; b > 0; b -- ) {
36728  
36729				t = b / bevelSegments;
36730				z = bevelThickness * Math.cos( t * Math.PI / 2 );
36731				bs = bevelSize * Math.sin( t * Math.PI / 2 );
36732  
36733				// contract shape
36734  
36735				for ( i = 0, il = contour.length; i < il; i ++ ) {
36736  
36737					vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
36738  
36739					v( vert.x, vert.y, - z );
36740  
36741				}
36742  
36743				// expand holes
36744  
36745				for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36746  
36747					ahole = holes[ h ];
36748					oneHoleMovements = holesMovements[ h ];
36749  
36750					for ( i = 0, il = ahole.length; i < il; i ++ ) {
36751  
36752						vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
36753  
36754						v( vert.x, vert.y, - z );
36755  
36756					}
36757  
36758				}
36759  
36760			}
36761  
36762			bs = bevelSize;
36763  
36764			// Back facing vertices
36765  
36766			for ( i = 0; i < vlen; i ++ ) {
36767  
36768				vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
36769  
36770				if ( ! extrudeByPath ) {
36771  
36772					v( vert.x, vert.y, 0 );
36773  
36774				} else {
36775  
36776					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
36777  
36778					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
36779					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
36780  
36781					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
36782  
36783					v( position2.x, position2.y, position2.z );
36784  
36785				}
36786  
36787			}
36788  
36789			// Add stepped vertices...
36790			// Including front facing vertices
36791  
36792			var s;
36793  
36794			for ( s = 1; s <= steps; s ++ ) {
36795  
36796				for ( i = 0; i < vlen; i ++ ) {
36797  
36798					vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
36799  
36800					if ( ! extrudeByPath ) {
36801  
36802						v( vert.x, vert.y, depth / steps * s );
36803  
36804					} else {
36805  
36806						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
36807  
36808						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
36809						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
36810  
36811						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
36812  
36813						v( position2.x, position2.y, position2.z );
36814  
36815					}
36816  
36817				}
36818  
36819			}
36820  
36821  
36822			// Add bevel segments planes
36823  
36824			//for ( b = 1; b <= bevelSegments; b ++ ) {
36825			for ( b = bevelSegments - 1; b >= 0; b -- ) {
36826  
36827				t = b / bevelSegments;
36828				z = bevelThickness * Math.cos( t * Math.PI / 2 );
36829				bs = bevelSize * Math.sin( t * Math.PI / 2 );
36830  
36831				// contract shape
36832  
36833				for ( i = 0, il = contour.length; i < il; i ++ ) {
36834  
36835					vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
36836					v( vert.x, vert.y, depth + z );
36837  
36838				}
36839  
36840				// expand holes
36841  
36842				for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36843  
36844					ahole = holes[ h ];
36845					oneHoleMovements = holesMovements[ h ];
36846  
36847					for ( i = 0, il = ahole.length; i < il; i ++ ) {
36848  
36849						vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
36850  
36851						if ( ! extrudeByPath ) {
36852  
36853							v( vert.x, vert.y, depth + z );
36854  
36855						} else {
36856  
36857							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
36858  
36859						}
36860  
36861					}
36862  
36863				}
36864  
36865			}
36866  
36867			/* Faces */
36868  
36869			// Top and bottom faces
36870  
36871			buildLidFaces();
36872  
36873			// Sides faces
36874  
36875			buildSideFaces();
36876  
36877  
36878			/////  Internal functions
36879  
36880			function buildLidFaces() {
36881  
36882				var start = verticesArray.length / 3;
36883  
36884				if ( bevelEnabled ) {
36885  
36886					var layer = 0; // steps + 1
36887					var offset = vlen * layer;
36888  
36889					// Bottom faces
36890  
36891					for ( i = 0; i < flen; i ++ ) {
36892  
36893						face = faces[ i ];
36894						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
36895  
36896					}
36897  
36898					layer = steps + bevelSegments * 2;
36899					offset = vlen * layer;
36900  
36901					// Top faces
36902  
36903					for ( i = 0; i < flen; i ++ ) {
36904  
36905						face = faces[ i ];
36906						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
36907  
36908					}
36909  
36910				} else {
36911  
36912					// Bottom faces
36913  
36914					for ( i = 0; i < flen; i ++ ) {
36915  
36916						face = faces[ i ];
36917						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
36918  
36919					}
36920  
36921					// Top faces
36922  
36923					for ( i = 0; i < flen; i ++ ) {
36924  
36925						face = faces[ i ];
36926						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
36927  
36928					}
36929  
36930				}
36931  
36932				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
36933  
36934			}
36935  
36936			// Create faces for the z-sides of the shape
36937  
36938			function buildSideFaces() {
36939  
36940				var start = verticesArray.length / 3;
36941				var layeroffset = 0;
36942				sidewalls( contour, layeroffset );
36943				layeroffset += contour.length;
36944  
36945				for ( h = 0, hl = holes.length; h < hl; h ++ ) {
36946  
36947					ahole = holes[ h ];
36948					sidewalls( ahole, layeroffset );
36949  
36950					//, true
36951					layeroffset += ahole.length;
36952  
36953				}
36954  
36955  
36956				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
36957  
36958  
36959			}
36960  
36961			function sidewalls( contour, layeroffset ) {
36962  
36963				var j, k;
36964				i = contour.length;
36965  
36966				while ( -- i >= 0 ) {
36967  
36968					j = i;
36969					k = i - 1;
36970					if ( k < 0 ) k = contour.length - 1;
36971  
36972					//console.log('b', i,j, i-1, k,vertices.length);
36973  
36974					var s = 0,
36975						sl = steps + bevelSegments * 2;
36976  
36977					for ( s = 0; s < sl; s ++ ) {
36978  
36979						var slen1 = vlen * s;
36980						var slen2 = vlen * ( s + 1 );
36981  
36982						var a = layeroffset + j + slen1,
36983							b = layeroffset + k + slen1,
36984							c = layeroffset + k + slen2,
36985							d = layeroffset + j + slen2;
36986  
36987						f4( a, b, c, d );
36988  
36989					}
36990  
36991				}
36992  
36993			}
36994  
36995			function v( x, y, z ) {
36996  
36997				placeholder.push( x );
36998				placeholder.push( y );
36999				placeholder.push( z );
37000  
37001			}
37002  
37003  
37004			function f3( a, b, c ) {
37005  
37006				addVertex( a );
37007				addVertex( b );
37008				addVertex( c );
37009  
37010				var nextIndex = verticesArray.length / 3;
37011				var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
37012  
37013				addUV( uvs[ 0 ] );
37014				addUV( uvs[ 1 ] );
37015				addUV( uvs[ 2 ] );
37016  
37017			}
37018  
37019			function f4( a, b, c, d ) {
37020  
37021				addVertex( a );
37022				addVertex( b );
37023				addVertex( d );
37024  
37025				addVertex( b );
37026				addVertex( c );
37027				addVertex( d );
37028  
37029  
37030				var nextIndex = verticesArray.length / 3;
37031				var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
37032  
37033				addUV( uvs[ 0 ] );
37034				addUV( uvs[ 1 ] );
37035				addUV( uvs[ 3 ] );
37036  
37037				addUV( uvs[ 1 ] );
37038				addUV( uvs[ 2 ] );
37039				addUV( uvs[ 3 ] );
37040  
37041			}
37042  
37043			function addVertex( index ) {
37044  
37045				verticesArray.push( placeholder[ index * 3 + 0 ] );
37046				verticesArray.push( placeholder[ index * 3 + 1 ] );
37047				verticesArray.push( placeholder[ index * 3 + 2 ] );
37048  
37049			}
37050  
37051  
37052			function addUV( vector2 ) {
37053  
37054				uvArray.push( vector2.x );
37055				uvArray.push( vector2.y );
37056  
37057			}
37058  
37059		}
37060  
37061	}
37062  
37063	ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
37064	ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
37065  
37066	ExtrudeBufferGeometry.prototype.toJSON = function () {
37067  
37068		var data = BufferGeometry.prototype.toJSON.call( this );
37069  
37070		var shapes = this.parameters.shapes;
37071		var options = this.parameters.options;
37072  
37073		return toJSON( shapes, options, data );
37074  
37075	};
37076  
37077	//
37078  
37079	var WorldUVGenerator = {
37080  
37081		generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
37082  
37083			var a_x = vertices[ indexA * 3 ];
37084			var a_y = vertices[ indexA * 3 + 1 ];
37085			var b_x = vertices[ indexB * 3 ];
37086			var b_y = vertices[ indexB * 3 + 1 ];
37087			var c_x = vertices[ indexC * 3 ];
37088			var c_y = vertices[ indexC * 3 + 1 ];
37089  
37090			return [
37091				new Vector2( a_x, a_y ),
37092				new Vector2( b_x, b_y ),
37093				new Vector2( c_x, c_y )
37094			];
37095  
37096		},
37097  
37098		generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
37099  
37100			var a_x = vertices[ indexA * 3 ];
37101			var a_y = vertices[ indexA * 3 + 1 ];
37102			var a_z = vertices[ indexA * 3 + 2 ];
37103			var b_x = vertices[ indexB * 3 ];
37104			var b_y = vertices[ indexB * 3 + 1 ];
37105			var b_z = vertices[ indexB * 3 + 2 ];
37106			var c_x = vertices[ indexC * 3 ];
37107			var c_y = vertices[ indexC * 3 + 1 ];
37108			var c_z = vertices[ indexC * 3 + 2 ];
37109			var d_x = vertices[ indexD * 3 ];
37110			var d_y = vertices[ indexD * 3 + 1 ];
37111			var d_z = vertices[ indexD * 3 + 2 ];
37112  
37113			if ( Math.abs( a_y - b_y ) < 0.01 ) {
37114  
37115				return [
37116					new Vector2( a_x, 1 - a_z ),
37117					new Vector2( b_x, 1 - b_z ),
37118					new Vector2( c_x, 1 - c_z ),
37119					new Vector2( d_x, 1 - d_z )
37120				];
37121  
37122			} else {
37123  
37124				return [
37125					new Vector2( a_y, 1 - a_z ),
37126					new Vector2( b_y, 1 - b_z ),
37127					new Vector2( c_y, 1 - c_z ),
37128					new Vector2( d_y, 1 - d_z )
37129				];
37130  
37131			}
37132  
37133		}
37134	};
37135  
37136	function toJSON( shapes, options, data ) {
37137  
37138		//
37139  
37140		data.shapes = [];
37141  
37142		if ( Array.isArray( shapes ) ) {
37143  
37144			for ( var i = 0, l = shapes.length; i < l; i ++ ) {
37145  
37146				var shape = shapes[ i ];
37147  
37148				data.shapes.push( shape.uuid );
37149  
37150			}
37151  
37152		} else {
37153  
37154			data.shapes.push( shapes.uuid );
37155  
37156		}
37157  
37158		//
37159  
37160		if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
37161  
37162		return data;
37163  
37164	}
37165  
37166	/**
37167	 * @author zz85 / http://www.lab4games.net/zz85/blog
37168	 * @author alteredq / http://alteredqualia.com/
37169	 *
37170	 * Text = 3D Text
37171	 *
37172	 * parameters = {
37173	 *  font: <THREE.Font>, // font
37174	 *
37175	 *  size: <float>, // size of the text
37176	 *  height: <float>, // thickness to extrude text
37177	 *  curveSegments: <int>, // number of points on the curves
37178	 *
37179	 *  bevelEnabled: <bool>, // turn on bevel
37180	 *  bevelThickness: <float>, // how deep into text bevel goes
37181	 *  bevelSize: <float> // how far from text outline is bevel
37182	 * }
37183	 */
37184  
37185	// TextGeometry
37186  
37187	function TextGeometry( text, parameters ) {
37188  
37189		Geometry.call( this );
37190  
37191		this.type = 'TextGeometry';
37192  
37193		this.parameters = {
37194			text: text,
37195			parameters: parameters
37196		};
37197  
37198		this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
37199		this.mergeVertices();
37200  
37201	}
37202  
37203	TextGeometry.prototype = Object.create( Geometry.prototype );
37204	TextGeometry.prototype.constructor = TextGeometry;
37205  
37206	// TextBufferGeometry
37207  
37208	function TextBufferGeometry( text, parameters ) {
37209  
37210		parameters = parameters || {};
37211  
37212		var font = parameters.font;
37213  
37214		if ( ! ( font && font.isFont ) ) {
37215  
37216			console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
37217			return new Geometry();
37218  
37219		}
37220  
37221		var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments );
37222  
37223		// translate parameters to ExtrudeGeometry API
37224  
37225		parameters.depth = parameters.height !== undefined ? parameters.height : 50;
37226  
37227		// defaults
37228  
37229		if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
37230		if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
37231		if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
37232  
37233		ExtrudeBufferGeometry.call( this, shapes, parameters );
37234  
37235		this.type = 'TextBufferGeometry';
37236  
37237	}
37238  
37239	TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
37240	TextBufferGeometry.prototype.constructor = TextBufferGeometry;
37241  
37242	/**
37243	 * @author mrdoob / http://mrdoob.com/
37244	 * @author benaadams / https://twitter.com/ben_a_adams
37245	 * @author Mugen87 / https://github.com/Mugen87
37246	 */
37247  
37248	// SphereGeometry
37249  
37250	function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
37251  
37252		Geometry.call( this );
37253  
37254		this.type = 'SphereGeometry';
37255  
37256		this.parameters = {
37257			radius: radius,
37258			widthSegments: widthSegments,
37259			heightSegments: heightSegments,
37260			phiStart: phiStart,
37261			phiLength: phiLength,
37262			thetaStart: thetaStart,
37263			thetaLength: thetaLength
37264		};
37265  
37266		this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
37267		this.mergeVertices();
37268  
37269	}
37270  
37271	SphereGeometry.prototype = Object.create( Geometry.prototype );
37272	SphereGeometry.prototype.constructor = SphereGeometry;
37273  
37274	// SphereBufferGeometry
37275  
37276	function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
37277  
37278		BufferGeometry.call( this );
37279  
37280		this.type = 'SphereBufferGeometry';
37281  
37282		this.parameters = {
37283			radius: radius,
37284			widthSegments: widthSegments,
37285			heightSegments: heightSegments,
37286			phiStart: phiStart,
37287			phiLength: phiLength,
37288			thetaStart: thetaStart,
37289			thetaLength: thetaLength
37290		};
37291  
37292		radius = radius || 1;
37293  
37294		widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
37295		heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
37296  
37297		phiStart = phiStart !== undefined ? phiStart : 0;
37298		phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
37299  
37300		thetaStart = thetaStart !== undefined ? thetaStart : 0;
37301		thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
37302  
37303		var thetaEnd = thetaStart + thetaLength;
37304  
37305		var ix, iy;
37306  
37307		var index = 0;
37308		var grid = [];
37309  
37310		var vertex = new Vector3();
37311		var normal = new Vector3();
37312  
37313		// buffers
37314  
37315		var indices = [];
37316		var vertices = [];
37317		var normals = [];
37318		var uvs = [];
37319  
37320		// generate vertices, normals and uvs
37321  
37322		for ( iy = 0; iy <= heightSegments; iy ++ ) {
37323  
37324			var verticesRow = [];
37325  
37326			var v = iy / heightSegments;
37327  
37328			for ( ix = 0; ix <= widthSegments; ix ++ ) {
37329  
37330				var u = ix / widthSegments;
37331  
37332				// vertex
37333  
37334				vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
37335				vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
37336				vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
37337  
37338				vertices.push( vertex.x, vertex.y, vertex.z );
37339  
37340				// normal
37341  
37342				normal.set( vertex.x, vertex.y, vertex.z ).normalize();
37343				normals.push( normal.x, normal.y, normal.z );
37344  
37345				// uv
37346  
37347				uvs.push( u, 1 - v );
37348  
37349				verticesRow.push( index ++ );
37350  
37351			}
37352  
37353			grid.push( verticesRow );
37354  
37355		}
37356  
37357		// indices
37358  
37359		for ( iy = 0; iy < heightSegments; iy ++ ) {
37360  
37361			for ( ix = 0; ix < widthSegments; ix ++ ) {
37362  
37363				var a = grid[ iy ][ ix + 1 ];
37364				var b = grid[ iy ][ ix ];
37365				var c = grid[ iy + 1 ][ ix ];
37366				var d = grid[ iy + 1 ][ ix + 1 ];
37367  
37368				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
37369				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
37370  
37371			}
37372  
37373		}
37374  
37375		// build geometry
37376  
37377		this.setIndex( indices );
37378		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37379		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37380		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37381  
37382	}
37383  
37384	SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
37385	SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
37386  
37387	/**
37388	 * @author Kaleb Murphy
37389	 * @author Mugen87 / https://github.com/Mugen87
37390	 */
37391  
37392	// RingGeometry
37393  
37394	function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
37395  
37396		Geometry.call( this );
37397  
37398		this.type = 'RingGeometry';
37399  
37400		this.parameters = {
37401			innerRadius: innerRadius,
37402			outerRadius: outerRadius,
37403			thetaSegments: thetaSegments,
37404			phiSegments: phiSegments,
37405			thetaStart: thetaStart,
37406			thetaLength: thetaLength
37407		};
37408  
37409		this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
37410		this.mergeVertices();
37411  
37412	}
37413  
37414	RingGeometry.prototype = Object.create( Geometry.prototype );
37415	RingGeometry.prototype.constructor = RingGeometry;
37416  
37417	// RingBufferGeometry
37418  
37419	function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
37420  
37421		BufferGeometry.call( this );
37422  
37423		this.type = 'RingBufferGeometry';
37424  
37425		this.parameters = {
37426			innerRadius: innerRadius,
37427			outerRadius: outerRadius,
37428			thetaSegments: thetaSegments,
37429			phiSegments: phiSegments,
37430			thetaStart: thetaStart,
37431			thetaLength: thetaLength
37432		};
37433  
37434		innerRadius = innerRadius || 0.5;
37435		outerRadius = outerRadius || 1;
37436  
37437		thetaStart = thetaStart !== undefined ? thetaStart : 0;
37438		thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
37439  
37440		thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
37441		phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
37442  
37443		// buffers
37444  
37445		var indices = [];
37446		var vertices = [];
37447		var normals = [];
37448		var uvs = [];
37449  
37450		// some helper variables
37451  
37452		var segment;
37453		var radius = innerRadius;
37454		var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
37455		var vertex = new Vector3();
37456		var uv = new Vector2();
37457		var j, i;
37458  
37459		// generate vertices, normals and uvs
37460  
37461		for ( j = 0; j <= phiSegments; j ++ ) {
37462  
37463			for ( i = 0; i <= thetaSegments; i ++ ) {
37464  
37465				// values are generate from the inside of the ring to the outside
37466  
37467				segment = thetaStart + i / thetaSegments * thetaLength;
37468  
37469				// vertex
37470  
37471				vertex.x = radius * Math.cos( segment );
37472				vertex.y = radius * Math.sin( segment );
37473  
37474				vertices.push( vertex.x, vertex.y, vertex.z );
37475  
37476				// normal
37477  
37478				normals.push( 0, 0, 1 );
37479  
37480				// uv
37481  
37482				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
37483				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
37484  
37485				uvs.push( uv.x, uv.y );
37486  
37487			}
37488  
37489			// increase the radius for next row of vertices
37490  
37491			radius += radiusStep;
37492  
37493		}
37494  
37495		// indices
37496  
37497		for ( j = 0; j < phiSegments; j ++ ) {
37498  
37499			var thetaSegmentLevel = j * ( thetaSegments + 1 );
37500  
37501			for ( i = 0; i < thetaSegments; i ++ ) {
37502  
37503				segment = i + thetaSegmentLevel;
37504  
37505				var a = segment;
37506				var b = segment + thetaSegments + 1;
37507				var c = segment + thetaSegments + 2;
37508				var d = segment + 1;
37509  
37510				// faces
37511  
37512				indices.push( a, b, d );
37513				indices.push( b, c, d );
37514  
37515			}
37516  
37517		}
37518  
37519		// build geometry
37520  
37521		this.setIndex( indices );
37522		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37523		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37524		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37525  
37526	}
37527  
37528	RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
37529	RingBufferGeometry.prototype.constructor = RingBufferGeometry;
37530  
37531	/**
37532	 * @author astrodud / http://astrodud.isgreat.org/
37533	 * @author zz85 / https://github.com/zz85
37534	 * @author bhouston / http://clara.io
37535	 * @author Mugen87 / https://github.com/Mugen87
37536	 */
37537  
37538	// LatheGeometry
37539  
37540	function LatheGeometry( points, segments, phiStart, phiLength ) {
37541  
37542		Geometry.call( this );
37543  
37544		this.type = 'LatheGeometry';
37545  
37546		this.parameters = {
37547			points: points,
37548			segments: segments,
37549			phiStart: phiStart,
37550			phiLength: phiLength
37551		};
37552  
37553		this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
37554		this.mergeVertices();
37555  
37556	}
37557  
37558	LatheGeometry.prototype = Object.create( Geometry.prototype );
37559	LatheGeometry.prototype.constructor = LatheGeometry;
37560  
37561	// LatheBufferGeometry
37562  
37563	function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
37564  
37565		BufferGeometry.call( this );
37566  
37567		this.type = 'LatheBufferGeometry';
37568  
37569		this.parameters = {
37570			points: points,
37571			segments: segments,
37572			phiStart: phiStart,
37573			phiLength: phiLength
37574		};
37575  
37576		segments = Math.floor( segments ) || 12;
37577		phiStart = phiStart || 0;
37578		phiLength = phiLength || Math.PI * 2;
37579  
37580		// clamp phiLength so it's in range of [ 0, 2PI ]
37581  
37582		phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
37583  
37584  
37585		// buffers
37586  
37587		var indices = [];
37588		var vertices = [];
37589		var uvs = [];
37590  
37591		// helper variables
37592  
37593		var base;
37594		var inverseSegments = 1.0 / segments;
37595		var vertex = new Vector3();
37596		var uv = new Vector2();
37597		var i, j;
37598  
37599		// generate vertices and uvs
37600  
37601		for ( i = 0; i <= segments; i ++ ) {
37602  
37603			var phi = phiStart + i * inverseSegments * phiLength;
37604  
37605			var sin = Math.sin( phi );
37606			var cos = Math.cos( phi );
37607  
37608			for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
37609  
37610				// vertex
37611  
37612				vertex.x = points[ j ].x * sin;
37613				vertex.y = points[ j ].y;
37614				vertex.z = points[ j ].x * cos;
37615  
37616				vertices.push( vertex.x, vertex.y, vertex.z );
37617  
37618				// uv
37619  
37620				uv.x = i / segments;
37621				uv.y = j / ( points.length - 1 );
37622  
37623				uvs.push( uv.x, uv.y );
37624  
37625  
37626			}
37627  
37628		}
37629  
37630		// indices
37631  
37632		for ( i = 0; i < segments; i ++ ) {
37633  
37634			for ( j = 0; j < ( points.length - 1 ); j ++ ) {
37635  
37636				base = j + i * points.length;
37637  
37638				var a = base;
37639				var b = base + points.length;
37640				var c = base + points.length + 1;
37641				var d = base + 1;
37642  
37643				// faces
37644  
37645				indices.push( a, b, d );
37646				indices.push( b, c, d );
37647  
37648			}
37649  
37650		}
37651  
37652		// build geometry
37653  
37654		this.setIndex( indices );
37655		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37656		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37657  
37658		// generate normals
37659  
37660		this.computeVertexNormals();
37661  
37662		// if the geometry is closed, we need to average the normals along the seam.
37663		// because the corresponding vertices are identical (but still have different UVs).
37664  
37665		if ( phiLength === Math.PI * 2 ) {
37666  
37667			var normals = this.attributes.normal.array;
37668			var n1 = new Vector3();
37669			var n2 = new Vector3();
37670			var n = new Vector3();
37671  
37672			// this is the buffer offset for the last line of vertices
37673  
37674			base = segments * points.length * 3;
37675  
37676			for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
37677  
37678				// select the normal of the vertex in the first line
37679  
37680				n1.x = normals[ j + 0 ];
37681				n1.y = normals[ j + 1 ];
37682				n1.z = normals[ j + 2 ];
37683  
37684				// select the normal of the vertex in the last line
37685  
37686				n2.x = normals[ base + j + 0 ];
37687				n2.y = normals[ base + j + 1 ];
37688				n2.z = normals[ base + j + 2 ];
37689  
37690				// average normals
37691  
37692				n.addVectors( n1, n2 ).normalize();
37693  
37694				// assign the new values to both normals
37695  
37696				normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
37697				normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
37698				normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
37699  
37700			}
37701  
37702		}
37703  
37704	}
37705  
37706	LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
37707	LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
37708  
37709	/**
37710	 * @author jonobr1 / http://jonobr1.com
37711	 * @author Mugen87 / https://github.com/Mugen87
37712	 */
37713  
37714	// ShapeGeometry
37715  
37716	function ShapeGeometry( shapes, curveSegments ) {
37717  
37718		Geometry.call( this );
37719  
37720		this.type = 'ShapeGeometry';
37721  
37722		if ( typeof curveSegments === 'object' ) {
37723  
37724			console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
37725  
37726			curveSegments = curveSegments.curveSegments;
37727  
37728		}
37729  
37730		this.parameters = {
37731			shapes: shapes,
37732			curveSegments: curveSegments
37733		};
37734  
37735		this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
37736		this.mergeVertices();
37737  
37738	}
37739  
37740	ShapeGeometry.prototype = Object.create( Geometry.prototype );
37741	ShapeGeometry.prototype.constructor = ShapeGeometry;
37742  
37743	ShapeGeometry.prototype.toJSON = function () {
37744  
37745		var data = Geometry.prototype.toJSON.call( this );
37746  
37747		var shapes = this.parameters.shapes;
37748  
37749		return toJSON$1( shapes, data );
37750  
37751	};
37752  
37753	// ShapeBufferGeometry
37754  
37755	function ShapeBufferGeometry( shapes, curveSegments ) {
37756  
37757		BufferGeometry.call( this );
37758  
37759		this.type = 'ShapeBufferGeometry';
37760  
37761		this.parameters = {
37762			shapes: shapes,
37763			curveSegments: curveSegments
37764		};
37765  
37766		curveSegments = curveSegments || 12;
37767  
37768		// buffers
37769  
37770		var indices = [];
37771		var vertices = [];
37772		var normals = [];
37773		var uvs = [];
37774  
37775		// helper variables
37776  
37777		var groupStart = 0;
37778		var groupCount = 0;
37779  
37780		// allow single and array values for "shapes" parameter
37781  
37782		if ( Array.isArray( shapes ) === false ) {
37783  
37784			addShape( shapes );
37785  
37786		} else {
37787  
37788			for ( var i = 0; i < shapes.length; i ++ ) {
37789  
37790				addShape( shapes[ i ] );
37791  
37792				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
37793  
37794				groupStart += groupCount;
37795				groupCount = 0;
37796  
37797			}
37798  
37799		}
37800  
37801		// build geometry
37802  
37803		this.setIndex( indices );
37804		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37805		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37806		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37807  
37808  
37809		// helper functions
37810  
37811		function addShape( shape ) {
37812  
37813			var i, l, shapeHole;
37814  
37815			var indexOffset = vertices.length / 3;
37816			var points = shape.extractPoints( curveSegments );
37817  
37818			var shapeVertices = points.shape;
37819			var shapeHoles = points.holes;
37820  
37821			// check direction of vertices
37822  
37823			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
37824  
37825				shapeVertices = shapeVertices.reverse();
37826  
37827				// also check if holes are in the opposite direction
37828  
37829				for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
37830  
37831					shapeHole = shapeHoles[ i ];
37832  
37833					if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
37834  
37835						shapeHoles[ i ] = shapeHole.reverse();
37836  
37837					}
37838  
37839				}
37840  
37841			}
37842  
37843			var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
37844  
37845			// join vertices of inner and outer paths to a single array
37846  
37847			for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
37848  
37849				shapeHole = shapeHoles[ i ];
37850				shapeVertices = shapeVertices.concat( shapeHole );
37851  
37852			}
37853  
37854			// vertices, normals, uvs
37855  
37856			for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
37857  
37858				var vertex = shapeVertices[ i ];
37859  
37860				vertices.push( vertex.x, vertex.y, 0 );
37861				normals.push( 0, 0, 1 );
37862				uvs.push( vertex.x, vertex.y ); // world uvs
37863  
37864			}
37865  
37866			// incides
37867  
37868			for ( i = 0, l = faces.length; i < l; i ++ ) {
37869  
37870				var face = faces[ i ];
37871  
37872				var a = face[ 0 ] + indexOffset;
37873				var b = face[ 1 ] + indexOffset;
37874				var c = face[ 2 ] + indexOffset;
37875  
37876				indices.push( a, b, c );
37877				groupCount += 3;
37878  
37879			}
37880  
37881		}
37882  
37883	}
37884  
37885	ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
37886	ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
37887  
37888	ShapeBufferGeometry.prototype.toJSON = function () {
37889  
37890		var data = BufferGeometry.prototype.toJSON.call( this );
37891  
37892		var shapes = this.parameters.shapes;
37893  
37894		return toJSON$1( shapes, data );
37895  
37896	};
37897  
37898	//
37899  
37900	function toJSON$1( shapes, data ) {
37901  
37902		data.shapes = [];
37903  
37904		if ( Array.isArray( shapes ) ) {
37905  
37906			for ( var i = 0, l = shapes.length; i < l; i ++ ) {
37907  
37908				var shape = shapes[ i ];
37909  
37910				data.shapes.push( shape.uuid );
37911  
37912			}
37913  
37914		} else {
37915  
37916			data.shapes.push( shapes.uuid );
37917  
37918		}
37919  
37920		return data;
37921  
37922	}
37923  
37924	/**
37925	 * @author WestLangley / http://github.com/WestLangley
37926	 * @author Mugen87 / https://github.com/Mugen87
37927	 */
37928  
37929	function EdgesGeometry( geometry, thresholdAngle ) {
37930  
37931		BufferGeometry.call( this );
37932  
37933		this.type = 'EdgesGeometry';
37934  
37935		this.parameters = {
37936			thresholdAngle: thresholdAngle
37937		};
37938  
37939		thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
37940  
37941		// buffer
37942  
37943		var vertices = [];
37944  
37945		// helper variables
37946  
37947		var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
37948		var edge = [ 0, 0 ], edges = {}, edge1, edge2;
37949		var key, keys = [ 'a', 'b', 'c' ];
37950  
37951		// prepare source geometry
37952  
37953		var geometry2;
37954  
37955		if ( geometry.isBufferGeometry ) {
37956  
37957			geometry2 = new Geometry();
37958			geometry2.fromBufferGeometry( geometry );
37959  
37960		} else {
37961  
37962			geometry2 = geometry.clone();
37963  
37964		}
37965  
37966		geometry2.mergeVertices();
37967		geometry2.computeFaceNormals();
37968  
37969		var sourceVertices = geometry2.vertices;
37970		var faces = geometry2.faces;
37971  
37972		// now create a data structure where each entry represents an edge with its adjoining faces
37973  
37974		for ( var i = 0, l = faces.length; i < l; i ++ ) {
37975  
37976			var face = faces[ i ];
37977  
37978			for ( var j = 0; j < 3; j ++ ) {
37979  
37980				edge1 = face[ keys[ j ] ];
37981				edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
37982				edge[ 0 ] = Math.min( edge1, edge2 );
37983				edge[ 1 ] = Math.max( edge1, edge2 );
37984  
37985				key = edge[ 0 ] + ',' + edge[ 1 ];
37986  
37987				if ( edges[ key ] === undefined ) {
37988  
37989					edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
37990  
37991				} else {
37992  
37993					edges[ key ].face2 = i;
37994  
37995				}
37996  
37997			}
37998  
37999		}
38000  
38001		// generate vertices
38002  
38003		for ( key in edges ) {
38004  
38005			var e = edges[ key ];
38006  
38007			// an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
38008  
38009			if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
38010  
38011				var vertex = sourceVertices[ e.index1 ];
38012				vertices.push( vertex.x, vertex.y, vertex.z );
38013  
38014				vertex = sourceVertices[ e.index2 ];
38015				vertices.push( vertex.x, vertex.y, vertex.z );
38016  
38017			}
38018  
38019		}
38020  
38021		// build geometry
38022  
38023		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
38024  
38025	}
38026  
38027	EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
38028	EdgesGeometry.prototype.constructor = EdgesGeometry;
38029  
38030	/**
38031	 * @author mrdoob / http://mrdoob.com/
38032	 * @author Mugen87 / https://github.com/Mugen87
38033	 */
38034  
38035	// CylinderGeometry
38036  
38037	function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
38038  
38039		Geometry.call( this );
38040  
38041		this.type = 'CylinderGeometry';
38042  
38043		this.parameters = {
38044			radiusTop: radiusTop,
38045			radiusBottom: radiusBottom,
38046			height: height,
38047			radialSegments: radialSegments,
38048			heightSegments: heightSegments,
38049			openEnded: openEnded,
38050			thetaStart: thetaStart,
38051			thetaLength: thetaLength
38052		};
38053  
38054		this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
38055		this.mergeVertices();
38056  
38057	}
38058  
38059	CylinderGeometry.prototype = Object.create( Geometry.prototype );
38060	CylinderGeometry.prototype.constructor = CylinderGeometry;
38061  
38062	// CylinderBufferGeometry
38063  
38064	function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
38065  
38066		BufferGeometry.call( this );
38067  
38068		this.type = 'CylinderBufferGeometry';
38069  
38070		this.parameters = {
38071			radiusTop: radiusTop,
38072			radiusBottom: radiusBottom,
38073			height: height,
38074			radialSegments: radialSegments,
38075			heightSegments: heightSegments,
38076			openEnded: openEnded,
38077			thetaStart: thetaStart,
38078			thetaLength: thetaLength
38079		};
38080  
38081		var scope = this;
38082  
38083		radiusTop = radiusTop !== undefined ? radiusTop : 1;
38084		radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
38085		height = height || 1;
38086  
38087		radialSegments = Math.floor( radialSegments ) || 8;
38088		heightSegments = Math.floor( heightSegments ) || 1;
38089  
38090		openEnded = openEnded !== undefined ? openEnded : false;
38091		thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
38092		thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
38093  
38094		// buffers
38095  
38096		var indices = [];
38097		var vertices = [];
38098		var normals = [];
38099		var uvs = [];
38100  
38101		// helper variables
38102  
38103		var index = 0;
38104		var indexArray = [];
38105		var halfHeight = height / 2;
38106		var groupStart = 0;
38107  
38108		// generate geometry
38109  
38110		generateTorso();
38111  
38112		if ( openEnded === false ) {
38113  
38114			if ( radiusTop > 0 ) generateCap( true );
38115			if ( radiusBottom > 0 ) generateCap( false );
38116  
38117		}
38118  
38119		// build geometry
38120  
38121		this.setIndex( indices );
38122		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
38123		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
38124		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
38125  
38126		function generateTorso() {
38127  
38128			var x, y;
38129			var normal = new Vector3();
38130			var vertex = new Vector3();
38131  
38132			var groupCount = 0;
38133  
38134			// this will be used to calculate the normal
38135			var slope = ( radiusBottom - radiusTop ) / height;
38136  
38137			// generate vertices, normals and uvs
38138  
38139			for ( y = 0; y <= heightSegments; y ++ ) {
38140  
38141				var indexRow = [];
38142  
38143				var v = y / heightSegments;
38144  
38145				// calculate the radius of the current row
38146  
38147				var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
38148  
38149				for ( x = 0; x <= radialSegments; x ++ ) {
38150  
38151					var u = x / radialSegments;
38152  
38153					var theta = u * thetaLength + thetaStart;
38154  
38155					var sinTheta = Math.sin( theta );
38156					var cosTheta = Math.cos( theta );
38157  
38158					// vertex
38159  
38160					vertex.x = radius * sinTheta;
38161					vertex.y = - v * height + halfHeight;
38162					vertex.z = radius * cosTheta;
38163					vertices.push( vertex.x, vertex.y, vertex.z );
38164  
38165					// normal
38166  
38167					normal.set( sinTheta, slope, cosTheta ).normalize();
38168					normals.push( normal.x, normal.y, normal.z );
38169  
38170					// uv
38171  
38172					uvs.push( u, 1 - v );
38173  
38174					// save index of vertex in respective row
38175  
38176					indexRow.push( index ++ );
38177  
38178				}
38179  
38180				// now save vertices of the row in our index array
38181  
38182				indexArray.push( indexRow );
38183  
38184			}
38185  
38186			// generate indices
38187  
38188			for ( x = 0; x < radialSegments; x ++ ) {
38189  
38190				for ( y = 0; y < heightSegments; y ++ ) {
38191  
38192					// we use the index array to access the correct indices
38193  
38194					var a = indexArray[ y ][ x ];
38195					var b = indexArray[ y + 1 ][ x ];
38196					var c = indexArray[ y + 1 ][ x + 1 ];
38197					var d = indexArray[ y ][ x + 1 ];
38198  
38199					// faces
38200  
38201					indices.push( a, b, d );
38202					indices.push( b, c, d );
38203  
38204					// update group counter
38205  
38206					groupCount += 6;
38207  
38208				}
38209  
38210			}
38211  
38212			// add a group to the geometry. this will ensure multi material support
38213  
38214			scope.addGroup( groupStart, groupCount, 0 );
38215  
38216			// calculate new start value for groups
38217  
38218			groupStart += groupCount;
38219  
38220		}
38221  
38222		function generateCap( top ) {
38223  
38224			var x, centerIndexStart, centerIndexEnd;
38225  
38226			var uv = new Vector2();
38227			var vertex = new Vector3();
38228  
38229			var groupCount = 0;
38230  
38231			var radius = ( top === true ) ? radiusTop : radiusBottom;
38232			var sign = ( top === true ) ? 1 : - 1;
38233  
38234			// save the index of the first center vertex
38235			centerIndexStart = index;
38236  
38237			// first we generate the center vertex data of the cap.
38238			// because the geometry needs one set of uvs per face,
38239			// we must generate a center vertex per face/segment
38240  
38241			for ( x = 1; x <= radialSegments; x ++ ) {
38242  
38243				// vertex
38244  
38245				vertices.push( 0, halfHeight * sign, 0 );
38246  
38247				// normal
38248  
38249				normals.push( 0, sign, 0 );
38250  
38251				// uv
38252  
38253				uvs.push( 0.5, 0.5 );
38254  
38255				// increase index
38256  
38257				index ++;
38258  
38259			}
38260  
38261			// save the index of the last center vertex
38262  
38263			centerIndexEnd = index;
38264  
38265			// now we generate the surrounding vertices, normals and uvs
38266  
38267			for ( x = 0; x <= radialSegments; x ++ ) {
38268  
38269				var u = x / radialSegments;
38270				var theta = u * thetaLength + thetaStart;
38271  
38272				var cosTheta = Math.cos( theta );
38273				var sinTheta = Math.sin( theta );
38274  
38275				// vertex
38276  
38277				vertex.x = radius * sinTheta;
38278				vertex.y = halfHeight * sign;
38279				vertex.z = radius * cosTheta;
38280				vertices.push( vertex.x, vertex.y, vertex.z );
38281  
38282				// normal
38283  
38284				normals.push( 0, sign, 0 );
38285  
38286				// uv
38287  
38288				uv.x = ( cosTheta * 0.5 ) + 0.5;
38289				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
38290				uvs.push( uv.x, uv.y );
38291  
38292				// increase index
38293  
38294				index ++;
38295  
38296			}
38297  
38298			// generate indices
38299  
38300			for ( x = 0; x < radialSegments; x ++ ) {
38301  
38302				var c = centerIndexStart + x;
38303				var i = centerIndexEnd + x;
38304  
38305				if ( top === true ) {
38306  
38307					// face top
38308  
38309					indices.push( i, i + 1, c );
38310  
38311				} else {
38312  
38313					// face bottom
38314  
38315					indices.push( i + 1, i, c );
38316  
38317				}
38318  
38319				groupCount += 3;
38320  
38321			}
38322  
38323			// add a group to the geometry. this will ensure multi material support
38324  
38325			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
38326  
38327			// calculate new start value for groups
38328  
38329			groupStart += groupCount;
38330  
38331		}
38332  
38333	}
38334  
38335	CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
38336	CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
38337  
38338	/**
38339	 * @author abelnation / http://github.com/abelnation
38340	 */
38341  
38342	// ConeGeometry
38343  
38344	function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
38345  
38346		CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
38347  
38348		this.type = 'ConeGeometry';
38349  
38350		this.parameters = {
38351			radius: radius,
38352			height: height,
38353			radialSegments: radialSegments,
38354			heightSegments: heightSegments,
38355			openEnded: openEnded,
38356			thetaStart: thetaStart,
38357			thetaLength: thetaLength
38358		};
38359  
38360	}
38361  
38362	ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
38363	ConeGeometry.prototype.constructor = ConeGeometry;
38364  
38365	// ConeBufferGeometry
38366  
38367	function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
38368  
38369		CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
38370  
38371		this.type = 'ConeBufferGeometry';
38372  
38373		this.parameters = {
38374			radius: radius,
38375			height: height,
38376			radialSegments: radialSegments,
38377			heightSegments: heightSegments,
38378			openEnded: openEnded,
38379			thetaStart: thetaStart,
38380			thetaLength: thetaLength
38381		};
38382  
38383	}
38384  
38385	ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
38386	ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
38387  
38388	/**
38389	 * @author benaadams / https://twitter.com/ben_a_adams
38390	 * @author Mugen87 / https://github.com/Mugen87
38391	 * @author hughes
38392	 */
38393  
38394	// CircleGeometry
38395  
38396	function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
38397  
38398		Geometry.call( this );
38399  
38400		this.type = 'CircleGeometry';
38401  
38402		this.parameters = {
38403			radius: radius,
38404			segments: segments,
38405			thetaStart: thetaStart,
38406			thetaLength: thetaLength
38407		};
38408  
38409		this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
38410		this.mergeVertices();
38411  
38412	}
38413  
38414	CircleGeometry.prototype = Object.create( Geometry.prototype );
38415	CircleGeometry.prototype.constructor = CircleGeometry;
38416  
38417	// CircleBufferGeometry
38418  
38419	function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
38420  
38421		BufferGeometry.call( this );
38422  
38423		this.type = 'CircleBufferGeometry';
38424  
38425		this.parameters = {
38426			radius: radius,
38427			segments: segments,
38428			thetaStart: thetaStart,
38429			thetaLength: thetaLength
38430		};
38431  
38432		radius = radius || 1;
38433		segments = segments !== undefined ? Math.max( 3, segments ) : 8;
38434  
38435		thetaStart = thetaStart !== undefined ? thetaStart : 0;
38436		thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
38437  
38438		// buffers
38439  
38440		var indices = [];
38441		var vertices = [];
38442		var normals = [];
38443		var uvs = [];
38444  
38445		// helper variables
38446  
38447		var i, s;
38448		var vertex = new Vector3();
38449		var uv = new Vector2();
38450  
38451		// center point
38452  
38453		vertices.push( 0, 0, 0 );
38454		normals.push( 0, 0, 1 );
38455		uvs.push( 0.5, 0.5 );
38456  
38457		for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
38458  
38459			var segment = thetaStart + s / segments * thetaLength;
38460  
38461			// vertex
38462  
38463			vertex.x = radius * Math.cos( segment );
38464			vertex.y = radius * Math.sin( segment );
38465  
38466			vertices.push( vertex.x, vertex.y, vertex.z );
38467  
38468			// normal
38469  
38470			normals.push( 0, 0, 1 );
38471  
38472			// uvs
38473  
38474			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
38475			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
38476  
38477			uvs.push( uv.x, uv.y );
38478  
38479		}
38480  
38481		// indices
38482  
38483		for ( i = 1; i <= segments; i ++ ) {
38484  
38485			indices.push( i, i + 1, 0 );
38486  
38487		}
38488  
38489		// build geometry
38490  
38491		this.setIndex( indices );
38492		this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
38493		this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
38494		this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
38495  
38496	}
38497  
38498	CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
38499	CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
38500  
38501  
38502  
38503	var Geometries = /*#__PURE__*/Object.freeze({
38504		WireframeGeometry: WireframeGeometry,
38505		ParametricGeometry: ParametricGeometry,
38506		ParametricBufferGeometry: ParametricBufferGeometry,
38507		TetrahedronGeometry: TetrahedronGeometry,
38508		TetrahedronBufferGeometry: TetrahedronBufferGeometry,
38509		OctahedronGeometry: OctahedronGeometry,
38510		OctahedronBufferGeometry: OctahedronBufferGeometry,
38511		IcosahedronGeometry: IcosahedronGeometry,
38512		IcosahedronBufferGeometry: IcosahedronBufferGeometry,
38513		DodecahedronGeometry: DodecahedronGeometry,
38514		DodecahedronBufferGeometry: DodecahedronBufferGeometry,
38515		PolyhedronGeometry: PolyhedronGeometry,
38516		PolyhedronBufferGeometry: PolyhedronBufferGeometry,
38517		TubeGeometry: TubeGeometry,
38518		TubeBufferGeometry: TubeBufferGeometry,
38519		TorusKnotGeometry: TorusKnotGeometry,
38520		TorusKnotBufferGeometry: TorusKnotBufferGeometry,
38521		TorusGeometry: TorusGeometry,
38522		TorusBufferGeometry: TorusBufferGeometry,
38523		TextGeometry: TextGeometry,
38524		TextBufferGeometry: TextBufferGeometry,
38525		SphereGeometry: SphereGeometry,
38526		SphereBufferGeometry: SphereBufferGeometry,
38527		RingGeometry: RingGeometry,
38528		RingBufferGeometry: RingBufferGeometry,
38529		PlaneGeometry: PlaneGeometry,
38530		PlaneBufferGeometry: PlaneBufferGeometry,
38531		LatheGeometry: LatheGeometry,
38532		LatheBufferGeometry: LatheBufferGeometry,
38533		ShapeGeometry: ShapeGeometry,
38534		ShapeBufferGeometry: ShapeBufferGeometry,
38535		ExtrudeGeometry: ExtrudeGeometry,
38536		ExtrudeBufferGeometry: ExtrudeBufferGeometry,
38537		EdgesGeometry: EdgesGeometry,
38538		ConeGeometry: ConeGeometry,
38539		ConeBufferGeometry: ConeBufferGeometry,
38540		CylinderGeometry: CylinderGeometry,
38541		CylinderBufferGeometry: CylinderBufferGeometry,
38542		CircleGeometry: CircleGeometry,
38543		CircleBufferGeometry: CircleBufferGeometry,
38544		BoxGeometry: BoxGeometry,
38545		BoxBufferGeometry: BoxBufferGeometry
38546	});
38547  
38548	/**
38549	 * @author mrdoob / http://mrdoob.com/
38550	 *
38551	 * parameters = {
38552	 *  color: <THREE.Color>
38553	 * }
38554	 */
38555  
38556	function ShadowMaterial( parameters ) {
38557  
38558		Material.call( this );
38559  
38560		this.type = 'ShadowMaterial';
38561  
38562		this.color = new Color( 0x000000 );
38563		this.transparent = true;
38564  
38565		this.setValues( parameters );
38566  
38567	}
38568  
38569	ShadowMaterial.prototype = Object.create( Material.prototype );
38570	ShadowMaterial.prototype.constructor = ShadowMaterial;
38571  
38572	ShadowMaterial.prototype.isShadowMaterial = true;
38573  
38574	ShadowMaterial.prototype.copy = function ( source ) {
38575  
38576		Material.prototype.copy.call( this, source );
38577  
38578		this.color.copy( source.color );
38579  
38580		return this;
38581  
38582	};
38583  
38584	/**
38585	 * @author mrdoob / http://mrdoob.com/
38586	 */
38587  
38588	function RawShaderMaterial( parameters ) {
38589  
38590		ShaderMaterial.call( this, parameters );
38591  
38592		this.type = 'RawShaderMaterial';
38593  
38594	}
38595  
38596	RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
38597	RawShaderMaterial.prototype.constructor = RawShaderMaterial;
38598  
38599	RawShaderMaterial.prototype.isRawShaderMaterial = true;
38600  
38601	/**
38602	 * @author WestLangley / http://github.com/WestLangley
38603	 *
38604	 * parameters = {
38605	 *  color: <hex>,
38606	 *  roughness: <float>,
38607	 *  metalness: <float>,
38608	 *  opacity: <float>,
38609	 *
38610	 *  map: new THREE.Texture( <Image> ),
38611	 *
38612	 *  lightMap: new THREE.Texture( <Image> ),
38613	 *  lightMapIntensity: <float>
38614	 *
38615	 *  aoMap: new THREE.Texture( <Image> ),
38616	 *  aoMapIntensity: <float>
38617	 *
38618	 *  emissive: <hex>,
38619	 *  emissiveIntensity: <float>
38620	 *  emissiveMap: new THREE.Texture( <Image> ),
38621	 *
38622	 *  bumpMap: new THREE.Texture( <Image> ),
38623	 *  bumpScale: <float>,
38624	 *
38625	 *  normalMap: new THREE.Texture( <Image> ),
38626	 *  normalScale: <Vector2>,
38627	 *
38628	 *  displacementMap: new THREE.Texture( <Image> ),
38629	 *  displacementScale: <float>,
38630	 *  displacementBias: <float>,
38631	 *
38632	 *  roughnessMap: new THREE.Texture( <Image> ),
38633	 *
38634	 *  metalnessMap: new THREE.Texture( <Image> ),
38635	 *
38636	 *  alphaMap: new THREE.Texture( <Image> ),
38637	 *
38638	 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
38639	 *  envMapIntensity: <float>
38640	 *
38641	 *  refractionRatio: <float>,
38642	 *
38643	 *  wireframe: <boolean>,
38644	 *  wireframeLinewidth: <float>,
38645	 *
38646	 *  skinning: <bool>,
38647	 *  morphTargets: <bool>,
38648	 *  morphNormals: <bool>
38649	 * }
38650	 */
38651  
38652	function MeshStandardMaterial( parameters ) {
38653  
38654		Material.call( this );
38655  
38656		this.defines = { 'STANDARD': '' };
38657  
38658		this.type = 'MeshStandardMaterial';
38659  
38660		this.color = new Color( 0xffffff ); // diffuse
38661		this.roughness = 0.5;
38662		this.metalness = 0.5;
38663  
38664		this.map = null;
38665  
38666		this.lightMap = null;
38667		this.lightMapIntensity = 1.0;
38668  
38669		this.aoMap = null;
38670		this.aoMapIntensity = 1.0;
38671  
38672		this.emissive = new Color( 0x000000 );
38673		this.emissiveIntensity = 1.0;
38674		this.emissiveMap = null;
38675  
38676		this.bumpMap = null;
38677		this.bumpScale = 1;
38678  
38679		this.normalMap = null;
38680		this.normalScale = new Vector2( 1, 1 );
38681  
38682		this.displacementMap = null;
38683		this.displacementScale = 1;
38684		this.displacementBias = 0;
38685  
38686		this.roughnessMap = null;
38687  
38688		this.metalnessMap = null;
38689  
38690		this.alphaMap = null;
38691  
38692		this.envMap = null;
38693		this.envMapIntensity = 1.0;
38694  
38695		this.refractionRatio = 0.98;
38696  
38697		this.wireframe = false;
38698		this.wireframeLinewidth = 1;
38699		this.wireframeLinecap = 'round';
38700		this.wireframeLinejoin = 'round';
38701  
38702		this.skinning = false;
38703		this.morphTargets = false;
38704		this.morphNormals = false;
38705  
38706		this.setValues( parameters );
38707  
38708	}
38709  
38710	MeshStandardMaterial.prototype = Object.create( Material.prototype );
38711	MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
38712  
38713	MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
38714  
38715	MeshStandardMaterial.prototype.copy = function ( source ) {
38716  
38717		Material.prototype.copy.call( this, source );
38718  
38719		this.defines = { 'STANDARD': '' };
38720  
38721		this.color.copy( source.color );
38722		this.roughness = source.roughness;
38723		this.metalness = source.metalness;
38724  
38725		this.map = source.map;
38726  
38727		this.lightMap = source.lightMap;
38728		this.lightMapIntensity = source.lightMapIntensity;
38729  
38730		this.aoMap = source.aoMap;
38731		this.aoMapIntensity = source.aoMapIntensity;
38732  
38733		this.emissive.copy( source.emissive );
38734		this.emissiveMap = source.emissiveMap;
38735		this.emissiveIntensity = source.emissiveIntensity;
38736  
38737		this.bumpMap = source.bumpMap;
38738		this.bumpScale = source.bumpScale;
38739  
38740		this.normalMap = source.normalMap;
38741		this.normalScale.copy( source.normalScale );
38742  
38743		this.displacementMap = source.displacementMap;
38744		this.displacementScale = source.displacementScale;
38745		this.displacementBias = source.displacementBias;
38746  
38747		this.roughnessMap = source.roughnessMap;
38748  
38749		this.metalnessMap = source.metalnessMap;
38750  
38751		this.alphaMap = source.alphaMap;
38752  
38753		this.envMap = source.envMap;
38754		this.envMapIntensity = source.envMapIntensity;
38755  
38756		this.refractionRatio = source.refractionRatio;
38757  
38758		this.wireframe = source.wireframe;
38759		this.wireframeLinewidth = source.wireframeLinewidth;
38760		this.wireframeLinecap = source.wireframeLinecap;
38761		this.wireframeLinejoin = source.wireframeLinejoin;
38762  
38763		this.skinning = source.skinning;
38764		this.morphTargets = source.morphTargets;
38765		this.morphNormals = source.morphNormals;
38766  
38767		return this;
38768  
38769	};
38770  
38771	/**
38772	 * @author WestLangley / http://github.com/WestLangley
38773	 *
38774	 * parameters = {
38775	 *  reflectivity: <float>
38776	 * }
38777	 */
38778  
38779	function MeshPhysicalMaterial( parameters ) {
38780  
38781		MeshStandardMaterial.call( this );
38782  
38783		this.defines = { 'PHYSICAL': '' };
38784  
38785		this.type = 'MeshPhysicalMaterial';
38786  
38787		this.reflectivity = 0.5; // maps to F0 = 0.04
38788  
38789		this.clearCoat = 0.0;
38790		this.clearCoatRoughness = 0.0;
38791  
38792		this.setValues( parameters );
38793  
38794	}
38795  
38796	MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
38797	MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
38798  
38799	MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
38800  
38801	MeshPhysicalMaterial.prototype.copy = function ( source ) {
38802  
38803		MeshStandardMaterial.prototype.copy.call( this, source );
38804  
38805		this.defines = { 'PHYSICAL': '' };
38806  
38807		this.reflectivity = source.reflectivity;
38808  
38809		this.clearCoat = source.clearCoat;
38810		this.clearCoatRoughness = source.clearCoatRoughness;
38811  
38812		return this;
38813  
38814	};
38815  
38816	/**
38817	 * @author mrdoob / http://mrdoob.com/
38818	 * @author alteredq / http://alteredqualia.com/
38819	 *
38820	 * parameters = {
38821	 *  color: <hex>,
38822	 *  specular: <hex>,
38823	 *  shininess: <float>,
38824	 *  opacity: <float>,
38825	 *
38826	 *  map: new THREE.Texture( <Image> ),
38827	 *
38828	 *  lightMap: new THREE.Texture( <Image> ),
38829	 *  lightMapIntensity: <float>
38830	 *
38831	 *  aoMap: new THREE.Texture( <Image> ),
38832	 *  aoMapIntensity: <float>
38833	 *
38834	 *  emissive: <hex>,
38835	 *  emissiveIntensity: <float>
38836	 *  emissiveMap: new THREE.Texture( <Image> ),
38837	 *
38838	 *  bumpMap: new THREE.Texture( <Image> ),
38839	 *  bumpScale: <float>,
38840	 *
38841	 *  normalMap: new THREE.Texture( <Image> ),
38842	 *  normalScale: <Vector2>,
38843	 *
38844	 *  displacementMap: new THREE.Texture( <Image> ),
38845	 *  displacementScale: <float>,
38846	 *  displacementBias: <float>,
38847	 *
38848	 *  specularMap: new THREE.Texture( <Image> ),
38849	 *
38850	 *  alphaMap: new THREE.Texture( <Image> ),
38851	 *
38852	 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
38853	 *  combine: THREE.Multiply,
38854	 *  reflectivity: <float>,
38855	 *  refractionRatio: <float>,
38856	 *
38857	 *  wireframe: <boolean>,
38858	 *  wireframeLinewidth: <float>,
38859	 *
38860	 *  skinning: <bool>,
38861	 *  morphTargets: <bool>,
38862	 *  morphNormals: <bool>
38863	 * }
38864	 */
38865  
38866	function MeshPhongMaterial( parameters ) {
38867  
38868		Material.call( this );
38869  
38870		this.type = 'MeshPhongMaterial';
38871  
38872		this.color = new Color( 0xffffff ); // diffuse
38873		this.specular = new Color( 0x111111 );
38874		this.shininess = 30;
38875  
38876		this.map = null;
38877  
38878		this.lightMap = null;
38879		this.lightMapIntensity = 1.0;
38880  
38881		this.aoMap = null;
38882		this.aoMapIntensity = 1.0;
38883  
38884		this.emissive = new Color( 0x000000 );
38885		this.emissiveIntensity = 1.0;
38886		this.emissiveMap = null;
38887  
38888		this.bumpMap = null;
38889		this.bumpScale = 1;
38890  
38891		this.normalMap = null;
38892		this.normalScale = new Vector2( 1, 1 );
38893  
38894		this.displacementMap = null;
38895		this.displacementScale = 1;
38896		this.displacementBias = 0;
38897  
38898		this.specularMap = null;
38899  
38900		this.alphaMap = null;
38901  
38902		this.envMap = null;
38903		this.combine = MultiplyOperation;
38904		this.reflectivity = 1;
38905		this.refractionRatio = 0.98;
38906  
38907		this.wireframe = false;
38908		this.wireframeLinewidth = 1;
38909		this.wireframeLinecap = 'round';
38910		this.wireframeLinejoin = 'round';
38911  
38912		this.skinning = false;
38913		this.morphTargets = false;
38914		this.morphNormals = false;
38915  
38916		this.setValues( parameters );
38917  
38918	}
38919  
38920	MeshPhongMaterial.prototype = Object.create( Material.prototype );
38921	MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
38922  
38923	MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
38924  
38925	MeshPhongMaterial.prototype.copy = function ( source ) {
38926  
38927		Material.prototype.copy.call( this, source );
38928  
38929		this.color.copy( source.color );
38930		this.specular.copy( source.specular );
38931		this.shininess = source.shininess;
38932  
38933		this.map = source.map;
38934  
38935		this.lightMap = source.lightMap;
38936		this.lightMapIntensity = source.lightMapIntensity;
38937  
38938		this.aoMap = source.aoMap;
38939		this.aoMapIntensity = source.aoMapIntensity;
38940  
38941		this.emissive.copy( source.emissive );
38942		this.emissiveMap = source.emissiveMap;
38943		this.emissiveIntensity = source.emissiveIntensity;
38944  
38945		this.bumpMap = source.bumpMap;
38946		this.bumpScale = source.bumpScale;
38947  
38948		this.normalMap = source.normalMap;
38949		this.normalScale.copy( source.normalScale );
38950  
38951		this.displacementMap = source.displacementMap;
38952		this.displacementScale = source.displacementScale;
38953		this.displacementBias = source.displacementBias;
38954  
38955		this.specularMap = source.specularMap;
38956  
38957		this.alphaMap = source.alphaMap;
38958  
38959		this.envMap = source.envMap;
38960		this.combine = source.combine;
38961		this.reflectivity = source.reflectivity;
38962		this.refractionRatio = source.refractionRatio;
38963  
38964		this.wireframe = source.wireframe;
38965		this.wireframeLinewidth = source.wireframeLinewidth;
38966		this.wireframeLinecap = source.wireframeLinecap;
38967		this.wireframeLinejoin = source.wireframeLinejoin;
38968  
38969		this.skinning = source.skinning;
38970		this.morphTargets = source.morphTargets;
38971		this.morphNormals = source.morphNormals;
38972  
38973		return this;
38974  
38975	};
38976  
38977	/**
38978	 * @author takahirox / http://github.com/takahirox
38979	 *
38980	 * parameters = {
38981	 *  gradientMap: new THREE.Texture( <Image> )
38982	 * }
38983	 */
38984  
38985	function MeshToonMaterial( parameters ) {
38986  
38987		MeshPhongMaterial.call( this );
38988  
38989		this.defines = { 'TOON': '' };
38990  
38991		this.type = 'MeshToonMaterial';
38992  
38993		this.gradientMap = null;
38994  
38995		this.setValues( parameters );
38996  
38997	}
38998  
38999	MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
39000	MeshToonMaterial.prototype.constructor = MeshToonMaterial;
39001  
39002	MeshToonMaterial.prototype.isMeshToonMaterial = true;
39003  
39004	MeshToonMaterial.prototype.copy = function ( source ) {
39005  
39006		MeshPhongMaterial.prototype.copy.call( this, source );
39007  
39008		this.gradientMap = source.gradientMap;
39009  
39010		return this;
39011  
39012	};
39013  
39014	/**
39015	 * @author mrdoob / http://mrdoob.com/
39016	 * @author WestLangley / http://github.com/WestLangley
39017	 *
39018	 * parameters = {
39019	 *  opacity: <float>,
39020	 *
39021	 *  bumpMap: new THREE.Texture( <Image> ),
39022	 *  bumpScale: <float>,
39023	 *
39024	 *  normalMap: new THREE.Texture( <Image> ),
39025	 *  normalScale: <Vector2>,
39026	 *
39027	 *  displacementMap: new THREE.Texture( <Image> ),
39028	 *  displacementScale: <float>,
39029	 *  displacementBias: <float>,
39030	 *
39031	 *  wireframe: <boolean>,
39032	 *  wireframeLinewidth: <float>
39033	 *
39034	 *  skinning: <bool>,
39035	 *  morphTargets: <bool>,
39036	 *  morphNormals: <bool>
39037	 * }
39038	 */
39039  
39040	function MeshNormalMaterial( parameters ) {
39041  
39042		Material.call( this );
39043  
39044		this.type = 'MeshNormalMaterial';
39045  
39046		this.bumpMap = null;
39047		this.bumpScale = 1;
39048  
39049		this.normalMap = null;
39050		this.normalScale = new Vector2( 1, 1 );
39051  
39052		this.displacementMap = null;
39053		this.displacementScale = 1;
39054		this.displacementBias = 0;
39055  
39056		this.wireframe = false;
39057		this.wireframeLinewidth = 1;
39058  
39059		this.fog = false;
39060		this.lights = false;
39061  
39062		this.skinning = false;
39063		this.morphTargets = false;
39064		this.morphNormals = false;
39065  
39066		this.setValues( parameters );
39067  
39068	}
39069  
39070	MeshNormalMaterial.prototype = Object.create( Material.prototype );
39071	MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
39072  
39073	MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
39074  
39075	MeshNormalMaterial.prototype.copy = function ( source ) {
39076  
39077		Material.prototype.copy.call( this, source );
39078  
39079		this.bumpMap = source.bumpMap;
39080		this.bumpScale = source.bumpScale;
39081  
39082		this.normalMap = source.normalMap;
39083		this.normalScale.copy( source.normalScale );
39084  
39085		this.displacementMap = source.displacementMap;
39086		this.displacementScale = source.displacementScale;
39087		this.displacementBias = source.displacementBias;
39088  
39089		this.wireframe = source.wireframe;
39090		this.wireframeLinewidth = source.wireframeLinewidth;
39091  
39092		this.skinning = source.skinning;
39093		this.morphTargets = source.morphTargets;
39094		this.morphNormals = source.morphNormals;
39095  
39096		return this;
39097  
39098	};
39099  
39100	/**
39101	 * @author mrdoob / http://mrdoob.com/
39102	 * @author alteredq / http://alteredqualia.com/
39103	 *
39104	 * parameters = {
39105	 *  color: <hex>,
39106	 *  opacity: <float>,
39107	 *
39108	 *  map: new THREE.Texture( <Image> ),
39109	 *
39110	 *  lightMap: new THREE.Texture( <Image> ),
39111	 *  lightMapIntensity: <float>
39112	 *
39113	 *  aoMap: new THREE.Texture( <Image> ),
39114	 *  aoMapIntensity: <float>
39115	 *
39116	 *  emissive: <hex>,
39117	 *  emissiveIntensity: <float>
39118	 *  emissiveMap: new THREE.Texture( <Image> ),
39119	 *
39120	 *  specularMap: new THREE.Texture( <Image> ),
39121	 *
39122	 *  alphaMap: new THREE.Texture( <Image> ),
39123	 *
39124	 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
39125	 *  combine: THREE.Multiply,
39126	 *  reflectivity: <float>,
39127	 *  refractionRatio: <float>,
39128	 *
39129	 *  wireframe: <boolean>,
39130	 *  wireframeLinewidth: <float>,
39131	 *
39132	 *  skinning: <bool>,
39133	 *  morphTargets: <bool>,
39134	 *  morphNormals: <bool>
39135	 * }
39136	 */
39137  
39138	function MeshLambertMaterial( parameters ) {
39139  
39140		Material.call( this );
39141  
39142		this.type = 'MeshLambertMaterial';
39143  
39144		this.color = new Color( 0xffffff ); // diffuse
39145  
39146		this.map = null;
39147  
39148		this.lightMap = null;
39149		this.lightMapIntensity = 1.0;
39150  
39151		this.aoMap = null;
39152		this.aoMapIntensity = 1.0;
39153  
39154		this.emissive = new Color( 0x000000 );
39155		this.emissiveIntensity = 1.0;
39156		this.emissiveMap = null;
39157  
39158		this.specularMap = null;
39159  
39160		this.alphaMap = null;
39161  
39162		this.envMap = null;
39163		this.combine = MultiplyOperation;
39164		this.reflectivity = 1;
39165		this.refractionRatio = 0.98;
39166  
39167		this.wireframe = false;
39168		this.wireframeLinewidth = 1;
39169		this.wireframeLinecap = 'round';
39170		this.wireframeLinejoin = 'round';
39171  
39172		this.skinning = false;
39173		this.morphTargets = false;
39174		this.morphNormals = false;
39175  
39176		this.setValues( parameters );
39177  
39178	}
39179  
39180	MeshLambertMaterial.prototype = Object.create( Material.prototype );
39181	MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
39182  
39183	MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
39184  
39185	MeshLambertMaterial.prototype.copy = function ( source ) {
39186  
39187		Material.prototype.copy.call( this, source );
39188  
39189		this.color.copy( source.color );
39190  
39191		this.map = source.map;
39192  
39193		this.lightMap = source.lightMap;
39194		this.lightMapIntensity = source.lightMapIntensity;
39195  
39196		this.aoMap = source.aoMap;
39197		this.aoMapIntensity = source.aoMapIntensity;
39198  
39199		this.emissive.copy( source.emissive );
39200		this.emissiveMap = source.emissiveMap;
39201		this.emissiveIntensity = source.emissiveIntensity;
39202  
39203		this.specularMap = source.specularMap;
39204  
39205		this.alphaMap = source.alphaMap;
39206  
39207		this.envMap = source.envMap;
39208		this.combine = source.combine;
39209		this.reflectivity = source.reflectivity;
39210		this.refractionRatio = source.refractionRatio;
39211  
39212		this.wireframe = source.wireframe;
39213		this.wireframeLinewidth = source.wireframeLinewidth;
39214		this.wireframeLinecap = source.wireframeLinecap;
39215		this.wireframeLinejoin = source.wireframeLinejoin;
39216  
39217		this.skinning = source.skinning;
39218		this.morphTargets = source.morphTargets;
39219		this.morphNormals = source.morphNormals;
39220  
39221		return this;
39222  
39223	};
39224  
39225	/**
39226	 * @author alteredq / http://alteredqualia.com/
39227	 *
39228	 * parameters = {
39229	 *  color: <hex>,
39230	 *  opacity: <float>,
39231	 *
39232	 *  linewidth: <float>,
39233	 *
39234	 *  scale: <float>,
39235	 *  dashSize: <float>,
39236	 *  gapSize: <float>
39237	 * }
39238	 */
39239  
39240	function LineDashedMaterial( parameters ) {
39241  
39242		LineBasicMaterial.call( this );
39243  
39244		this.type = 'LineDashedMaterial';
39245  
39246		this.scale = 1;
39247		this.dashSize = 3;
39248		this.gapSize = 1;
39249  
39250		this.setValues( parameters );
39251  
39252	}
39253  
39254	LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
39255	LineDashedMaterial.prototype.constructor = LineDashedMaterial;
39256  
39257	LineDashedMaterial.prototype.isLineDashedMaterial = true;
39258  
39259	LineDashedMaterial.prototype.copy = function ( source ) {
39260  
39261		LineBasicMaterial.prototype.copy.call( this, source );
39262  
39263		this.scale = source.scale;
39264		this.dashSize = source.dashSize;
39265		this.gapSize = source.gapSize;
39266  
39267		return this;
39268  
39269	};
39270  
39271  
39272  
39273	var Materials = /*#__PURE__*/Object.freeze({
39274		ShadowMaterial: ShadowMaterial,
39275		SpriteMaterial: SpriteMaterial,
39276		RawShaderMaterial: RawShaderMaterial,
39277		ShaderMaterial: ShaderMaterial,
39278		PointsMaterial: PointsMaterial,
39279		MeshPhysicalMaterial: MeshPhysicalMaterial,
39280		MeshStandardMaterial: MeshStandardMaterial,
39281		MeshPhongMaterial: MeshPhongMaterial,
39282		MeshToonMaterial: MeshToonMaterial,
39283		MeshNormalMaterial: MeshNormalMaterial,
39284		MeshLambertMaterial: MeshLambertMaterial,
39285		MeshDepthMaterial: MeshDepthMaterial,
39286		MeshDistanceMaterial: MeshDistanceMaterial,
39287		MeshBasicMaterial: MeshBasicMaterial,
39288		LineDashedMaterial: LineDashedMaterial,
39289		LineBasicMaterial: LineBasicMaterial,
39290		Material: Material
39291	});
39292  
39293	/**
39294	 * @author mrdoob / http://mrdoob.com/
39295	 */
39296  
39297	var Cache = {
39298  
39299		enabled: false,
39300  
39301		files: {},
39302  
39303		add: function ( key, file ) {
39304  
39305			if ( this.enabled === false ) return;
39306  
vendor: 10,683 bytes, lines 39307-39876
39307			// console.log( 'THREE.Cache', 'Adding key:', key );
39308  
39309			this.files[ key ] = file;
39310  
39311		},
39312  
39313		get: function ( key ) {
39314  
39315			if ( this.enabled === false ) return;
39316  
39317			// console.log( 'THREE.Cache', 'Checking key:', key );
39318  
39319			return this.files[ key ];
39320  
39321		},
39322  
39323		remove: function ( key ) {
39324  
39325			delete this.files[ key ];
39326  
39327		},
39328  
39329		clear: function () {
39330  
39331			this.files = {};
39332  
39333		}
39334  
39335	};
39336  
39337	/**
39338	 * @author mrdoob / http://mrdoob.com/
39339	 */
39340  
39341	function LoadingManager( onLoad, onProgress, onError ) {
39342  
39343		var scope = this;
39344  
39345		var isLoading = false;
39346		var itemsLoaded = 0;
39347		var itemsTotal = 0;
39348		var urlModifier = undefined;
39349  
39350		this.onStart = undefined;
39351		this.onLoad = onLoad;
39352		this.onProgress = onProgress;
39353		this.onError = onError;
39354  
39355		this.itemStart = function ( url ) {
39356  
39357			itemsTotal ++;
39358  
39359			if ( isLoading === false ) {
39360  
39361				if ( scope.onStart !== undefined ) {
39362  
39363					scope.onStart( url, itemsLoaded, itemsTotal );
39364  
39365				}
39366  
39367			}
39368  
39369			isLoading = true;
39370  
39371		};
39372  
39373		this.itemEnd = function ( url ) {
39374  
39375			itemsLoaded ++;
39376  
39377			if ( scope.onProgress !== undefined ) {
39378  
39379				scope.onProgress( url, itemsLoaded, itemsTotal );
39380  
39381			}
39382  
39383			if ( itemsLoaded === itemsTotal ) {
39384  
39385				isLoading = false;
39386  
39387				if ( scope.onLoad !== undefined ) {
39388  
39389					scope.onLoad();
39390  
39391				}
39392  
39393			}
39394  
39395		};
39396  
39397		this.itemError = function ( url ) {
39398  
39399			if ( scope.onError !== undefined ) {
39400  
39401				scope.onError( url );
39402  
39403			}
39404  
39405		};
39406  
39407		this.resolveURL = function ( url ) {
39408  
39409			if ( urlModifier ) {
39410  
39411				return urlModifier( url );
39412  
39413			}
39414  
39415			return url;
39416  
39417		};
39418  
39419		this.setURLModifier = function ( transform ) {
39420  
39421			urlModifier = transform;
39422			return this;
39423  
39424		};
39425  
39426	}
39427  
39428	var DefaultLoadingManager = new LoadingManager();
39429  
39430	/**
39431	 * @author mrdoob / http://mrdoob.com/
39432	 */
39433  
39434	var loading = {};
39435  
39436	function FileLoader( manager ) {
39437  
39438		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39439  
39440	}
39441  
39442	Object.assign( FileLoader.prototype, {
39443  
39444		load: function ( url, onLoad, onProgress, onError ) {
39445  
39446			if ( url === undefined ) url = '';
39447  
39448			if ( this.path !== undefined ) url = this.path + url;
39449  
39450			url = this.manager.resolveURL( url );
39451  
39452			var scope = this;
39453  
39454			var cached = Cache.get( url );
39455  
39456			if ( cached !== undefined ) {
39457  
39458				scope.manager.itemStart( url );
39459  
39460				setTimeout( function () {
39461  
39462					if ( onLoad ) onLoad( cached );
39463  
39464					scope.manager.itemEnd( url );
39465  
39466				}, 0 );
39467  
39468				return cached;
39469  
39470			}
39471  
39472			// Check if request is duplicate
39473  
39474			if ( loading[ url ] !== undefined ) {
39475  
39476				loading[ url ].push( {
39477  
39478					onLoad: onLoad,
39479					onProgress: onProgress,
39480					onError: onError
39481  
39482				} );
39483  
39484				return;
39485  
39486			}
39487  
39488			// Check for data: URI
39489			var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
39490			var dataUriRegexResult = url.match( dataUriRegex );
39491  
39492			// Safari can not handle Data URIs through XMLHttpRequest so process manually
39493			if ( dataUriRegexResult ) {
39494  
39495				var mimeType = dataUriRegexResult[ 1 ];
39496				var isBase64 = !! dataUriRegexResult[ 2 ];
39497				var data = dataUriRegexResult[ 3 ];
39498  
39499				data = window.decodeURIComponent( data );
39500  
39501				if ( isBase64 ) data = window.atob( data );
39502  
39503				try {
39504  
39505					var response;
39506					var responseType = ( this.responseType || '' ).toLowerCase();
39507  
39508					switch ( responseType ) {
39509  
39510						case 'arraybuffer':
39511						case 'blob':
39512  
39513							var view = new Uint8Array( data.length );
39514  
39515							for ( var i = 0; i < data.length; i ++ ) {
39516  
39517								view[ i ] = data.charCodeAt( i );
39518  
39519							}
39520  
39521							if ( responseType === 'blob' ) {
39522  
39523								response = new Blob( [ view.buffer ], { type: mimeType } );
39524  
39525							} else {
39526  
39527								response = view.buffer;
39528  
39529							}
39530  
39531							break;
39532  
39533						case 'document':
39534  
39535							var parser = new DOMParser();
39536							response = parser.parseFromString( data, mimeType );
39537  
39538							break;
39539  
39540						case 'json':
39541  
39542							response = JSON.parse( data );
39543  
39544							break;
39545  
39546						default: // 'text' or other
39547  
39548							response = data;
39549  
39550							break;
39551  
39552					}
39553  
39554					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
39555					window.setTimeout( function () {
39556  
39557						if ( onLoad ) onLoad( response );
39558  
39559						scope.manager.itemEnd( url );
39560  
39561					}, 0 );
39562  
39563				} catch ( error ) {
39564  
39565					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
39566					window.setTimeout( function () {
39567  
39568						if ( onError ) onError( error );
39569  
39570						scope.manager.itemEnd( url );
39571						scope.manager.itemError( url );
39572  
39573					}, 0 );
39574  
39575				}
39576  
39577			} else {
39578  
39579				// Initialise array for duplicate requests
39580  
39581				loading[ url ] = [];
39582  
39583				loading[ url ].push( {
39584  
39585					onLoad: onLoad,
39586					onProgress: onProgress,
39587					onError: onError
39588  
39589				} );
39590  
39591				var request = new XMLHttpRequest();
39592  
39593				request.open( 'GET', url, true );
39594  
39595				request.addEventListener( 'load', function ( event ) {
39596  
39597					var response = this.response;
39598  
39599					Cache.add( url, response );
39600  
39601					var callbacks = loading[ url ];
39602  
39603					delete loading[ url ];
39604  
39605					if ( this.status === 200 || this.status === 0 ) {
39606  
39607						// Some browsers return HTTP Status 0 when using non-http protocol
39608						// e.g. 'file://' or 'data://'. Handle as success.
39609  
39610						if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
39611  
39612						for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
39613  
39614							var callback = callbacks[ i ];
39615							if ( callback.onLoad ) callback.onLoad( response );
39616  
39617						}
39618  
39619						scope.manager.itemEnd( url );
39620  
39621					} else {
39622  
39623						for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
39624  
39625							var callback = callbacks[ i ];
39626							if ( callback.onError ) callback.onError( event );
39627  
39628						}
39629  
39630						scope.manager.itemEnd( url );
39631						scope.manager.itemError( url );
39632  
39633					}
39634  
39635				}, false );
39636  
39637				request.addEventListener( 'progress', function ( event ) {
39638  
39639					var callbacks = loading[ url ];
39640  
39641					for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
39642  
39643						var callback = callbacks[ i ];
39644						if ( callback.onProgress ) callback.onProgress( event );
39645  
39646					}
39647  
39648				}, false );
39649  
39650				request.addEventListener( 'error', function ( event ) {
39651  
39652					var callbacks = loading[ url ];
39653  
39654					delete loading[ url ];
39655  
39656					for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
39657  
39658						var callback = callbacks[ i ];
39659						if ( callback.onError ) callback.onError( event );
39660  
39661					}
39662  
39663					scope.manager.itemEnd( url );
39664					scope.manager.itemError( url );
39665  
39666				}, false );
39667  
39668				if ( this.responseType !== undefined ) request.responseType = this.responseType;
39669				if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
39670  
39671				if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
39672  
39673				for ( var header in this.requestHeader ) {
39674  
39675					request.setRequestHeader( header, this.requestHeader[ header ] );
39676  
39677				}
39678  
39679				request.send( null );
39680  
39681			}
39682  
39683			scope.manager.itemStart( url );
39684  
39685			return request;
39686  
39687		},
39688  
39689		setPath: function ( value ) {
39690  
39691			this.path = value;
39692			return this;
39693  
39694		},
39695  
39696		setResponseType: function ( value ) {
39697  
39698			this.responseType = value;
39699			return this;
39700  
39701		},
39702  
39703		setWithCredentials: function ( value ) {
39704  
39705			this.withCredentials = value;
39706			return this;
39707  
39708		},
39709  
39710		setMimeType: function ( value ) {
39711  
39712			this.mimeType = value;
39713			return this;
39714  
39715		},
39716  
39717		setRequestHeader: function ( value ) {
39718  
39719			this.requestHeader = value;
39720			return this;
39721  
39722		}
39723  
39724	} );
39725  
39726	/**
39727	 * @author mrdoob / http://mrdoob.com/
39728	 *
39729	 * Abstract Base class to block based textures loader (dds, pvr, ...)
39730	 */
39731  
39732	function CompressedTextureLoader( manager ) {
39733  
39734		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39735  
39736		// override in sub classes
39737		this._parser = null;
39738  
39739	}
39740  
39741	Object.assign( CompressedTextureLoader.prototype, {
39742  
39743		load: function ( url, onLoad, onProgress, onError ) {
39744  
39745			var scope = this;
39746  
39747			var images = [];
39748  
39749			var texture = new CompressedTexture();
39750			texture.image = images;
39751  
39752			var loader = new FileLoader( this.manager );
39753			loader.setPath( this.path );
39754			loader.setResponseType( 'arraybuffer' );
39755  
39756			function loadTexture( i ) {
39757  
39758				loader.load( url[ i ], function ( buffer ) {
39759  
39760					var texDatas = scope._parser( buffer, true );
39761  
39762					images[ i ] = {
39763						width: texDatas.width,
39764						height: texDatas.height,
39765						format: texDatas.format,
39766						mipmaps: texDatas.mipmaps
39767					};
39768  
39769					loaded += 1;
39770  
39771					if ( loaded === 6 ) {
39772  
39773						if ( texDatas.mipmapCount === 1 )
39774							texture.minFilter = LinearFilter;
39775  
39776						texture.format = texDatas.format;
39777						texture.needsUpdate = true;
39778  
39779						if ( onLoad ) onLoad( texture );
39780  
39781					}
39782  
39783				}, onProgress, onError );
39784  
39785			}
39786  
39787			if ( Array.isArray( url ) ) {
39788  
39789				var loaded = 0;
39790  
39791				for ( var i = 0, il = url.length; i < il; ++ i ) {
39792  
39793					loadTexture( i );
39794  
39795				}
39796  
39797			} else {
39798  
39799				// compressed cubemap texture stored in a single DDS file
39800  
39801				loader.load( url, function ( buffer ) {
39802  
39803					var texDatas = scope._parser( buffer, true );
39804  
39805					if ( texDatas.isCubemap ) {
39806  
39807						var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
39808  
39809						for ( var f = 0; f < faces; f ++ ) {
39810  
39811							images[ f ] = { mipmaps: [] };
39812  
39813							for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
39814  
39815								images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
39816								images[ f ].format = texDatas.format;
39817								images[ f ].width = texDatas.width;
39818								images[ f ].height = texDatas.height;
39819  
39820							}
39821  
39822						}
39823  
39824					} else {
39825  
39826						texture.image.width = texDatas.width;
39827						texture.image.height = texDatas.height;
39828						texture.mipmaps = texDatas.mipmaps;
39829  
39830					}
39831  
39832					if ( texDatas.mipmapCount === 1 ) {
39833  
39834						texture.minFilter = LinearFilter;
39835  
39836					}
39837  
39838					texture.format = texDatas.format;
39839					texture.needsUpdate = true;
39840  
39841					if ( onLoad ) onLoad( texture );
39842  
39843				}, onProgress, onError );
39844  
39845			}
39846  
39847			return texture;
39848  
39849		},
39850  
39851		setPath: function ( value ) {
39852  
39853			this.path = value;
39854			return this;
39855  
39856		}
39857  
39858	} );
39859  
39860	/**
39861	 * @author Nikos M. / https://github.com/foo123/
39862	 *
39863	 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
39864	 */
39865  
39866	function DataTextureLoader( manager ) {
39867  
39868		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39869  
39870		// override in sub classes
39871		this._parser = null;
39872  
39873	}
39874  
39875	Object.assign( DataTextureLoader.prototype, {
39876  
39877		load: function ( url, onLoad, onProgress, onError ) {
39878  
39879			var scope = this;
39880  
39881			var texture = new DataTexture();
39882  
39883			var loader = new FileLoader( this.manager );
39884			loader.setResponseType( 'arraybuffer' );
39885  
39886			loader.load( url, function ( buffer ) {
39887  
39888				var texData = scope._parser( buffer );
39889  
39890				if ( ! texData ) return;
39891  
39892				if ( undefined !== texData.image ) {
39893  
39894					texture.image = texData.image;
39895  
39896				} else if ( undefined !== texData.data ) {
39897  
39898					texture.image.width = texData.width;
39899					texture.image.height = texData.height;
39900					texture.image.data = texData.data;
39901  
39902				}
39903  
39904				texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
39905				texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
39906  
39907				texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
39908				texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
39909  
39910				texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
39911  
39912				if ( undefined !== texData.format ) {
39913  
39914					texture.format = texData.format;
39915  
39916				}
39917				if ( undefined !== texData.type ) {
39918  
39919					texture.type = texData.type;
39920  
39921				}
39922  
39923				if ( undefined !== texData.mipmaps ) {
39924  
39925					texture.mipmaps = texData.mipmaps;
39926  
39927				}
39928  
39929				if ( 1 === texData.mipmapCount ) {
39930  
39931					texture.minFilter = LinearFilter;
39932  
39933				}
39934  
39935				texture.needsUpdate = true;
39936  
39937				if ( onLoad ) onLoad( texture, texData );
39938  
39939			}, onProgress, onError );
39940  
39941  
39942			return texture;
39943  
39944		}
39945  
39946	} );
39947  
39948	/**
39949	 * @author mrdoob / http://mrdoob.com/
39950	 */
39951  
39952  
39953	function ImageLoader( manager ) {
39954  
39955		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39956  
39957	}
39958  
39959	Object.assign( ImageLoader.prototype, {
39960  
vendor: 97,894 bytes, lines 39961-44526
39961		crossOrigin: 'Anonymous',
39962  
39963		load: function ( url, onLoad, onProgress, onError ) {
39964  
39965			if ( url === undefined ) url = '';
39966  
39967			if ( this.path !== undefined ) url = this.path + url;
39968  
39969			url = this.manager.resolveURL( url );
39970  
39971			var scope = this;
39972  
39973			var cached = Cache.get( url );
39974  
39975			if ( cached !== undefined ) {
39976  
39977				scope.manager.itemStart( url );
39978  
39979				setTimeout( function () {
39980  
39981					if ( onLoad ) onLoad( cached );
39982  
39983					scope.manager.itemEnd( url );
39984  
39985				}, 0 );
39986  
39987				return cached;
39988  
39989			}
39990  
39991			var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
39992  
39993			function onImageLoad() {
39994  
39995				image.removeEventListener( 'load', onImageLoad, false );
39996				image.removeEventListener( 'error', onImageError, false );
39997  
39998				Cache.add( url, this );
39999  
40000				if ( onLoad ) onLoad( this );
40001  
40002				scope.manager.itemEnd( url );
40003  
40004			}
40005  
40006			function onImageError( event ) {
40007  
40008				image.removeEventListener( 'load', onImageLoad, false );
40009				image.removeEventListener( 'error', onImageError, false );
40010  
40011				if ( onError ) onError( event );
40012  
40013				scope.manager.itemEnd( url );
40014				scope.manager.itemError( url );
40015  
40016			}
40017  
40018			image.addEventListener( 'load', onImageLoad, false );
40019			image.addEventListener( 'error', onImageError, false );
40020  
40021			if ( url.substr( 0, 5 ) !== 'data:' ) {
40022  
40023				if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
40024  
40025			}
40026  
40027			scope.manager.itemStart( url );
40028  
40029			image.src = url;
40030  
40031			return image;
40032  
40033		},
40034  
40035		setCrossOrigin: function ( value ) {
40036  
40037			this.crossOrigin = value;
40038			return this;
40039  
40040		},
40041  
40042		setPath: function ( value ) {
40043  
40044			this.path = value;
40045			return this;
40046  
40047		}
40048  
40049	} );
40050  
40051	/**
40052	 * @author mrdoob / http://mrdoob.com/
40053	 */
40054  
40055  
40056	function CubeTextureLoader( manager ) {
40057  
40058		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
40059  
40060	}
40061  
40062	Object.assign( CubeTextureLoader.prototype, {
40063  
40064		crossOrigin: 'Anonymous',
40065  
40066		load: function ( urls, onLoad, onProgress, onError ) {
40067  
40068			var texture = new CubeTexture();
40069  
40070			var loader = new ImageLoader( this.manager );
40071			loader.setCrossOrigin( this.crossOrigin );
40072			loader.setPath( this.path );
40073  
40074			var loaded = 0;
40075  
40076			function loadTexture( i ) {
40077  
40078				loader.load( urls[ i ], function ( image ) {
40079  
40080					texture.images[ i ] = image;
40081  
40082					loaded ++;
40083  
40084					if ( loaded === 6 ) {
40085  
40086						texture.needsUpdate = true;
40087  
40088						if ( onLoad ) onLoad( texture );
40089  
40090					}
40091  
40092				}, undefined, onError );
40093  
40094			}
40095  
40096			for ( var i = 0; i < urls.length; ++ i ) {
40097  
40098				loadTexture( i );
40099  
40100			}
40101  
40102			return texture;
40103  
40104		},
40105  
40106		setCrossOrigin: function ( value ) {
40107  
40108			this.crossOrigin = value;
40109			return this;
40110  
40111		},
40112  
40113		setPath: function ( value ) {
40114  
40115			this.path = value;
40116			return this;
40117  
40118		}
40119  
40120	} );
40121  
40122	/**
40123	 * @author mrdoob / http://mrdoob.com/
40124	 */
40125  
40126  
40127	function TextureLoader( manager ) {
40128  
40129		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
40130  
40131	}
40132  
40133	Object.assign( TextureLoader.prototype, {
40134  
40135		crossOrigin: 'Anonymous',
40136  
40137		load: function ( url, onLoad, onProgress, onError ) {
40138  
40139			var texture = new Texture();
40140  
40141			var loader = new ImageLoader( this.manager );
40142			loader.setCrossOrigin( this.crossOrigin );
40143			loader.setPath( this.path );
40144  
40145			loader.load( url, function ( image ) {
40146  
40147				texture.image = image;
40148  
40149				// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
40150				var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
40151  
40152				texture.format = isJPEG ? RGBFormat : RGBAFormat;
40153				texture.needsUpdate = true;
40154  
40155				if ( onLoad !== undefined ) {
40156  
40157					onLoad( texture );
40158  
40159				}
40160  
40161			}, onProgress, onError );
40162  
40163			return texture;
40164  
40165		},
40166  
40167		setCrossOrigin: function ( value ) {
40168  
40169			this.crossOrigin = value;
40170			return this;
40171  
40172		},
40173  
40174		setPath: function ( value ) {
40175  
40176			this.path = value;
40177			return this;
40178  
40179		}
40180  
40181	} );
40182  
40183	/**
40184	 * @author zz85 / http://www.lab4games.net/zz85/blog
40185	 * Extensible curve object
40186	 *
40187	 * Some common of curve methods:
40188	 * .getPoint( t, optionalTarget ), .getTangent( t )
40189	 * .getPointAt( u, optionalTarget ), .getTangentAt( u )
40190	 * .getPoints(), .getSpacedPoints()
40191	 * .getLength()
40192	 * .updateArcLengths()
40193	 *
40194	 * This following curves inherit from THREE.Curve:
40195	 *
40196	 * -- 2D curves --
40197	 * THREE.ArcCurve
40198	 * THREE.CubicBezierCurve
40199	 * THREE.EllipseCurve
40200	 * THREE.LineCurve
40201	 * THREE.QuadraticBezierCurve
40202	 * THREE.SplineCurve
40203	 *
40204	 * -- 3D curves --
40205	 * THREE.CatmullRomCurve3
40206	 * THREE.CubicBezierCurve3
40207	 * THREE.LineCurve3
40208	 * THREE.QuadraticBezierCurve3
40209	 *
40210	 * A series of curves can be represented as a THREE.CurvePath.
40211	 *
40212	 **/
40213  
40214	/**************************************************************
40215	 *	Abstract Curve base class
40216	 **************************************************************/
40217  
40218	function Curve() {
40219  
40220		this.type = 'Curve';
40221  
40222		this.arcLengthDivisions = 200;
40223  
40224	}
40225  
40226	Object.assign( Curve.prototype, {
40227  
40228		// Virtual base class method to overwrite and implement in subclasses
40229		//	- t [0 .. 1]
40230  
40231		getPoint: function ( /* t, optionalTarget */ ) {
40232  
40233			console.warn( 'THREE.Curve: .getPoint() not implemented.' );
40234			return null;
40235  
40236		},
40237  
40238		// Get point at relative position in curve according to arc length
40239		// - u [0 .. 1]
40240  
40241		getPointAt: function ( u, optionalTarget ) {
40242  
40243			var t = this.getUtoTmapping( u );
40244			return this.getPoint( t, optionalTarget );
40245  
40246		},
40247  
40248		// Get sequence of points using getPoint( t )
40249  
40250		getPoints: function ( divisions ) {
40251  
40252			if ( divisions === undefined ) divisions = 5;
40253  
40254			var points = [];
40255  
40256			for ( var d = 0; d <= divisions; d ++ ) {
40257  
40258				points.push( this.getPoint( d / divisions ) );
40259  
40260			}
40261  
40262			return points;
40263  
40264		},
40265  
40266		// Get sequence of points using getPointAt( u )
40267  
40268		getSpacedPoints: function ( divisions ) {
40269  
40270			if ( divisions === undefined ) divisions = 5;
40271  
40272			var points = [];
40273  
40274			for ( var d = 0; d <= divisions; d ++ ) {
40275  
40276				points.push( this.getPointAt( d / divisions ) );
40277  
40278			}
40279  
40280			return points;
40281  
40282		},
40283  
40284		// Get total curve arc length
40285  
40286		getLength: function () {
40287  
40288			var lengths = this.getLengths();
40289			return lengths[ lengths.length - 1 ];
40290  
40291		},
40292  
40293		// Get list of cumulative segment lengths
40294  
40295		getLengths: function ( divisions ) {
40296  
40297			if ( divisions === undefined ) divisions = this.arcLengthDivisions;
40298  
40299			if ( this.cacheArcLengths &&
40300				( this.cacheArcLengths.length === divisions + 1 ) &&
40301				! this.needsUpdate ) {
40302  
40303				return this.cacheArcLengths;
40304  
40305			}
40306  
40307			this.needsUpdate = false;
40308  
40309			var cache = [];
40310			var current, last = this.getPoint( 0 );
40311			var p, sum = 0;
40312  
40313			cache.push( 0 );
40314  
40315			for ( p = 1; p <= divisions; p ++ ) {
40316  
40317				current = this.getPoint( p / divisions );
40318				sum += current.distanceTo( last );
40319				cache.push( sum );
40320				last = current;
40321  
40322			}
40323  
40324			this.cacheArcLengths = cache;
40325  
40326			return cache; // { sums: cache, sum: sum }; Sum is in the last element.
40327  
40328		},
40329  
40330		updateArcLengths: function () {
40331  
40332			this.needsUpdate = true;
40333			this.getLengths();
40334  
40335		},
40336  
40337		// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
40338  
40339		getUtoTmapping: function ( u, distance ) {
40340  
40341			var arcLengths = this.getLengths();
40342  
40343			var i = 0, il = arcLengths.length;
40344  
40345			var targetArcLength; // The targeted u distance value to get
40346  
40347			if ( distance ) {
40348  
40349				targetArcLength = distance;
40350  
40351			} else {
40352  
40353				targetArcLength = u * arcLengths[ il - 1 ];
40354  
40355			}
40356  
40357			// binary search for the index with largest value smaller than target u distance
40358  
40359			var low = 0, high = il - 1, comparison;
40360  
40361			while ( low <= high ) {
40362  
40363				i = 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
40364  
40365				comparison = arcLengths[ i ] - targetArcLength;
40366  
40367				if ( comparison < 0 ) {
40368  
40369					low = i + 1;
40370  
40371				} else if ( comparison > 0 ) {
40372  
40373					high = i - 1;
40374  
40375				} else {
40376  
40377					high = i;
40378					break;
40379  
40380					// DONE
40381  
40382				}
40383  
40384			}
40385  
40386			i = high;
40387  
40388			if ( arcLengths[ i ] === targetArcLength ) {
40389  
40390				return i / ( il - 1 );
40391  
40392			}
40393  
40394			// we could get finer grain at lengths, or use simple interpolation between two points
40395  
40396			var lengthBefore = arcLengths[ i ];
40397			var lengthAfter = arcLengths[ i + 1 ];
40398  
40399			var segmentLength = lengthAfter - lengthBefore;
40400  
40401			// determine where we are between the 'before' and 'after' points
40402  
40403			var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
40404  
40405			// add that fractional amount to t
40406  
40407			var t = ( i + segmentFraction ) / ( il - 1 );
40408  
40409			return t;
40410  
40411		},
40412  
40413		// Returns a unit vector tangent at t
40414		// In case any sub curve does not implement its tangent derivation,
40415		// 2 points a small delta apart will be used to find its gradient
40416		// which seems to give a reasonable approximation
40417  
40418		getTangent: function ( t ) {
40419  
40420			var delta = 0.0001;
40421			var t1 = t - delta;
40422			var t2 = t + delta;
40423  
40424			// Capping in case of danger
40425  
40426			if ( t1 < 0 ) t1 = 0;
40427			if ( t2 > 1 ) t2 = 1;
40428  
40429			var pt1 = this.getPoint( t1 );
40430			var pt2 = this.getPoint( t2 );
40431  
40432			var vec = pt2.clone().sub( pt1 );
40433			return vec.normalize();
40434  
40435		},
40436  
40437		getTangentAt: function ( u ) {
40438  
40439			var t = this.getUtoTmapping( u );
40440			return this.getTangent( t );
40441  
40442		},
40443  
40444		computeFrenetFrames: function ( segments, closed ) {
40445  
40446			// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
40447  
40448			var normal = new Vector3();
40449  
40450			var tangents = [];
40451			var normals = [];
40452			var binormals = [];
40453  
40454			var vec = new Vector3();
40455			var mat = new Matrix4();
40456  
40457			var i, u, theta;
40458  
40459			// compute the tangent vectors for each segment on the curve
40460  
40461			for ( i = 0; i <= segments; i ++ ) {
40462  
40463				u = i / segments;
40464  
40465				tangents[ i ] = this.getTangentAt( u );
40466				tangents[ i ].normalize();
40467  
40468			}
40469  
40470			// select an initial normal vector perpendicular to the first tangent vector,
40471			// and in the direction of the minimum tangent xyz component
40472  
40473			normals[ 0 ] = new Vector3();
40474			binormals[ 0 ] = new Vector3();
40475			var min = Number.MAX_VALUE;
40476			var tx = Math.abs( tangents[ 0 ].x );
40477			var ty = Math.abs( tangents[ 0 ].y );
40478			var tz = Math.abs( tangents[ 0 ].z );
40479  
40480			if ( tx <= min ) {
40481  
40482				min = tx;
40483				normal.set( 1, 0, 0 );
40484  
40485			}
40486  
40487			if ( ty <= min ) {
40488  
40489				min = ty;
40490				normal.set( 0, 1, 0 );
40491  
40492			}
40493  
40494			if ( tz <= min ) {
40495  
40496				normal.set( 0, 0, 1 );
40497  
40498			}
40499  
40500			vec.crossVectors( tangents[ 0 ], normal ).normalize();
40501  
40502			normals[ 0 ].crossVectors( tangents[ 0 ], vec );
40503			binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
40504  
40505  
40506			// compute the slowly-varying normal and binormal vectors for each segment on the curve
40507  
40508			for ( i = 1; i <= segments; i ++ ) {
40509  
40510				normals[ i ] = normals[ i - 1 ].clone();
40511  
40512				binormals[ i ] = binormals[ i - 1 ].clone();
40513  
40514				vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
40515  
40516				if ( vec.length() > Number.EPSILON ) {
40517  
40518					vec.normalize();
40519  
40520					theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
40521  
40522					normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
40523  
40524				}
40525  
40526				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
40527  
40528			}
40529  
40530			// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
40531  
40532			if ( closed === true ) {
40533  
40534				theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
40535				theta /= segments;
40536  
40537				if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
40538  
40539					theta = - theta;
40540  
40541				}
40542  
40543				for ( i = 1; i <= segments; i ++ ) {
40544  
40545					// twist a little...
40546					normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
40547					binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
40548  
40549				}
40550  
40551			}
40552  
40553			return {
40554				tangents: tangents,
40555				normals: normals,
40556				binormals: binormals
40557			};
40558  
40559		},
40560  
40561		clone: function () {
40562  
40563			return new this.constructor().copy( this );
40564  
40565		},
40566  
40567		copy: function ( source ) {
40568  
40569			this.arcLengthDivisions = source.arcLengthDivisions;
40570  
40571			return this;
40572  
40573		},
40574  
40575		toJSON: function () {
40576  
40577			var data = {
40578				metadata: {
40579					version: 4.5,
40580					type: 'Curve',
40581					generator: 'Curve.toJSON'
40582				}
40583			};
40584  
40585			data.arcLengthDivisions = this.arcLengthDivisions;
40586			data.type = this.type;
40587  
40588			return data;
40589  
40590		},
40591  
40592		fromJSON: function ( json ) {
40593  
40594			this.arcLengthDivisions = json.arcLengthDivisions;
40595  
40596			return this;
40597  
40598		}
40599  
40600	} );
40601  
40602	function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
40603  
40604		Curve.call( this );
40605  
40606		this.type = 'EllipseCurve';
40607  
40608		this.aX = aX || 0;
40609		this.aY = aY || 0;
40610  
40611		this.xRadius = xRadius || 1;
40612		this.yRadius = yRadius || 1;
40613  
40614		this.aStartAngle = aStartAngle || 0;
40615		this.aEndAngle = aEndAngle || 2 * Math.PI;
40616  
40617		this.aClockwise = aClockwise || false;
40618  
40619		this.aRotation = aRotation || 0;
40620  
40621	}
40622  
40623	EllipseCurve.prototype = Object.create( Curve.prototype );
40624	EllipseCurve.prototype.constructor = EllipseCurve;
40625  
40626	EllipseCurve.prototype.isEllipseCurve = true;
40627  
40628	EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
40629  
40630		var point = optionalTarget || new Vector2();
40631  
40632		var twoPi = Math.PI * 2;
40633		var deltaAngle = this.aEndAngle - this.aStartAngle;
40634		var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
40635  
40636		// ensures that deltaAngle is 0 .. 2 PI
40637		while ( deltaAngle < 0 ) deltaAngle += twoPi;
40638		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
40639  
40640		if ( deltaAngle < Number.EPSILON ) {
40641  
40642			if ( samePoints ) {
40643  
40644				deltaAngle = 0;
40645  
40646			} else {
40647  
40648				deltaAngle = twoPi;
40649  
40650			}
40651  
40652		}
40653  
40654		if ( this.aClockwise === true && ! samePoints ) {
40655  
40656			if ( deltaAngle === twoPi ) {
40657  
40658				deltaAngle = - twoPi;
40659  
40660			} else {
40661  
40662				deltaAngle = deltaAngle - twoPi;
40663  
40664			}
40665  
40666		}
40667  
40668		var angle = this.aStartAngle + t * deltaAngle;
40669		var x = this.aX + this.xRadius * Math.cos( angle );
40670		var y = this.aY + this.yRadius * Math.sin( angle );
40671  
40672		if ( this.aRotation !== 0 ) {
40673  
40674			var cos = Math.cos( this.aRotation );
40675			var sin = Math.sin( this.aRotation );
40676  
40677			var tx = x - this.aX;
40678			var ty = y - this.aY;
40679  
40680			// Rotate the point about the center of the ellipse.
40681			x = tx * cos - ty * sin + this.aX;
40682			y = tx * sin + ty * cos + this.aY;
40683  
40684		}
40685  
40686		return point.set( x, y );
40687  
40688	};
40689  
40690	EllipseCurve.prototype.copy = function ( source ) {
40691  
40692		Curve.prototype.copy.call( this, source );
40693  
40694		this.aX = source.aX;
40695		this.aY = source.aY;
40696  
40697		this.xRadius = source.xRadius;
40698		this.yRadius = source.yRadius;
40699  
40700		this.aStartAngle = source.aStartAngle;
40701		this.aEndAngle = source.aEndAngle;
40702  
40703		this.aClockwise = source.aClockwise;
40704  
40705		this.aRotation = source.aRotation;
40706  
40707		return this;
40708  
40709	};
40710  
40711  
40712	EllipseCurve.prototype.toJSON = function () {
40713  
40714		var data = Curve.prototype.toJSON.call( this );
40715  
40716		data.aX = this.aX;
40717		data.aY = this.aY;
40718  
40719		data.xRadius = this.xRadius;
40720		data.yRadius = this.yRadius;
40721  
40722		data.aStartAngle = this.aStartAngle;
40723		data.aEndAngle = this.aEndAngle;
40724  
40725		data.aClockwise = this.aClockwise;
40726  
40727		data.aRotation = this.aRotation;
40728  
40729		return data;
40730  
40731	};
40732  
40733	EllipseCurve.prototype.fromJSON = function ( json ) {
40734  
40735		Curve.prototype.fromJSON.call( this, json );
40736  
40737		this.aX = json.aX;
40738		this.aY = json.aY;
40739  
40740		this.xRadius = json.xRadius;
40741		this.yRadius = json.yRadius;
40742  
40743		this.aStartAngle = json.aStartAngle;
40744		this.aEndAngle = json.aEndAngle;
40745  
40746		this.aClockwise = json.aClockwise;
40747  
40748		this.aRotation = json.aRotation;
40749  
40750		return this;
40751  
40752	};
40753  
40754	function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
40755  
40756		EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
40757  
40758		this.type = 'ArcCurve';
40759  
40760	}
40761  
40762	ArcCurve.prototype = Object.create( EllipseCurve.prototype );
40763	ArcCurve.prototype.constructor = ArcCurve;
40764  
40765	ArcCurve.prototype.isArcCurve = true;
40766  
40767	/**
40768	 * @author zz85 https://github.com/zz85
40769	 *
40770	 * Centripetal CatmullRom Curve - which is useful for avoiding
40771	 * cusps and self-intersections in non-uniform catmull rom curves.
40772	 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
40773	 *
40774	 * curve.type accepts centripetal(default), chordal and catmullrom
40775	 * curve.tension is used for catmullrom which defaults to 0.5
40776	 */
40777  
40778  
40779	/*
40780	Based on an optimized c++ solution in
40781	 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
40782	 - http://ideone.com/NoEbVM
40783  
40784	This CubicPoly class could be used for reusing some variables and calculations,
40785	but for three.js curve use, it could be possible inlined and flatten into a single function call
40786	which can be placed in CurveUtils.
40787	*/
40788  
40789	function CubicPoly() {
40790  
40791		var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
40792  
40793		/*
40794		 * Compute coefficients for a cubic polynomial
40795		 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
40796		 * such that
40797		 *   p(0) = x0, p(1) = x1
40798		 *  and
40799		 *   p'(0) = t0, p'(1) = t1.
40800		 */
40801		function init( x0, x1, t0, t1 ) {
40802  
40803			c0 = x0;
40804			c1 = t0;
40805			c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
40806			c3 = 2 * x0 - 2 * x1 + t0 + t1;
40807  
40808		}
40809  
40810		return {
40811  
40812			initCatmullRom: function ( x0, x1, x2, x3, tension ) {
40813  
40814				init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
40815  
40816			},
40817  
40818			initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
40819  
40820				// compute tangents when parameterized in [t1,t2]
40821				var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
40822				var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
40823  
40824				// rescale tangents for parametrization in [0,1]
40825				t1 *= dt1;
40826				t2 *= dt1;
40827  
40828				init( x1, x2, t1, t2 );
40829  
40830			},
40831  
40832			calc: function ( t ) {
40833  
40834				var t2 = t * t;
40835				var t3 = t2 * t;
40836				return c0 + c1 * t + c2 * t2 + c3 * t3;
40837  
40838			}
40839  
40840		};
40841  
40842	}
40843  
40844	//
40845  
40846	var tmp = new Vector3();
40847	var px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
40848  
40849	function CatmullRomCurve3( points, closed, curveType, tension ) {
40850  
40851		Curve.call( this );
40852  
40853		this.type = 'CatmullRomCurve3';
40854  
40855		this.points = points || [];
40856		this.closed = closed || false;
40857		this.curveType = curveType || 'centripetal';
40858		this.tension = tension || 0.5;
40859  
40860	}
40861  
40862	CatmullRomCurve3.prototype = Object.create( Curve.prototype );
40863	CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
40864  
40865	CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
40866  
40867	CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {
40868  
40869		var point = optionalTarget || new Vector3();
40870  
40871		var points = this.points;
40872		var l = points.length;
40873  
40874		var p = ( l - ( this.closed ? 0 : 1 ) ) * t;
40875		var intPoint = Math.floor( p );
40876		var weight = p - intPoint;
40877  
40878		if ( this.closed ) {
40879  
40880			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
40881  
40882		} else if ( weight === 0 && intPoint === l - 1 ) {
40883  
40884			intPoint = l - 2;
40885			weight = 1;
40886  
40887		}
40888  
40889		var p0, p1, p2, p3; // 4 points
40890  
40891		if ( this.closed || intPoint > 0 ) {
40892  
40893			p0 = points[ ( intPoint - 1 ) % l ];
40894  
40895		} else {
40896  
40897			// extrapolate first point
40898			tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
40899			p0 = tmp;
40900  
40901		}
40902  
40903		p1 = points[ intPoint % l ];
40904		p2 = points[ ( intPoint + 1 ) % l ];
40905  
40906		if ( this.closed || intPoint + 2 < l ) {
40907  
40908			p3 = points[ ( intPoint + 2 ) % l ];
40909  
40910		} else {
40911  
40912			// extrapolate last point
40913			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
40914			p3 = tmp;
40915  
40916		}
40917  
40918		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
40919  
40920			// init Centripetal / Chordal Catmull-Rom
40921			var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
40922			var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
40923			var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
40924			var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
40925  
40926			// safety check for repeated points
40927			if ( dt1 < 1e-4 ) dt1 = 1.0;
40928			if ( dt0 < 1e-4 ) dt0 = dt1;
40929			if ( dt2 < 1e-4 ) dt2 = dt1;
40930  
40931			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
40932			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
40933			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
40934  
40935		} else if ( this.curveType === 'catmullrom' ) {
40936  
40937			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
40938			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
40939			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
40940  
40941		}
40942  
40943		point.set(
40944			px.calc( weight ),
40945			py.calc( weight ),
40946			pz.calc( weight )
40947		);
40948  
40949		return point;
40950  
40951	};
40952  
40953	CatmullRomCurve3.prototype.copy = function ( source ) {
40954  
40955		Curve.prototype.copy.call( this, source );
40956  
40957		this.points = [];
40958  
40959		for ( var i = 0, l = source.points.length; i < l; i ++ ) {
40960  
40961			var point = source.points[ i ];
40962  
40963			this.points.push( point.clone() );
40964  
40965		}
40966  
40967		this.closed = source.closed;
40968		this.curveType = source.curveType;
40969		this.tension = source.tension;
40970  
40971		return this;
40972  
40973	};
40974  
40975	CatmullRomCurve3.prototype.toJSON = function () {
40976  
40977		var data = Curve.prototype.toJSON.call( this );
40978  
40979		data.points = [];
40980  
40981		for ( var i = 0, l = this.points.length; i < l; i ++ ) {
40982  
40983			var point = this.points[ i ];
40984			data.points.push( point.toArray() );
40985  
40986		}
40987  
40988		data.closed = this.closed;
40989		data.curveType = this.curveType;
40990		data.tension = this.tension;
40991  
40992		return data;
40993  
40994	};
40995  
40996	CatmullRomCurve3.prototype.fromJSON = function ( json ) {
40997  
40998		Curve.prototype.fromJSON.call( this, json );
40999  
41000		this.points = [];
41001  
41002		for ( var i = 0, l = json.points.length; i < l; i ++ ) {
41003  
41004			var point = json.points[ i ];
41005			this.points.push( new Vector3().fromArray( point ) );
41006  
41007		}
41008  
41009		this.closed = json.closed;
41010		this.curveType = json.curveType;
41011		this.tension = json.tension;
41012  
41013		return this;
41014  
41015	};
41016  
41017	/**
41018	 * @author zz85 / http://www.lab4games.net/zz85/blog
41019	 *
41020	 * Bezier Curves formulas obtained from
41021	 * http://en.wikipedia.org/wiki/Bézier_curve
41022	 */
41023  
41024	function CatmullRom( t, p0, p1, p2, p3 ) {
41025  
41026		var v0 = ( p2 - p0 ) * 0.5;
41027		var v1 = ( p3 - p1 ) * 0.5;
41028		var t2 = t * t;
41029		var t3 = t * t2;
41030		return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
41031  
41032	}
41033  
41034	//
41035  
41036	function QuadraticBezierP0( t, p ) {
41037  
41038		var k = 1 - t;
41039		return k * k * p;
41040  
41041	}
41042  
41043	function QuadraticBezierP1( t, p ) {
41044  
41045		return 2 * ( 1 - t ) * t * p;
41046  
41047	}
41048  
41049	function QuadraticBezierP2( t, p ) {
41050  
41051		return t * t * p;
41052  
41053	}
41054  
41055	function QuadraticBezier( t, p0, p1, p2 ) {
41056  
41057		return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
41058			QuadraticBezierP2( t, p2 );
41059  
41060	}
41061  
41062	//
41063  
41064	function CubicBezierP0( t, p ) {
41065  
41066		var k = 1 - t;
41067		return k * k * k * p;
41068  
41069	}
41070  
41071	function CubicBezierP1( t, p ) {
41072  
41073		var k = 1 - t;
41074		return 3 * k * k * t * p;
41075  
41076	}
41077  
41078	function CubicBezierP2( t, p ) {
41079  
41080		return 3 * ( 1 - t ) * t * t * p;
41081  
41082	}
41083  
41084	function CubicBezierP3( t, p ) {
41085  
41086		return t * t * t * p;
41087  
41088	}
41089  
41090	function CubicBezier( t, p0, p1, p2, p3 ) {
41091  
41092		return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
41093			CubicBezierP3( t, p3 );
41094  
41095	}
41096  
41097	function CubicBezierCurve( v0, v1, v2, v3 ) {
41098  
41099		Curve.call( this );
41100  
41101		this.type = 'CubicBezierCurve';
41102  
41103		this.v0 = v0 || new Vector2();
41104		this.v1 = v1 || new Vector2();
41105		this.v2 = v2 || new Vector2();
41106		this.v3 = v3 || new Vector2();
41107  
41108	}
41109  
41110	CubicBezierCurve.prototype = Object.create( Curve.prototype );
41111	CubicBezierCurve.prototype.constructor = CubicBezierCurve;
41112  
41113	CubicBezierCurve.prototype.isCubicBezierCurve = true;
41114  
41115	CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
41116  
41117		var point = optionalTarget || new Vector2();
41118  
41119		var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
41120  
41121		point.set(
41122			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
41123			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
41124		);
41125  
41126		return point;
41127  
41128	};
41129  
41130	CubicBezierCurve.prototype.copy = function ( source ) {
41131  
41132		Curve.prototype.copy.call( this, source );
41133  
41134		this.v0.copy( source.v0 );
41135		this.v1.copy( source.v1 );
41136		this.v2.copy( source.v2 );
41137		this.v3.copy( source.v3 );
41138  
41139		return this;
41140  
41141	};
41142  
41143	CubicBezierCurve.prototype.toJSON = function () {
41144  
41145		var data = Curve.prototype.toJSON.call( this );
41146  
41147		data.v0 = this.v0.toArray();
41148		data.v1 = this.v1.toArray();
41149		data.v2 = this.v2.toArray();
41150		data.v3 = this.v3.toArray();
41151  
41152		return data;
41153  
41154	};
41155  
41156	CubicBezierCurve.prototype.fromJSON = function ( json ) {
41157  
41158		Curve.prototype.fromJSON.call( this, json );
41159  
41160		this.v0.fromArray( json.v0 );
41161		this.v1.fromArray( json.v1 );
41162		this.v2.fromArray( json.v2 );
41163		this.v3.fromArray( json.v3 );
41164  
41165		return this;
41166  
41167	};
41168  
41169	function CubicBezierCurve3( v0, v1, v2, v3 ) {
41170  
41171		Curve.call( this );
41172  
41173		this.type = 'CubicBezierCurve3';
41174  
41175		this.v0 = v0 || new Vector3();
41176		this.v1 = v1 || new Vector3();
41177		this.v2 = v2 || new Vector3();
41178		this.v3 = v3 || new Vector3();
41179  
41180	}
41181  
41182	CubicBezierCurve3.prototype = Object.create( Curve.prototype );
41183	CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
41184  
41185	CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
41186  
41187	CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
41188  
41189		var point = optionalTarget || new Vector3();
41190  
41191		var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
41192  
41193		point.set(
41194			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
41195			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
41196			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
41197		);
41198  
41199		return point;
41200  
41201	};
41202  
41203	CubicBezierCurve3.prototype.copy = function ( source ) {
41204  
41205		Curve.prototype.copy.call( this, source );
41206  
41207		this.v0.copy( source.v0 );
41208		this.v1.copy( source.v1 );
41209		this.v2.copy( source.v2 );
41210		this.v3.copy( source.v3 );
41211  
41212		return this;
41213  
41214	};
41215  
41216	CubicBezierCurve3.prototype.toJSON = function () {
41217  
41218		var data = Curve.prototype.toJSON.call( this );
41219  
41220		data.v0 = this.v0.toArray();
41221		data.v1 = this.v1.toArray();
41222		data.v2 = this.v2.toArray();
41223		data.v3 = this.v3.toArray();
41224  
41225		return data;
41226  
41227	};
41228  
41229	CubicBezierCurve3.prototype.fromJSON = function ( json ) {
41230  
41231		Curve.prototype.fromJSON.call( this, json );
41232  
41233		this.v0.fromArray( json.v0 );
41234		this.v1.fromArray( json.v1 );
41235		this.v2.fromArray( json.v2 );
41236		this.v3.fromArray( json.v3 );
41237  
41238		return this;
41239  
41240	};
41241  
41242	function LineCurve( v1, v2 ) {
41243  
41244		Curve.call( this );
41245  
41246		this.type = 'LineCurve';
41247  
41248		this.v1 = v1 || new Vector2();
41249		this.v2 = v2 || new Vector2();
41250  
41251	}
41252  
41253	LineCurve.prototype = Object.create( Curve.prototype );
41254	LineCurve.prototype.constructor = LineCurve;
41255  
41256	LineCurve.prototype.isLineCurve = true;
41257  
41258	LineCurve.prototype.getPoint = function ( t, optionalTarget ) {
41259  
41260		var point = optionalTarget || new Vector2();
41261  
41262		if ( t === 1 ) {
41263  
41264			point.copy( this.v2 );
41265  
41266		} else {
41267  
41268			point.copy( this.v2 ).sub( this.v1 );
41269			point.multiplyScalar( t ).add( this.v1 );
41270  
41271		}
41272  
41273		return point;
41274  
41275	};
41276  
41277	// Line curve is linear, so we can overwrite default getPointAt
41278  
41279	LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
41280  
41281		return this.getPoint( u, optionalTarget );
41282  
41283	};
41284  
41285	LineCurve.prototype.getTangent = function ( /* t */ ) {
41286  
41287		var tangent = this.v2.clone().sub( this.v1 );
41288  
41289		return tangent.normalize();
41290  
41291	};
41292  
41293	LineCurve.prototype.copy = function ( source ) {
41294  
41295		Curve.prototype.copy.call( this, source );
41296  
41297		this.v1.copy( source.v1 );
41298		this.v2.copy( source.v2 );
41299  
41300		return this;
41301  
41302	};
41303  
41304	LineCurve.prototype.toJSON = function () {
41305  
41306		var data = Curve.prototype.toJSON.call( this );
41307  
41308		data.v1 = this.v1.toArray();
41309		data.v2 = this.v2.toArray();
41310  
41311		return data;
41312  
41313	};
41314  
41315	LineCurve.prototype.fromJSON = function ( json ) {
41316  
41317		Curve.prototype.fromJSON.call( this, json );
41318  
41319		this.v1.fromArray( json.v1 );
41320		this.v2.fromArray( json.v2 );
41321  
41322		return this;
41323  
41324	};
41325  
41326	function LineCurve3( v1, v2 ) {
41327  
41328		Curve.call( this );
41329  
41330		this.type = 'LineCurve3';
41331  
41332		this.v1 = v1 || new Vector3();
41333		this.v2 = v2 || new Vector3();
41334  
41335	}
41336  
41337	LineCurve3.prototype = Object.create( Curve.prototype );
41338	LineCurve3.prototype.constructor = LineCurve3;
41339  
41340	LineCurve3.prototype.isLineCurve3 = true;
41341  
41342	LineCurve3.prototype.getPoint = function ( t, optionalTarget ) {
41343  
41344		var point = optionalTarget || new Vector3();
41345  
41346		if ( t === 1 ) {
41347  
41348			point.copy( this.v2 );
41349  
41350		} else {
41351  
41352			point.copy( this.v2 ).sub( this.v1 );
41353			point.multiplyScalar( t ).add( this.v1 );
41354  
41355		}
41356  
41357		return point;
41358  
41359	};
41360  
41361	// Line curve is linear, so we can overwrite default getPointAt
41362  
41363	LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
41364  
41365		return this.getPoint( u, optionalTarget );
41366  
41367	};
41368  
41369	LineCurve3.prototype.copy = function ( source ) {
41370  
41371		Curve.prototype.copy.call( this, source );
41372  
41373		this.v1.copy( source.v1 );
41374		this.v2.copy( source.v2 );
41375  
41376		return this;
41377  
41378	};
41379  
41380	LineCurve3.prototype.toJSON = function () {
41381  
41382		var data = Curve.prototype.toJSON.call( this );
41383  
41384		data.v1 = this.v1.toArray();
41385		data.v2 = this.v2.toArray();
41386  
41387		return data;
41388  
41389	};
41390  
41391	LineCurve3.prototype.fromJSON = function ( json ) {
41392  
41393		Curve.prototype.fromJSON.call( this, json );
41394  
41395		this.v1.fromArray( json.v1 );
41396		this.v2.fromArray( json.v2 );
41397  
41398		return this;
41399  
41400	};
41401  
41402	function QuadraticBezierCurve( v0, v1, v2 ) {
41403  
41404		Curve.call( this );
41405  
41406		this.type = 'QuadraticBezierCurve';
41407  
41408		this.v0 = v0 || new Vector2();
41409		this.v1 = v1 || new Vector2();
41410		this.v2 = v2 || new Vector2();
41411  
41412	}
41413  
41414	QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
41415	QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
41416  
41417	QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
41418  
41419	QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
41420  
41421		var point = optionalTarget || new Vector2();
41422  
41423		var v0 = this.v0, v1 = this.v1, v2 = this.v2;
41424  
41425		point.set(
41426			QuadraticBezier( t, v0.x, v1.x, v2.x ),
41427			QuadraticBezier( t, v0.y, v1.y, v2.y )
41428		);
41429  
41430		return point;
41431  
41432	};
41433  
41434	QuadraticBezierCurve.prototype.copy = function ( source ) {
41435  
41436		Curve.prototype.copy.call( this, source );
41437  
41438		this.v0.copy( source.v0 );
41439		this.v1.copy( source.v1 );
41440		this.v2.copy( source.v2 );
41441  
41442		return this;
41443  
41444	};
41445  
41446	QuadraticBezierCurve.prototype.toJSON = function () {
41447  
41448		var data = Curve.prototype.toJSON.call( this );
41449  
41450		data.v0 = this.v0.toArray();
41451		data.v1 = this.v1.toArray();
41452		data.v2 = this.v2.toArray();
41453  
41454		return data;
41455  
41456	};
41457  
41458	QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
41459  
41460		Curve.prototype.fromJSON.call( this, json );
41461  
41462		this.v0.fromArray( json.v0 );
41463		this.v1.fromArray( json.v1 );
41464		this.v2.fromArray( json.v2 );
41465  
41466		return this;
41467  
41468	};
41469  
41470	function QuadraticBezierCurve3( v0, v1, v2 ) {
41471  
41472		Curve.call( this );
41473  
41474		this.type = 'QuadraticBezierCurve3';
41475  
41476		this.v0 = v0 || new Vector3();
41477		this.v1 = v1 || new Vector3();
41478		this.v2 = v2 || new Vector3();
41479  
41480	}
41481  
41482	QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
41483	QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
41484  
41485	QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
41486  
41487	QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
41488  
41489		var point = optionalTarget || new Vector3();
41490  
41491		var v0 = this.v0, v1 = this.v1, v2 = this.v2;
41492  
41493		point.set(
41494			QuadraticBezier( t, v0.x, v1.x, v2.x ),
41495			QuadraticBezier( t, v0.y, v1.y, v2.y ),
41496			QuadraticBezier( t, v0.z, v1.z, v2.z )
41497		);
41498  
41499		return point;
41500  
41501	};
41502  
41503	QuadraticBezierCurve3.prototype.copy = function ( source ) {
41504  
41505		Curve.prototype.copy.call( this, source );
41506  
41507		this.v0.copy( source.v0 );
41508		this.v1.copy( source.v1 );
41509		this.v2.copy( source.v2 );
41510  
41511		return this;
41512  
41513	};
41514  
41515	QuadraticBezierCurve3.prototype.toJSON = function () {
41516  
41517		var data = Curve.prototype.toJSON.call( this );
41518  
41519		data.v0 = this.v0.toArray();
41520		data.v1 = this.v1.toArray();
41521		data.v2 = this.v2.toArray();
41522  
41523		return data;
41524  
41525	};
41526  
41527	QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
41528  
41529		Curve.prototype.fromJSON.call( this, json );
41530  
41531		this.v0.fromArray( json.v0 );
41532		this.v1.fromArray( json.v1 );
41533		this.v2.fromArray( json.v2 );
41534  
41535		return this;
41536  
41537	};
41538  
41539	function SplineCurve( points /* array of Vector2 */ ) {
41540  
41541		Curve.call( this );
41542  
41543		this.type = 'SplineCurve';
41544  
41545		this.points = points || [];
41546  
41547	}
41548  
41549	SplineCurve.prototype = Object.create( Curve.prototype );
41550	SplineCurve.prototype.constructor = SplineCurve;
41551  
41552	SplineCurve.prototype.isSplineCurve = true;
41553  
41554	SplineCurve.prototype.getPoint = function ( t, optionalTarget ) {
41555  
41556		var point = optionalTarget || new Vector2();
41557  
41558		var points = this.points;
41559		var p = ( points.length - 1 ) * t;
41560  
41561		var intPoint = Math.floor( p );
41562		var weight = p - intPoint;
41563  
41564		var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
41565		var p1 = points[ intPoint ];
41566		var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
41567		var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
41568  
41569		point.set(
41570			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
41571			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
41572		);
41573  
41574		return point;
41575  
41576	};
41577  
41578	SplineCurve.prototype.copy = function ( source ) {
41579  
41580		Curve.prototype.copy.call( this, source );
41581  
41582		this.points = [];
41583  
41584		for ( var i = 0, l = source.points.length; i < l; i ++ ) {
41585  
41586			var point = source.points[ i ];
41587  
41588			this.points.push( point.clone() );
41589  
41590		}
41591  
41592		return this;
41593  
41594	};
41595  
41596	SplineCurve.prototype.toJSON = function () {
41597  
41598		var data = Curve.prototype.toJSON.call( this );
41599  
41600		data.points = [];
41601  
41602		for ( var i = 0, l = this.points.length; i < l; i ++ ) {
41603  
41604			var point = this.points[ i ];
41605			data.points.push( point.toArray() );
41606  
41607		}
41608  
41609		return data;
41610  
41611	};
41612  
41613	SplineCurve.prototype.fromJSON = function ( json ) {
41614  
41615		Curve.prototype.fromJSON.call( this, json );
41616  
41617		this.points = [];
41618  
41619		for ( var i = 0, l = json.points.length; i < l; i ++ ) {
41620  
41621			var point = json.points[ i ];
41622			this.points.push( new Vector2().fromArray( point ) );
41623  
41624		}
41625  
41626		return this;
41627  
41628	};
41629  
41630  
41631  
41632	var Curves = /*#__PURE__*/Object.freeze({
41633		ArcCurve: ArcCurve,
41634		CatmullRomCurve3: CatmullRomCurve3,
41635		CubicBezierCurve: CubicBezierCurve,
41636		CubicBezierCurve3: CubicBezierCurve3,
41637		EllipseCurve: EllipseCurve,
41638		LineCurve: LineCurve,
41639		LineCurve3: LineCurve3,
41640		QuadraticBezierCurve: QuadraticBezierCurve,
41641		QuadraticBezierCurve3: QuadraticBezierCurve3,
41642		SplineCurve: SplineCurve
41643	});
41644  
41645	/**
41646	 * @author zz85 / http://www.lab4games.net/zz85/blog
41647	 *
41648	 **/
41649  
41650	/**************************************************************
41651	 *	Curved Path - a curve path is simply a array of connected
41652	 *  curves, but retains the api of a curve
41653	 **************************************************************/
41654  
41655	function CurvePath() {
41656  
41657		Curve.call( this );
41658  
41659		this.type = 'CurvePath';
41660  
41661		this.curves = [];
41662		this.autoClose = false; // Automatically closes the path
41663  
41664	}
41665  
41666	CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
41667  
41668		constructor: CurvePath,
41669  
41670		add: function ( curve ) {
41671  
41672			this.curves.push( curve );
41673  
41674		},
41675  
41676		closePath: function () {
41677  
41678			// Add a line curve if start and end of lines are not connected
41679			var startPoint = this.curves[ 0 ].getPoint( 0 );
41680			var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
41681  
41682			if ( ! startPoint.equals( endPoint ) ) {
41683  
41684				this.curves.push( new LineCurve( endPoint, startPoint ) );
41685  
41686			}
41687  
41688		},
41689  
41690		// To get accurate point with reference to
41691		// entire path distance at time t,
41692		// following has to be done:
41693  
41694		// 1. Length of each sub path have to be known
41695		// 2. Locate and identify type of curve
41696		// 3. Get t for the curve
41697		// 4. Return curve.getPointAt(t')
41698  
41699		getPoint: function ( t ) {
41700  
41701			var d = t * this.getLength();
41702			var curveLengths = this.getCurveLengths();
41703			var i = 0;
41704  
41705			// To think about boundaries points.
41706  
41707			while ( i < curveLengths.length ) {
41708  
41709				if ( curveLengths[ i ] >= d ) {
41710  
41711					var diff = curveLengths[ i ] - d;
41712					var curve = this.curves[ i ];
41713  
41714					var segmentLength = curve.getLength();
41715					var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
41716  
41717					return curve.getPointAt( u );
41718  
41719				}
41720  
41721				i ++;
41722  
41723			}
41724  
41725			return null;
41726  
41727			// loop where sum != 0, sum > d , sum+1 <d
41728  
41729		},
41730  
41731		// We cannot use the default THREE.Curve getPoint() with getLength() because in
41732		// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
41733		// getPoint() depends on getLength
41734  
41735		getLength: function () {
41736  
41737			var lens = this.getCurveLengths();
41738			return lens[ lens.length - 1 ];
41739  
41740		},
41741  
41742		// cacheLengths must be recalculated.
41743		updateArcLengths: function () {
41744  
41745			this.needsUpdate = true;
41746			this.cacheLengths = null;
41747			this.getCurveLengths();
41748  
41749		},
41750  
41751		// Compute lengths and cache them
41752		// We cannot overwrite getLengths() because UtoT mapping uses it.
41753  
41754		getCurveLengths: function () {
41755  
41756			// We use cache values if curves and cache array are same length
41757  
41758			if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
41759  
41760				return this.cacheLengths;
41761  
41762			}
41763  
41764			// Get length of sub-curve
41765			// Push sums into cached array
41766  
41767			var lengths = [], sums = 0;
41768  
41769			for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
41770  
41771				sums += this.curves[ i ].getLength();
41772				lengths.push( sums );
41773  
41774			}
41775  
41776			this.cacheLengths = lengths;
41777  
41778			return lengths;
41779  
41780		},
41781  
41782		getSpacedPoints: function ( divisions ) {
41783  
41784			if ( divisions === undefined ) divisions = 40;
41785  
41786			var points = [];
41787  
41788			for ( var i = 0; i <= divisions; i ++ ) {
41789  
41790				points.push( this.getPoint( i / divisions ) );
41791  
41792			}
41793  
41794			if ( this.autoClose ) {
41795  
41796				points.push( points[ 0 ] );
41797  
41798			}
41799  
41800			return points;
41801  
41802		},
41803  
41804		getPoints: function ( divisions ) {
41805  
41806			divisions = divisions || 12;
41807  
41808			var points = [], last;
41809  
41810			for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
41811  
41812				var curve = curves[ i ];
41813				var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
41814					: ( curve && curve.isLineCurve ) ? 1
41815						: ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
41816							: divisions;
41817  
41818				var pts = curve.getPoints( resolution );
41819  
41820				for ( var j = 0; j < pts.length; j ++ ) {
41821  
41822					var point = pts[ j ];
41823  
41824					if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
41825  
41826					points.push( point );
41827					last = point;
41828  
41829				}
41830  
41831			}
41832  
41833			if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
41834  
41835				points.push( points[ 0 ] );
41836  
41837			}
41838  
41839			return points;
41840  
41841		},
41842  
41843		copy: function ( source ) {
41844  
41845			Curve.prototype.copy.call( this, source );
41846  
41847			this.curves = [];
41848  
41849			for ( var i = 0, l = source.curves.length; i < l; i ++ ) {
41850  
41851				var curve = source.curves[ i ];
41852  
41853				this.curves.push( curve.clone() );
41854  
41855			}
41856  
41857			this.autoClose = source.autoClose;
41858  
41859			return this;
41860  
41861		},
41862  
41863		toJSON: function () {
41864  
41865			var data = Curve.prototype.toJSON.call( this );
41866  
41867			data.autoClose = this.autoClose;
41868			data.curves = [];
41869  
41870			for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
41871  
41872				var curve = this.curves[ i ];
41873				data.curves.push( curve.toJSON() );
41874  
41875			}
41876  
41877			return data;
41878  
41879		},
41880  
41881		fromJSON: function ( json ) {
41882  
41883			Curve.prototype.fromJSON.call( this, json );
41884  
41885			this.autoClose = json.autoClose;
41886			this.curves = [];
41887  
41888			for ( var i = 0, l = json.curves.length; i < l; i ++ ) {
41889  
41890				var curve = json.curves[ i ];
41891				this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
41892  
41893			}
41894  
41895			return this;
41896  
41897		}
41898  
41899	} );
41900  
41901	/**
41902	 * @author zz85 / http://www.lab4games.net/zz85/blog
41903	 * Creates free form 2d path using series of points, lines or curves.
41904	 **/
41905  
41906	function Path( points ) {
41907  
41908		CurvePath.call( this );
41909  
41910		this.type = 'Path';
41911  
41912		this.currentPoint = new Vector2();
41913  
41914		if ( points ) {
41915  
41916			this.setFromPoints( points );
41917  
41918		}
41919  
41920	}
41921  
41922	Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
41923  
41924		constructor: Path,
41925  
41926		setFromPoints: function ( points ) {
41927  
41928			this.moveTo( points[ 0 ].x, points[ 0 ].y );
41929  
41930			for ( var i = 1, l = points.length; i < l; i ++ ) {
41931  
41932				this.lineTo( points[ i ].x, points[ i ].y );
41933  
41934			}
41935  
41936		},
41937  
41938		moveTo: function ( x, y ) {
41939  
41940			this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
41941  
41942		},
41943  
41944		lineTo: function ( x, y ) {
41945  
41946			var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
41947			this.curves.push( curve );
41948  
41949			this.currentPoint.set( x, y );
41950  
41951		},
41952  
41953		quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
41954  
41955			var curve = new QuadraticBezierCurve(
41956				this.currentPoint.clone(),
41957				new Vector2( aCPx, aCPy ),
41958				new Vector2( aX, aY )
41959			);
41960  
41961			this.curves.push( curve );
41962  
41963			this.currentPoint.set( aX, aY );
41964  
41965		},
41966  
41967		bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
41968  
41969			var curve = new CubicBezierCurve(
41970				this.currentPoint.clone(),
41971				new Vector2( aCP1x, aCP1y ),
41972				new Vector2( aCP2x, aCP2y ),
41973				new Vector2( aX, aY )
41974			);
41975  
41976			this.curves.push( curve );
41977  
41978			this.currentPoint.set( aX, aY );
41979  
41980		},
41981  
41982		splineThru: function ( pts /*Array of Vector*/ ) {
41983  
41984			var npts = [ this.currentPoint.clone() ].concat( pts );
41985  
41986			var curve = new SplineCurve( npts );
41987			this.curves.push( curve );
41988  
41989			this.currentPoint.copy( pts[ pts.length - 1 ] );
41990  
41991		},
41992  
41993		arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
41994  
41995			var x0 = this.currentPoint.x;
41996			var y0 = this.currentPoint.y;
41997  
41998			this.absarc( aX + x0, aY + y0, aRadius,
41999				aStartAngle, aEndAngle, aClockwise );
42000  
42001		},
42002  
42003		absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
42004  
42005			this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
42006  
42007		},
42008  
42009		ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
42010  
42011			var x0 = this.currentPoint.x;
42012			var y0 = this.currentPoint.y;
42013  
42014			this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
42015  
42016		},
42017  
42018		absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
42019  
42020			var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
42021  
42022			if ( this.curves.length > 0 ) {
42023  
42024				// if a previous curve is present, attempt to join
42025				var firstPoint = curve.getPoint( 0 );
42026  
42027				if ( ! firstPoint.equals( this.currentPoint ) ) {
42028  
42029					this.lineTo( firstPoint.x, firstPoint.y );
42030  
42031				}
42032  
42033			}
42034  
42035			this.curves.push( curve );
42036  
42037			var lastPoint = curve.getPoint( 1 );
42038			this.currentPoint.copy( lastPoint );
42039  
42040		},
42041  
42042		copy: function ( source ) {
42043  
42044			CurvePath.prototype.copy.call( this, source );
42045  
42046			this.currentPoint.copy( source.currentPoint );
42047  
42048			return this;
42049  
42050		},
42051  
42052		toJSON: function () {
42053  
42054			var data = CurvePath.prototype.toJSON.call( this );
42055  
42056			data.currentPoint = this.currentPoint.toArray();
42057  
42058			return data;
42059  
42060		},
42061  
42062		fromJSON: function ( json ) {
42063  
42064			CurvePath.prototype.fromJSON.call( this, json );
42065  
42066			this.currentPoint.fromArray( json.currentPoint );
42067  
42068			return this;
42069  
42070		}
42071  
42072	} );
42073  
42074	/**
42075	 * @author zz85 / http://www.lab4games.net/zz85/blog
42076	 * Defines a 2d shape plane using paths.
42077	 **/
42078  
42079	// STEP 1 Create a path.
42080	// STEP 2 Turn path into shape.
42081	// STEP 3 ExtrudeGeometry takes in Shape/Shapes
42082	// STEP 3a - Extract points from each shape, turn to vertices
42083	// STEP 3b - Triangulate each shape, add faces.
42084  
42085	function Shape( points ) {
42086  
42087		Path.call( this, points );
42088  
42089		this.uuid = _Math.generateUUID();
42090  
42091		this.type = 'Shape';
42092  
42093		this.holes = [];
42094  
42095	}
42096  
42097	Shape.prototype = Object.assign( Object.create( Path.prototype ), {
42098  
42099		constructor: Shape,
42100  
42101		getPointsHoles: function ( divisions ) {
42102  
42103			var holesPts = [];
42104  
42105			for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
42106  
42107				holesPts[ i ] = this.holes[ i ].getPoints( divisions );
42108  
42109			}
42110  
42111			return holesPts;
42112  
42113		},
42114  
42115		// get points of shape and holes (keypoints based on segments parameter)
42116  
42117		extractPoints: function ( divisions ) {
42118  
42119			return {
42120  
42121				shape: this.getPoints( divisions ),
42122				holes: this.getPointsHoles( divisions )
42123  
42124			};
42125  
42126		},
42127  
42128		copy: function ( source ) {
42129  
42130			Path.prototype.copy.call( this, source );
42131  
42132			this.holes = [];
42133  
42134			for ( var i = 0, l = source.holes.length; i < l; i ++ ) {
42135  
42136				var hole = source.holes[ i ];
42137  
42138				this.holes.push( hole.clone() );
42139  
42140			}
42141  
42142			return this;
42143  
42144		},
42145  
42146		toJSON: function () {
42147  
42148			var data = Path.prototype.toJSON.call( this );
42149  
42150			data.uuid = this.uuid;
42151			data.holes = [];
42152  
42153			for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
42154  
42155				var hole = this.holes[ i ];
42156				data.holes.push( hole.toJSON() );
42157  
42158			}
42159  
42160			return data;
42161  
42162		},
42163  
42164		fromJSON: function ( json ) {
42165  
42166			Path.prototype.fromJSON.call( this, json );
42167  
42168			this.uuid = json.uuid;
42169			this.holes = [];
42170  
42171			for ( var i = 0, l = json.holes.length; i < l; i ++ ) {
42172  
42173				var hole = json.holes[ i ];
42174				this.holes.push( new Path().fromJSON( hole ) );
42175  
42176			}
42177  
42178			return this;
42179  
42180		}
42181  
42182	} );
42183  
42184	/**
42185	 * @author mrdoob / http://mrdoob.com/
42186	 * @author alteredq / http://alteredqualia.com/
42187	 */
42188  
42189	function Light( color, intensity ) {
42190  
42191		Object3D.call( this );
42192  
42193		this.type = 'Light';
42194  
42195		this.color = new Color( color );
42196		this.intensity = intensity !== undefined ? intensity : 1;
42197  
42198		this.receiveShadow = undefined;
42199  
42200	}
42201  
42202	Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
42203  
42204		constructor: Light,
42205  
42206		isLight: true,
42207  
42208		copy: function ( source ) {
42209  
42210			Object3D.prototype.copy.call( this, source );
42211  
42212			this.color.copy( source.color );
42213			this.intensity = source.intensity;
42214  
42215			return this;
42216  
42217		},
42218  
42219		toJSON: function ( meta ) {
42220  
42221			var data = Object3D.prototype.toJSON.call( this, meta );
42222  
42223			data.object.color = this.color.getHex();
42224			data.object.intensity = this.intensity;
42225  
42226			if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
42227  
42228			if ( this.distance !== undefined ) data.object.distance = this.distance;
42229			if ( this.angle !== undefined ) data.object.angle = this.angle;
42230			if ( this.decay !== undefined ) data.object.decay = this.decay;
42231			if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
42232  
42233			if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
42234  
42235			return data;
42236  
42237		}
42238  
42239	} );
42240  
42241	/**
42242	 * @author alteredq / http://alteredqualia.com/
42243	 */
42244  
42245	function HemisphereLight( skyColor, groundColor, intensity ) {
42246  
42247		Light.call( this, skyColor, intensity );
42248  
42249		this.type = 'HemisphereLight';
42250  
42251		this.castShadow = undefined;
42252  
42253		this.position.copy( Object3D.DefaultUp );
42254		this.updateMatrix();
42255  
42256		this.groundColor = new Color( groundColor );
42257  
42258	}
42259  
42260	HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
42261  
42262		constructor: HemisphereLight,
42263  
42264		isHemisphereLight: true,
42265  
42266		copy: function ( source ) {
42267  
42268			Light.prototype.copy.call( this, source );
42269  
42270			this.groundColor.copy( source.groundColor );
42271  
42272			return this;
42273  
42274		}
42275  
42276	} );
42277  
42278	/**
42279	 * @author mrdoob / http://mrdoob.com/
42280	 */
42281  
42282	function LightShadow( camera ) {
42283  
42284		this.camera = camera;
42285  
42286		this.bias = 0;
42287		this.radius = 1;
42288  
42289		this.mapSize = new Vector2( 512, 512 );
42290  
42291		this.map = null;
42292		this.matrix = new Matrix4();
42293  
42294	}
42295  
42296	Object.assign( LightShadow.prototype, {
42297  
42298		copy: function ( source ) {
42299  
42300			this.camera = source.camera.clone();
42301  
42302			this.bias = source.bias;
42303			this.radius = source.radius;
42304  
42305			this.mapSize.copy( source.mapSize );
42306  
42307			return this;
42308  
42309		},
42310  
42311		clone: function () {
42312  
42313			return new this.constructor().copy( this );
42314  
42315		},
42316  
42317		toJSON: function () {
42318  
42319			var object = {};
42320  
42321			if ( this.bias !== 0 ) object.bias = this.bias;
42322			if ( this.radius !== 1 ) object.radius = this.radius;
42323			if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
42324  
42325			object.camera = this.camera.toJSON( false ).object;
42326			delete object.camera.matrix;
42327  
42328			return object;
42329  
42330		}
42331  
42332	} );
42333  
42334	/**
42335	 * @author mrdoob / http://mrdoob.com/
42336	 */
42337  
42338	function SpotLightShadow() {
42339  
42340		LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
42341  
42342	}
42343  
42344	SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
42345  
42346		constructor: SpotLightShadow,
42347  
42348		isSpotLightShadow: true,
42349  
42350		update: function ( light ) {
42351  
42352			var camera = this.camera;
42353  
42354			var fov = _Math.RAD2DEG * 2 * light.angle;
42355			var aspect = this.mapSize.width / this.mapSize.height;
42356			var far = light.distance || camera.far;
42357  
42358			if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
42359  
42360				camera.fov = fov;
42361				camera.aspect = aspect;
42362				camera.far = far;
42363				camera.updateProjectionMatrix();
42364  
42365			}
42366  
42367		}
42368  
42369	} );
42370  
42371	/**
42372	 * @author alteredq / http://alteredqualia.com/
42373	 */
42374  
42375	function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
42376  
42377		Light.call( this, color, intensity );
42378  
42379		this.type = 'SpotLight';
42380  
42381		this.position.copy( Object3D.DefaultUp );
42382		this.updateMatrix();
42383  
42384		this.target = new Object3D();
42385  
42386		Object.defineProperty( this, 'power', {
42387			get: function () {
42388  
42389				// intensity = power per solid angle.
42390				// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
42391				return this.intensity * Math.PI;
42392  
42393			},
42394			set: function ( power ) {
42395  
42396				// intensity = power per solid angle.
42397				// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
42398				this.intensity = power / Math.PI;
42399  
42400			}
42401		} );
42402  
42403		this.distance = ( distance !== undefined ) ? distance : 0;
42404		this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
42405		this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
42406		this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
42407  
42408		this.shadow = new SpotLightShadow();
42409  
42410	}
42411  
42412	SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
42413  
42414		constructor: SpotLight,
42415  
42416		isSpotLight: true,
42417  
42418		copy: function ( source ) {
42419  
42420			Light.prototype.copy.call( this, source );
42421  
42422			this.distance = source.distance;
42423			this.angle = source.angle;
42424			this.penumbra = source.penumbra;
42425			this.decay = source.decay;
42426  
42427			this.target = source.target.clone();
42428  
42429			this.shadow = source.shadow.clone();
42430  
42431			return this;
42432  
42433		}
42434  
42435	} );
42436  
42437	/**
42438	 * @author mrdoob / http://mrdoob.com/
42439	 */
42440  
42441  
42442	function PointLight( color, intensity, distance, decay ) {
42443  
42444		Light.call( this, color, intensity );
42445  
42446		this.type = 'PointLight';
42447  
42448		Object.defineProperty( this, 'power', {
42449			get: function () {
42450  
42451				// intensity = power per solid angle.
42452				// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
42453				return this.intensity * 4 * Math.PI;
42454  
42455			},
42456			set: function ( power ) {
42457  
42458				// intensity = power per solid angle.
42459				// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
42460				this.intensity = power / ( 4 * Math.PI );
42461  
42462			}
42463		} );
42464  
42465		this.distance = ( distance !== undefined ) ? distance : 0;
42466		this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
42467  
42468		this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
42469  
42470	}
42471  
42472	PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
42473  
42474		constructor: PointLight,
42475  
42476		isPointLight: true,
42477  
42478		copy: function ( source ) {
42479  
42480			Light.prototype.copy.call( this, source );
42481  
42482			this.distance = source.distance;
42483			this.decay = source.decay;
42484  
42485			this.shadow = source.shadow.clone();
42486  
42487			return this;
42488  
42489		}
42490  
42491	} );
42492  
42493	/**
42494	 * @author mrdoob / http://mrdoob.com/
42495	 */
42496  
42497	function DirectionalLightShadow( ) {
42498  
42499		LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
42500  
42501	}
42502  
42503	DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
42504  
42505		constructor: DirectionalLightShadow
42506  
42507	} );
42508  
42509	/**
42510	 * @author mrdoob / http://mrdoob.com/
42511	 * @author alteredq / http://alteredqualia.com/
42512	 */
42513  
42514	function DirectionalLight( color, intensity ) {
42515  
42516		Light.call( this, color, intensity );
42517  
42518		this.type = 'DirectionalLight';
42519  
42520		this.position.copy( Object3D.DefaultUp );
42521		this.updateMatrix();
42522  
42523		this.target = new Object3D();
42524  
42525		this.shadow = new DirectionalLightShadow();
42526  
42527	}
42528  
42529	DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
42530  
42531		constructor: DirectionalLight,
42532  
42533		isDirectionalLight: true,
42534  
42535		copy: function ( source ) {
42536  
42537			Light.prototype.copy.call( this, source );
42538  
42539			this.target = source.target.clone();
42540  
42541			this.shadow = source.shadow.clone();
42542  
42543			return this;
42544  
42545		}
42546  
42547	} );
42548  
42549	/**
42550	 * @author mrdoob / http://mrdoob.com/
42551	 */
42552  
42553	function AmbientLight( color, intensity ) {
42554  
42555		Light.call( this, color, intensity );
42556  
42557		this.type = 'AmbientLight';
42558  
42559		this.castShadow = undefined;
42560  
42561	}
42562  
42563	AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
42564  
42565		constructor: AmbientLight,
42566  
42567		isAmbientLight: true
42568  
42569	} );
42570  
42571	/**
42572	 * @author abelnation / http://github.com/abelnation
42573	 */
42574  
42575	function RectAreaLight( color, intensity, width, height ) {
42576  
42577		Light.call( this, color, intensity );
42578  
42579		this.type = 'RectAreaLight';
42580  
42581		this.width = ( width !== undefined ) ? width : 10;
42582		this.height = ( height !== undefined ) ? height : 10;
42583  
42584	}
42585  
42586	RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
42587  
42588		constructor: RectAreaLight,
42589  
42590		isRectAreaLight: true,
42591  
42592		copy: function ( source ) {
42593  
42594			Light.prototype.copy.call( this, source );
42595  
42596			this.width = source.width;
42597			this.height = source.height;
42598  
42599			return this;
42600  
42601		},
42602  
42603		toJSON: function ( meta ) {
42604  
42605			var data = Light.prototype.toJSON.call( this, meta );
42606  
42607			data.object.width = this.width;
42608			data.object.height = this.height;
42609  
42610			return data;
42611  
42612		}
42613  
42614	} );
42615  
42616	/**
42617	 *
42618	 * A Track that interpolates Strings
42619	 *
42620	 *
42621	 * @author Ben Houston / http://clara.io/
42622	 * @author David Sarno / http://lighthaus.us/
42623	 * @author tschw
42624	 */
42625  
42626	function StringKeyframeTrack( name, times, values, interpolation ) {
42627  
42628		KeyframeTrack.call( this, name, times, values, interpolation );
42629  
42630	}
42631  
42632	StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
42633  
42634		constructor: StringKeyframeTrack,
42635  
42636		ValueTypeName: 'string',
42637		ValueBufferType: Array,
42638  
42639		DefaultInterpolation: InterpolateDiscrete,
42640  
42641		InterpolantFactoryMethodLinear: undefined,
42642  
42643		InterpolantFactoryMethodSmooth: undefined
42644  
42645	} );
42646  
42647	/**
42648	 *
42649	 * A Track of Boolean keyframe values.
42650	 *
42651	 *
42652	 * @author Ben Houston / http://clara.io/
42653	 * @author David Sarno / http://lighthaus.us/
42654	 * @author tschw
42655	 */
42656  
42657	function BooleanKeyframeTrack( name, times, values ) {
42658  
42659		KeyframeTrack.call( this, name, times, values );
42660  
42661	}
42662  
42663	BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
42664  
42665		constructor: BooleanKeyframeTrack,
42666  
42667		ValueTypeName: 'bool',
42668		ValueBufferType: Array,
42669  
42670		DefaultInterpolation: InterpolateDiscrete,
42671  
42672		InterpolantFactoryMethodLinear: undefined,
42673		InterpolantFactoryMethodSmooth: undefined
42674  
42675		// Note: Actually this track could have a optimized / compressed
42676		// representation of a single value and a custom interpolant that
42677		// computes "firstValue ^ isOdd( index )".
42678  
42679	} );
42680  
42681	/**
42682	 * Abstract base class of interpolants over parametric samples.
42683	 *
42684	 * The parameter domain is one dimensional, typically the time or a path
42685	 * along a curve defined by the data.
42686	 *
42687	 * The sample values can have any dimensionality and derived classes may
42688	 * apply special interpretations to the data.
42689	 *
42690	 * This class provides the interval seek in a Template Method, deferring
42691	 * the actual interpolation to derived classes.
42692	 *
42693	 * Time complexity is O(1) for linear access crossing at most two points
42694	 * and O(log N) for random access, where N is the number of positions.
42695	 *
42696	 * References:
42697	 *
42698	 * 		http://www.oodesign.com/template-method-pattern.html
42699	 *
42700	 * @author tschw
42701	 */
42702  
42703	function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42704  
42705		this.parameterPositions = parameterPositions;
42706		this._cachedIndex = 0;
42707  
42708		this.resultBuffer = resultBuffer !== undefined ?
42709			resultBuffer : new sampleValues.constructor( sampleSize );
42710		this.sampleValues = sampleValues;
42711		this.valueSize = sampleSize;
42712  
42713	}
42714  
42715	Object.assign( Interpolant.prototype, {
42716  
42717		evaluate: function ( t ) {
42718  
42719			var pp = this.parameterPositions,
42720				i1 = this._cachedIndex,
42721  
42722				t1 = pp[ i1 ],
42723				t0 = pp[ i1 - 1 ];
42724  
42725			validate_interval: {
42726  
42727				seek: {
42728  
42729					var right;
42730  
42731					linear_scan: {
42732  
42733						//- See http://jsperf.com/comparison-to-undefined/3
42734						//- slower code:
42735						//-
42736						//- 				if ( t >= t1 || t1 === undefined ) {
42737						forward_scan: if ( ! ( t < t1 ) ) {
42738  
42739							for ( var giveUpAt = i1 + 2; ; ) {
42740  
42741								if ( t1 === undefined ) {
42742  
42743									if ( t < t0 ) break forward_scan;
42744  
42745									// after end
42746  
42747									i1 = pp.length;
42748									this._cachedIndex = i1;
42749									return this.afterEnd_( i1 - 1, t, t0 );
42750  
42751								}
42752  
42753								if ( i1 === giveUpAt ) break; // this loop
42754  
42755								t0 = t1;
42756								t1 = pp[ ++ i1 ];
42757  
42758								if ( t < t1 ) {
42759  
42760									// we have arrived at the sought interval
42761									break seek;
42762  
42763								}
42764  
42765							}
42766  
42767							// prepare binary search on the right side of the index
42768							right = pp.length;
42769							break linear_scan;
42770  
42771						}
42772  
42773						//- slower code:
42774						//-					if ( t < t0 || t0 === undefined ) {
42775						if ( ! ( t >= t0 ) ) {
42776  
42777							// looping?
42778  
42779							var t1global = pp[ 1 ];
42780  
42781							if ( t < t1global ) {
42782  
42783								i1 = 2; // + 1, using the scan for the details
42784								t0 = t1global;
42785  
42786							}
42787  
42788							// linear reverse scan
42789  
42790							for ( var giveUpAt = i1 - 2; ; ) {
42791  
42792								if ( t0 === undefined ) {
42793  
42794									// before start
42795  
42796									this._cachedIndex = 0;
42797									return this.beforeStart_( 0, t, t1 );
42798  
42799								}
42800  
42801								if ( i1 === giveUpAt ) break; // this loop
42802  
42803								t1 = t0;
42804								t0 = pp[ -- i1 - 1 ];
42805  
42806								if ( t >= t0 ) {
42807  
42808									// we have arrived at the sought interval
42809									break seek;
42810  
42811								}
42812  
42813							}
42814  
42815							// prepare binary search on the left side of the index
42816							right = i1;
42817							i1 = 0;
42818							break linear_scan;
42819  
42820						}
42821  
42822						// the interval is valid
42823  
42824						break validate_interval;
42825  
42826					} // linear scan
42827  
42828					// binary search
42829  
42830					while ( i1 < right ) {
42831  
42832						var mid = ( i1 + right ) >>> 1;
42833  
42834						if ( t < pp[ mid ] ) {
42835  
42836							right = mid;
42837  
42838						} else {
42839  
42840							i1 = mid + 1;
42841  
42842						}
42843  
42844					}
42845  
42846					t1 = pp[ i1 ];
42847					t0 = pp[ i1 - 1 ];
42848  
42849					// check boundary cases, again
42850  
42851					if ( t0 === undefined ) {
42852  
42853						this._cachedIndex = 0;
42854						return this.beforeStart_( 0, t, t1 );
42855  
42856					}
42857  
42858					if ( t1 === undefined ) {
42859  
42860						i1 = pp.length;
42861						this._cachedIndex = i1;
42862						return this.afterEnd_( i1 - 1, t0, t );
42863  
42864					}
42865  
42866				} // seek
42867  
42868				this._cachedIndex = i1;
42869  
42870				this.intervalChanged_( i1, t0, t1 );
42871  
42872			} // validate_interval
42873  
42874			return this.interpolate_( i1, t0, t, t1 );
42875  
42876		},
42877  
42878		settings: null, // optional, subclass-specific settings structure
42879		// Note: The indirection allows central control of many interpolants.
42880  
42881		// --- Protected interface
42882  
42883		DefaultSettings_: {},
42884  
42885		getSettings_: function () {
42886  
42887			return this.settings || this.DefaultSettings_;
42888  
42889		},
42890  
42891		copySampleValue_: function ( index ) {
42892  
42893			// copies a sample value to the result buffer
42894  
42895			var result = this.resultBuffer,
42896				values = this.sampleValues,
42897				stride = this.valueSize,
42898				offset = index * stride;
42899  
42900			for ( var i = 0; i !== stride; ++ i ) {
42901  
42902				result[ i ] = values[ offset + i ];
42903  
42904			}
42905  
42906			return result;
42907  
42908		},
42909  
42910		// Template methods for derived classes:
42911  
42912		interpolate_: function ( /* i1, t0, t, t1 */ ) {
42913  
42914			throw new Error( 'call to abstract method' );
42915			// implementations shall return this.resultBuffer
42916  
42917		},
42918  
42919		intervalChanged_: function ( /* i1, t0, t1 */ ) {
42920  
42921			// empty
42922  
42923		}
42924  
42925	} );
42926  
42927	//!\ DECLARE ALIAS AFTER assign prototype !
42928	Object.assign( Interpolant.prototype, {
42929  
42930		//( 0, t, t0 ), returns this.resultBuffer
42931		beforeStart_: Interpolant.prototype.copySampleValue_,
42932  
42933		//( N-1, tN-1, t ), returns this.resultBuffer
42934		afterEnd_: Interpolant.prototype.copySampleValue_,
42935  
42936	} );
42937  
42938	/**
42939	 * Spherical linear unit quaternion interpolant.
42940	 *
42941	 * @author tschw
42942	 */
42943  
42944	function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42945  
42946		Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
42947  
42948	}
42949  
42950	QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
42951  
42952		constructor: QuaternionLinearInterpolant,
42953  
42954		interpolate_: function ( i1, t0, t, t1 ) {
42955  
42956			var result = this.resultBuffer,
42957				values = this.sampleValues,
42958				stride = this.valueSize,
42959  
42960				offset = i1 * stride,
42961  
42962				alpha = ( t - t0 ) / ( t1 - t0 );
42963  
42964			for ( var end = offset + stride; offset !== end; offset += 4 ) {
42965  
42966				Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
42967  
42968			}
42969  
42970			return result;
42971  
42972		}
42973  
42974	} );
42975  
42976	/**
42977	 *
42978	 * A Track of quaternion keyframe values.
42979	 *
42980	 * @author Ben Houston / http://clara.io/
42981	 * @author David Sarno / http://lighthaus.us/
42982	 * @author tschw
42983	 */
42984  
42985	function QuaternionKeyframeTrack( name, times, values, interpolation ) {
42986  
42987		KeyframeTrack.call( this, name, times, values, interpolation );
42988  
42989	}
42990  
42991	QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
42992  
42993		constructor: QuaternionKeyframeTrack,
42994  
42995		ValueTypeName: 'quaternion',
42996  
42997		// ValueBufferType is inherited
42998  
42999		DefaultInterpolation: InterpolateLinear,
43000  
43001		InterpolantFactoryMethodLinear: function ( result ) {
43002  
43003			return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
43004  
43005		},
43006  
43007		InterpolantFactoryMethodSmooth: undefined // not yet implemented
43008  
43009	} );
43010  
43011	/**
43012	 *
43013	 * A Track of keyframe values that represent color.
43014	 *
43015	 *
43016	 * @author Ben Houston / http://clara.io/
43017	 * @author David Sarno / http://lighthaus.us/
43018	 * @author tschw
43019	 */
43020  
43021	function ColorKeyframeTrack( name, times, values, interpolation ) {
43022  
43023		KeyframeTrack.call( this, name, times, values, interpolation );
43024  
43025	}
43026  
43027	ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
43028  
43029		constructor: ColorKeyframeTrack,
43030  
43031		ValueTypeName: 'color'
43032  
43033		// ValueBufferType is inherited
43034  
43035		// DefaultInterpolation is inherited
43036  
43037		// Note: Very basic implementation and nothing special yet.
43038		// However, this is the place for color space parameterization.
43039  
43040	} );
43041  
43042	/**
43043	 *
43044	 * A Track of numeric keyframe values.
43045	 *
43046	 * @author Ben Houston / http://clara.io/
43047	 * @author David Sarno / http://lighthaus.us/
43048	 * @author tschw
43049	 */
43050  
43051	function NumberKeyframeTrack( name, times, values, interpolation ) {
43052  
43053		KeyframeTrack.call( this, name, times, values, interpolation );
43054  
43055	}
43056  
43057	NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
43058  
43059		constructor: NumberKeyframeTrack,
43060  
43061		ValueTypeName: 'number'
43062  
43063		// ValueBufferType is inherited
43064  
43065		// DefaultInterpolation is inherited
43066  
43067	} );
43068  
43069	/**
43070	 * Fast and simple cubic spline interpolant.
43071	 *
43072	 * It was derived from a Hermitian construction setting the first derivative
43073	 * at each sample position to the linear slope between neighboring positions
43074	 * over their parameter interval.
43075	 *
43076	 * @author tschw
43077	 */
43078  
43079	function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
43080  
43081		Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
43082  
43083		this._weightPrev = - 0;
43084		this._offsetPrev = - 0;
43085		this._weightNext = - 0;
43086		this._offsetNext = - 0;
43087  
43088	}
43089  
43090	CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
43091  
43092		constructor: CubicInterpolant,
43093  
43094		DefaultSettings_: {
43095  
43096			endingStart: ZeroCurvatureEnding,
43097			endingEnd: ZeroCurvatureEnding
43098  
43099		},
43100  
43101		intervalChanged_: function ( i1, t0, t1 ) {
43102  
43103			var pp = this.parameterPositions,
43104				iPrev = i1 - 2,
43105				iNext = i1 + 1,
43106  
43107				tPrev = pp[ iPrev ],
43108				tNext = pp[ iNext ];
43109  
43110			if ( tPrev === undefined ) {
43111  
43112				switch ( this.getSettings_().endingStart ) {
43113  
43114					case ZeroSlopeEnding:
43115  
43116						// f'(t0) = 0
43117						iPrev = i1;
43118						tPrev = 2 * t0 - t1;
43119  
43120						break;
43121  
43122					case WrapAroundEnding:
43123  
43124						// use the other end of the curve
43125						iPrev = pp.length - 2;
43126						tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
43127  
43128						break;
43129  
43130					default: // ZeroCurvatureEnding
43131  
43132						// f''(t0) = 0 a.k.a. Natural Spline
43133						iPrev = i1;
43134						tPrev = t1;
43135  
43136				}
43137  
43138			}
43139  
43140			if ( tNext === undefined ) {
43141  
43142				switch ( this.getSettings_().endingEnd ) {
43143  
43144					case ZeroSlopeEnding:
43145  
43146						// f'(tN) = 0
43147						iNext = i1;
43148						tNext = 2 * t1 - t0;
43149  
43150						break;
43151  
43152					case WrapAroundEnding:
43153  
43154						// use the other end of the curve
43155						iNext = 1;
43156						tNext = t1 + pp[ 1 ] - pp[ 0 ];
43157  
43158						break;
43159  
43160					default: // ZeroCurvatureEnding
43161  
43162						// f''(tN) = 0, a.k.a. Natural Spline
43163						iNext = i1 - 1;
43164						tNext = t0;
43165  
43166				}
43167  
43168			}
43169  
43170			var halfDt = ( t1 - t0 ) * 0.5,
43171				stride = this.valueSize;
43172  
43173			this._weightPrev = halfDt / ( t0 - tPrev );
43174			this._weightNext = halfDt / ( tNext - t1 );
43175			this._offsetPrev = iPrev * stride;
43176			this._offsetNext = iNext * stride;
43177  
43178		},
43179  
43180		interpolate_: function ( i1, t0, t, t1 ) {
43181  
43182			var result = this.resultBuffer,
43183				values = this.sampleValues,
43184				stride = this.valueSize,
43185  
43186				o1 = i1 * stride,		o0 = o1 - stride,
43187				oP = this._offsetPrev, 	oN = this._offsetNext,
43188				wP = this._weightPrev,	wN = this._weightNext,
43189  
43190				p = ( t - t0 ) / ( t1 - t0 ),
43191				pp = p * p,
43192				ppp = pp * p;
43193  
43194			// evaluate polynomials
43195  
43196			var sP = - wP * ppp + 2 * wP * pp - wP * p;
43197			var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
43198			var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
43199			var sN = wN * ppp - wN * pp;
43200  
43201			// combine data linearly
43202  
43203			for ( var i = 0; i !== stride; ++ i ) {
43204  
43205				result[ i ] =
43206						sP * values[ oP + i ] +
43207						s0 * values[ o0 + i ] +
43208						s1 * values[ o1 + i ] +
43209						sN * values[ oN + i ];
43210  
43211			}
43212  
43213			return result;
43214  
43215		}
43216  
43217	} );
43218  
43219	/**
43220	 * @author tschw
43221	 */
43222  
43223	function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
43224  
43225		Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
43226  
43227	}
43228  
43229	LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
43230  
43231		constructor: LinearInterpolant,
43232  
43233		interpolate_: function ( i1, t0, t, t1 ) {
43234  
43235			var result = this.resultBuffer,
43236				values = this.sampleValues,
43237				stride = this.valueSize,
43238  
43239				offset1 = i1 * stride,
43240				offset0 = offset1 - stride,
43241  
43242				weight1 = ( t - t0 ) / ( t1 - t0 ),
43243				weight0 = 1 - weight1;
43244  
43245			for ( var i = 0; i !== stride; ++ i ) {
43246  
43247				result[ i ] =
43248						values[ offset0 + i ] * weight0 +
43249						values[ offset1 + i ] * weight1;
43250  
43251			}
43252  
43253			return result;
43254  
43255		}
43256  
43257	} );
43258  
43259	/**
43260	 *
43261	 * Interpolant that evaluates to the sample value at the position preceeding
43262	 * the parameter.
43263	 *
43264	 * @author tschw
43265	 */
43266  
43267	function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
43268  
43269		Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
43270  
43271	}
43272  
43273	DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
43274  
43275		constructor: DiscreteInterpolant,
43276  
43277		interpolate_: function ( i1 /*, t0, t, t1 */ ) {
43278  
43279			return this.copySampleValue_( i1 - 1 );
43280  
43281		}
43282  
43283	} );
43284  
43285	/**
43286	 * @author tschw
43287	 * @author Ben Houston / http://clara.io/
43288	 * @author David Sarno / http://lighthaus.us/
43289	 */
43290  
43291	var AnimationUtils = {
43292  
43293		// same as Array.prototype.slice, but also works on typed arrays
43294		arraySlice: function ( array, from, to ) {
43295  
43296			if ( AnimationUtils.isTypedArray( array ) ) {
43297  
43298				// in ios9 array.subarray(from, undefined) will return empty array
43299				// but array.subarray(from) or array.subarray(from, len) is correct
43300				return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
43301  
43302			}
43303  
43304			return array.slice( from, to );
43305  
43306		},
43307  
43308		// converts an array to a specific type
43309		convertArray: function ( array, type, forceClone ) {
43310  
43311			if ( ! array || // let 'undefined' and 'null' pass
43312					! forceClone && array.constructor === type ) return array;
43313  
43314			if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
43315  
43316				return new type( array ); // create typed array
43317  
43318			}
43319  
43320			return Array.prototype.slice.call( array ); // create Array
43321  
43322		},
43323  
43324		isTypedArray: function ( object ) {
43325  
43326			return ArrayBuffer.isView( object ) &&
43327					! ( object instanceof DataView );
43328  
43329		},
43330  
43331		// returns an array by which times and values can be sorted
43332		getKeyframeOrder: function ( times ) {
43333  
43334			function compareTime( i, j ) {
43335  
43336				return times[ i ] - times[ j ];
43337  
43338			}
43339  
43340			var n = times.length;
43341			var result = new Array( n );
43342			for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
43343  
43344			result.sort( compareTime );
43345  
43346			return result;
43347  
43348		},
43349  
43350		// uses the array previously returned by 'getKeyframeOrder' to sort data
43351		sortedArray: function ( values, stride, order ) {
43352  
43353			var nValues = values.length;
43354			var result = new values.constructor( nValues );
43355  
43356			for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
43357  
43358				var srcOffset = order[ i ] * stride;
43359  
43360				for ( var j = 0; j !== stride; ++ j ) {
43361  
43362					result[ dstOffset ++ ] = values[ srcOffset + j ];
43363  
43364				}
43365  
43366			}
43367  
43368			return result;
43369  
43370		},
43371  
43372		// function for parsing AOS keyframe formats
43373		flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
43374  
43375			var i = 1, key = jsonKeys[ 0 ];
43376  
43377			while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
43378  
43379				key = jsonKeys[ i ++ ];
43380  
43381			}
43382  
43383			if ( key === undefined ) return; // no data
43384  
43385			var value = key[ valuePropertyName ];
43386			if ( value === undefined ) return; // no data
43387  
43388			if ( Array.isArray( value ) ) {
43389  
43390				do {
43391  
43392					value = key[ valuePropertyName ];
43393  
43394					if ( value !== undefined ) {
43395  
43396						times.push( key.time );
43397						values.push.apply( values, value ); // push all elements
43398  
43399					}
43400  
43401					key = jsonKeys[ i ++ ];
43402  
43403				} while ( key !== undefined );
43404  
43405			} else if ( value.toArray !== undefined ) {
43406  
43407				// ...assume THREE.Math-ish
43408  
43409				do {
43410  
43411					value = key[ valuePropertyName ];
43412  
43413					if ( value !== undefined ) {
43414  
43415						times.push( key.time );
43416						value.toArray( values, values.length );
43417  
43418					}
43419  
43420					key = jsonKeys[ i ++ ];
43421  
43422				} while ( key !== undefined );
43423  
43424			} else {
43425  
43426				// otherwise push as-is
43427  
43428				do {
43429  
43430					value = key[ valuePropertyName ];
43431  
43432					if ( value !== undefined ) {
43433  
43434						times.push( key.time );
43435						values.push( value );
43436  
43437					}
43438  
43439					key = jsonKeys[ i ++ ];
43440  
43441				} while ( key !== undefined );
43442  
43443			}
43444  
43445		}
43446  
43447	};
43448  
43449	/**
43450	 *
43451	 * A timed sequence of keyframes for a specific property.
43452	 *
43453	 *
43454	 * @author Ben Houston / http://clara.io/
43455	 * @author David Sarno / http://lighthaus.us/
43456	 * @author tschw
43457	 */
43458  
43459	function KeyframeTrack( name, times, values, interpolation ) {
43460  
43461		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
43462		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
43463  
43464		this.name = name;
43465  
43466		this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
43467		this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
43468  
43469		this.setInterpolation( interpolation || this.DefaultInterpolation );
43470  
43471		this.validate();
43472		this.optimize();
43473  
43474	}
43475  
43476	// Static methods:
43477  
43478	Object.assign( KeyframeTrack, {
43479  
43480		// Serialization (in static context, because of constructor invocation
43481		// and automatic invocation of .toJSON):
43482  
43483		parse: function ( json ) {
43484  
43485			if ( json.type === undefined ) {
43486  
43487				throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
43488  
43489			}
43490  
43491			var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type );
43492  
43493			if ( json.times === undefined ) {
43494  
43495				var times = [], values = [];
43496  
43497				AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
43498  
43499				json.times = times;
43500				json.values = values;
43501  
43502			}
43503  
43504			// derived classes can define a static parse method
43505			if ( trackType.parse !== undefined ) {
43506  
43507				return trackType.parse( json );
43508  
43509			} else {
43510  
43511				// by default, we assume a constructor compatible with the base
43512				return new trackType( json.name, json.times, json.values, json.interpolation );
43513  
43514			}
43515  
43516		},
43517  
43518		toJSON: function ( track ) {
43519  
43520			var trackType = track.constructor;
43521  
43522			var json;
43523  
43524			// derived classes can define a static toJSON method
43525			if ( trackType.toJSON !== undefined ) {
43526  
43527				json = trackType.toJSON( track );
43528  
43529			} else {
43530  
43531				// by default, we assume the data can be serialized as-is
43532				json = {
43533  
43534					'name': track.name,
43535					'times': AnimationUtils.convertArray( track.times, Array ),
43536					'values': AnimationUtils.convertArray( track.values, Array )
43537  
43538				};
43539  
43540				var interpolation = track.getInterpolation();
43541  
43542				if ( interpolation !== track.DefaultInterpolation ) {
43543  
43544					json.interpolation = interpolation;
43545  
43546				}
43547  
43548			}
43549  
43550			json.type = track.ValueTypeName; // mandatory
43551  
43552			return json;
43553  
43554		},
43555  
43556		_getTrackTypeForValueTypeName: function ( typeName ) {
43557  
43558			switch ( typeName.toLowerCase() ) {
43559  
43560				case 'scalar':
43561				case 'double':
43562				case 'float':
43563				case 'number':
43564				case 'integer':
43565  
43566					return NumberKeyframeTrack;
43567  
43568				case 'vector':
43569				case 'vector2':
43570				case 'vector3':
43571				case 'vector4':
43572  
43573					return VectorKeyframeTrack;
43574  
43575				case 'color':
43576  
43577					return ColorKeyframeTrack;
43578  
43579				case 'quaternion':
43580  
43581					return QuaternionKeyframeTrack;
43582  
43583				case 'bool':
43584				case 'boolean':
43585  
43586					return BooleanKeyframeTrack;
43587  
43588				case 'string':
43589  
43590					return StringKeyframeTrack;
43591  
43592			}
43593  
43594			throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
43595  
43596		}
43597  
43598	} );
43599  
43600	Object.assign( KeyframeTrack.prototype, {
43601  
43602		constructor: KeyframeTrack,
43603  
43604		TimeBufferType: Float32Array,
43605  
43606		ValueBufferType: Float32Array,
43607  
43608		DefaultInterpolation: InterpolateLinear,
43609  
43610		InterpolantFactoryMethodDiscrete: function ( result ) {
43611  
43612			return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
43613  
43614		},
43615  
43616		InterpolantFactoryMethodLinear: function ( result ) {
43617  
43618			return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
43619  
43620		},
43621  
43622		InterpolantFactoryMethodSmooth: function ( result ) {
43623  
43624			return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
43625  
43626		},
43627  
43628		setInterpolation: function ( interpolation ) {
43629  
43630			var factoryMethod;
43631  
43632			switch ( interpolation ) {
43633  
43634				case InterpolateDiscrete:
43635  
43636					factoryMethod = this.InterpolantFactoryMethodDiscrete;
43637  
43638					break;
43639  
43640				case InterpolateLinear:
43641  
43642					factoryMethod = this.InterpolantFactoryMethodLinear;
43643  
43644					break;
43645  
43646				case InterpolateSmooth:
43647  
43648					factoryMethod = this.InterpolantFactoryMethodSmooth;
43649  
43650					break;
43651  
43652			}
43653  
43654			if ( factoryMethod === undefined ) {
43655  
43656				var message = "unsupported interpolation for " +
43657					this.ValueTypeName + " keyframe track named " + this.name;
43658  
43659				if ( this.createInterpolant === undefined ) {
43660  
43661					// fall back to default, unless the default itself is messed up
43662					if ( interpolation !== this.DefaultInterpolation ) {
43663  
43664						this.setInterpolation( this.DefaultInterpolation );
43665  
43666					} else {
43667  
43668						throw new Error( message ); // fatal, in this case
43669  
43670					}
43671  
43672				}
43673  
43674				console.warn( 'THREE.KeyframeTrack:', message );
43675				return;
43676  
43677			}
43678  
43679			this.createInterpolant = factoryMethod;
43680  
43681		},
43682  
43683		getInterpolation: function () {
43684  
43685			switch ( this.createInterpolant ) {
43686  
43687				case this.InterpolantFactoryMethodDiscrete:
43688  
43689					return InterpolateDiscrete;
43690  
43691				case this.InterpolantFactoryMethodLinear:
43692  
43693					return InterpolateLinear;
43694  
43695				case this.InterpolantFactoryMethodSmooth:
43696  
43697					return InterpolateSmooth;
43698  
43699			}
43700  
43701		},
43702  
43703		getValueSize: function () {
43704  
43705			return this.values.length / this.times.length;
43706  
43707		},
43708  
43709		// move all keyframes either forwards or backwards in time
43710		shift: function ( timeOffset ) {
43711  
43712			if ( timeOffset !== 0.0 ) {
43713  
43714				var times = this.times;
43715  
43716				for ( var i = 0, n = times.length; i !== n; ++ i ) {
43717  
43718					times[ i ] += timeOffset;
43719  
43720				}
43721  
43722			}
43723  
43724			return this;
43725  
43726		},
43727  
43728		// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
43729		scale: function ( timeScale ) {
43730  
43731			if ( timeScale !== 1.0 ) {
43732  
43733				var times = this.times;
43734  
43735				for ( var i = 0, n = times.length; i !== n; ++ i ) {
43736  
43737					times[ i ] *= timeScale;
43738  
43739				}
43740  
43741			}
43742  
43743			return this;
43744  
43745		},
43746  
43747		// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
43748		// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
43749		trim: function ( startTime, endTime ) {
43750  
43751			var times = this.times,
43752				nKeys = times.length,
43753				from = 0,
43754				to = nKeys - 1;
43755  
43756			while ( from !== nKeys && times[ from ] < startTime ) {
43757  
43758				++ from;
43759  
43760			}
43761  
43762			while ( to !== - 1 && times[ to ] > endTime ) {
43763  
43764				-- to;
43765  
43766			}
43767  
43768			++ to; // inclusive -> exclusive bound
43769  
43770			if ( from !== 0 || to !== nKeys ) {
43771  
43772				// empty tracks are forbidden, so keep at least one keyframe
43773				if ( from >= to ) to = Math.max( to, 1 ), from = to - 1;
43774  
43775				var stride = this.getValueSize();
43776				this.times = AnimationUtils.arraySlice( times, from, to );
43777				this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
43778  
43779			}
43780  
43781			return this;
43782  
43783		},
43784  
43785		// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
43786		validate: function () {
43787  
43788			var valid = true;
43789  
43790			var valueSize = this.getValueSize();
43791			if ( valueSize - Math.floor( valueSize ) !== 0 ) {
43792  
43793				console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
43794				valid = false;
43795  
43796			}
43797  
43798			var times = this.times,
43799				values = this.values,
43800  
43801				nKeys = times.length;
43802  
43803			if ( nKeys === 0 ) {
43804  
43805				console.error( 'THREE.KeyframeTrack: Track is empty.', this );
43806				valid = false;
43807  
43808			}
43809  
43810			var prevTime = null;
43811  
43812			for ( var i = 0; i !== nKeys; i ++ ) {
43813  
43814				var currTime = times[ i ];
43815  
43816				if ( typeof currTime === 'number' && isNaN( currTime ) ) {
43817  
43818					console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
43819					valid = false;
43820					break;
43821  
43822				}
43823  
43824				if ( prevTime !== null && prevTime > currTime ) {
43825  
43826					console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
43827					valid = false;
43828					break;
43829  
43830				}
43831  
43832				prevTime = currTime;
43833  
43834			}
43835  
43836			if ( values !== undefined ) {
43837  
43838				if ( AnimationUtils.isTypedArray( values ) ) {
43839  
43840					for ( var i = 0, n = values.length; i !== n; ++ i ) {
43841  
43842						var value = values[ i ];
43843  
43844						if ( isNaN( value ) ) {
43845  
43846							console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
43847							valid = false;
43848							break;
43849  
43850						}
43851  
43852					}
43853  
43854				}
43855  
43856			}
43857  
43858			return valid;
43859  
43860		},
43861  
43862		// removes equivalent sequential keys as common in morph target sequences
43863		// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
43864		optimize: function () {
43865  
43866			var times = this.times,
43867				values = this.values,
43868				stride = this.getValueSize(),
43869  
43870				smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
43871  
43872				writeIndex = 1,
43873				lastIndex = times.length - 1;
43874  
43875			for ( var i = 1; i < lastIndex; ++ i ) {
43876  
43877				var keep = false;
43878  
43879				var time = times[ i ];
43880				var timeNext = times[ i + 1 ];
43881  
43882				// remove adjacent keyframes scheduled at the same time
43883  
43884				if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
43885  
43886					if ( ! smoothInterpolation ) {
43887  
43888						// remove unnecessary keyframes same as their neighbors
43889  
43890						var offset = i * stride,
43891							offsetP = offset - stride,
43892							offsetN = offset + stride;
43893  
43894						for ( var j = 0; j !== stride; ++ j ) {
43895  
43896							var value = values[ offset + j ];
43897  
43898							if ( value !== values[ offsetP + j ] ||
43899								value !== values[ offsetN + j ] ) {
43900  
43901								keep = true;
43902								break;
43903  
43904							}
43905  
43906						}
43907  
43908					} else {
43909  
43910						keep = true;
43911  
43912					}
43913  
43914				}
43915  
43916				// in-place compaction
43917  
43918				if ( keep ) {
43919  
43920					if ( i !== writeIndex ) {
43921  
43922						times[ writeIndex ] = times[ i ];
43923  
43924						var readOffset = i * stride,
43925							writeOffset = writeIndex * stride;
43926  
43927						for ( var j = 0; j !== stride; ++ j ) {
43928  
43929							values[ writeOffset + j ] = values[ readOffset + j ];
43930  
43931						}
43932  
43933					}
43934  
43935					++ writeIndex;
43936  
43937				}
43938  
43939			}
43940  
43941			// flush last keyframe (compaction looks ahead)
43942  
43943			if ( lastIndex > 0 ) {
43944  
43945				times[ writeIndex ] = times[ lastIndex ];
43946  
43947				for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
43948  
43949					values[ writeOffset + j ] = values[ readOffset + j ];
43950  
43951				}
43952  
43953				++ writeIndex;
43954  
43955			}
43956  
43957			if ( writeIndex !== times.length ) {
43958  
43959				this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
43960				this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
43961  
43962			}
43963  
43964			return this;
43965  
43966		}
43967  
43968	} );
43969  
43970	/**
43971	 *
43972	 * A Track of vectored keyframe values.
43973	 *
43974	 *
43975	 * @author Ben Houston / http://clara.io/
43976	 * @author David Sarno / http://lighthaus.us/
43977	 * @author tschw
43978	 */
43979  
43980	function VectorKeyframeTrack( name, times, values, interpolation ) {
43981  
43982		KeyframeTrack.call( this, name, times, values, interpolation );
43983  
43984	}
43985  
43986	VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
43987  
43988		constructor: VectorKeyframeTrack,
43989  
43990		ValueTypeName: 'vector'
43991  
43992		// ValueBufferType is inherited
43993  
43994		// DefaultInterpolation is inherited
43995  
43996	} );
43997  
43998	/**
43999	 *
44000	 * Reusable set of Tracks that represent an animation.
44001	 *
44002	 * @author Ben Houston / http://clara.io/
44003	 * @author David Sarno / http://lighthaus.us/
44004	 */
44005  
44006	function AnimationClip( name, duration, tracks ) {
44007  
44008		this.name = name;
44009		this.tracks = tracks;
44010		this.duration = ( duration !== undefined ) ? duration : - 1;
44011  
44012		this.uuid = _Math.generateUUID();
44013  
44014		// this means it should figure out its duration by scanning the tracks
44015		if ( this.duration < 0 ) {
44016  
44017			this.resetDuration();
44018  
44019		}
44020  
44021		this.optimize();
44022  
44023	}
44024  
44025	Object.assign( AnimationClip, {
44026  
44027		parse: function ( json ) {
44028  
44029			var tracks = [],
44030				jsonTracks = json.tracks,
44031				frameTime = 1.0 / ( json.fps || 1.0 );
44032  
44033			for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
44034  
44035				tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) );
44036  
44037			}
44038  
44039			return new AnimationClip( json.name, json.duration, tracks );
44040  
44041		},
44042  
44043		toJSON: function ( clip ) {
44044  
44045			var tracks = [],
44046				clipTracks = clip.tracks;
44047  
44048			var json = {
44049  
44050				'name': clip.name,
44051				'duration': clip.duration,
44052				'tracks': tracks,
44053				'uuid': clip.uuid
44054  
44055			};
44056  
44057			for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
44058  
44059				tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
44060  
44061			}
44062  
44063			return json;
44064  
44065		},
44066  
44067		CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
44068  
44069			var numMorphTargets = morphTargetSequence.length;
44070			var tracks = [];
44071  
44072			for ( var i = 0; i < numMorphTargets; i ++ ) {
44073  
44074				var times = [];
44075				var values = [];
44076  
44077				times.push(
44078					( i + numMorphTargets - 1 ) % numMorphTargets,
44079					i,
44080					( i + 1 ) % numMorphTargets );
44081  
44082				values.push( 0, 1, 0 );
44083  
44084				var order = AnimationUtils.getKeyframeOrder( times );
44085				times = AnimationUtils.sortedArray( times, 1, order );
44086				values = AnimationUtils.sortedArray( values, 1, order );
44087  
44088				// if there is a key at the first frame, duplicate it as the
44089				// last frame as well for perfect loop.
44090				if ( ! noLoop && times[ 0 ] === 0 ) {
44091  
44092					times.push( numMorphTargets );
44093					values.push( values[ 0 ] );
44094  
44095				}
44096  
44097				tracks.push(
44098					new NumberKeyframeTrack(
44099						'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
44100						times, values
44101					).scale( 1.0 / fps ) );
44102  
44103			}
44104  
44105			return new AnimationClip( name, - 1, tracks );
44106  
44107		},
44108  
44109		findByName: function ( objectOrClipArray, name ) {
44110  
44111			var clipArray = objectOrClipArray;
44112  
44113			if ( ! Array.isArray( objectOrClipArray ) ) {
44114  
44115				var o = objectOrClipArray;
44116				clipArray = o.geometry && o.geometry.animations || o.animations;
44117  
44118			}
44119  
44120			for ( var i = 0; i < clipArray.length; i ++ ) {
44121  
44122				if ( clipArray[ i ].name === name ) {
44123  
44124					return clipArray[ i ];
44125  
44126				}
44127  
44128			}
44129  
44130			return null;
44131  
44132		},
44133  
44134		CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
44135  
44136			var animationToMorphTargets = {};
44137  
44138			// tested with https://regex101.com/ on trick sequences
44139			// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
44140			var pattern = /^([\w-]*?)([\d]+)$/;
44141  
44142			// sort morph target names into animation groups based
44143			// patterns like Walk_001, Walk_002, Run_001, Run_002
44144			for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
44145  
44146				var morphTarget = morphTargets[ i ];
44147				var parts = morphTarget.name.match( pattern );
44148  
44149				if ( parts && parts.length > 1 ) {
44150  
44151					var name = parts[ 1 ];
44152  
44153					var animationMorphTargets = animationToMorphTargets[ name ];
44154					if ( ! animationMorphTargets ) {
44155  
44156						animationToMorphTargets[ name ] = animationMorphTargets = [];
44157  
44158					}
44159  
44160					animationMorphTargets.push( morphTarget );
44161  
44162				}
44163  
44164			}
44165  
44166			var clips = [];
44167  
44168			for ( var name in animationToMorphTargets ) {
44169  
44170				clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
44171  
44172			}
44173  
44174			return clips;
44175  
44176		},
44177  
44178		// parse the animation.hierarchy format
44179		parseAnimation: function ( animation, bones ) {
44180  
44181			if ( ! animation ) {
44182  
44183				console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
44184				return null;
44185  
44186			}
44187  
44188			var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
44189  
44190				// only return track if there are actually keys.
44191				if ( animationKeys.length !== 0 ) {
44192  
44193					var times = [];
44194					var values = [];
44195  
44196					AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
44197  
44198					// empty keys are filtered out, so check again
44199					if ( times.length !== 0 ) {
44200  
44201						destTracks.push( new trackType( trackName, times, values ) );
44202  
44203					}
44204  
44205				}
44206  
44207			};
44208  
44209			var tracks = [];
44210  
44211			var clipName = animation.name || 'default';
44212			// automatic length determination in AnimationClip.
44213			var duration = animation.length || - 1;
44214			var fps = animation.fps || 30;
44215  
44216			var hierarchyTracks = animation.hierarchy || [];
44217  
44218			for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
44219  
44220				var animationKeys = hierarchyTracks[ h ].keys;
44221  
44222				// skip empty tracks
44223				if ( ! animationKeys || animationKeys.length === 0 ) continue;
44224  
44225				// process morph targets
44226				if ( animationKeys[ 0 ].morphTargets ) {
44227  
44228					// figure out all morph targets used in this track
44229					var morphTargetNames = {};
44230  
44231					for ( var k = 0; k < animationKeys.length; k ++ ) {
44232  
44233						if ( animationKeys[ k ].morphTargets ) {
44234  
44235							for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
44236  
44237								morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
44238  
44239							}
44240  
44241						}
44242  
44243					}
44244  
44245					// create a track for each morph target with all zero
44246					// morphTargetInfluences except for the keys in which
44247					// the morphTarget is named.
44248					for ( var morphTargetName in morphTargetNames ) {
44249  
44250						var times = [];
44251						var values = [];
44252  
44253						for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
44254  
44255							var animationKey = animationKeys[ k ];
44256  
44257							times.push( animationKey.time );
44258							values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
44259  
44260						}
44261  
44262						tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
44263  
44264					}
44265  
44266					duration = morphTargetNames.length * ( fps || 1.0 );
44267  
44268				} else {
44269  
44270					// ...assume skeletal animation
44271  
44272					var boneName = '.bones[' + bones[ h ].name + ']';
44273  
44274					addNonemptyTrack(
44275						VectorKeyframeTrack, boneName + '.position',
44276						animationKeys, 'pos', tracks );
44277  
44278					addNonemptyTrack(
44279						QuaternionKeyframeTrack, boneName + '.quaternion',
44280						animationKeys, 'rot', tracks );
44281  
44282					addNonemptyTrack(
44283						VectorKeyframeTrack, boneName + '.scale',
44284						animationKeys, 'scl', tracks );
44285  
44286				}
44287  
44288			}
44289  
44290			if ( tracks.length === 0 ) {
44291  
44292				return null;
44293  
44294			}
44295  
44296			var clip = new AnimationClip( clipName, duration, tracks );
44297  
44298			return clip;
44299  
44300		}
44301  
44302	} );
44303  
44304	Object.assign( AnimationClip.prototype, {
44305  
44306		resetDuration: function () {
44307  
44308			var tracks = this.tracks, duration = 0;
44309  
44310			for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
44311  
44312				var track = this.tracks[ i ];
44313  
44314				duration = Math.max( duration, track.times[ track.times.length - 1 ] );
44315  
44316			}
44317  
44318			this.duration = duration;
44319  
44320		},
44321  
44322		trim: function () {
44323  
44324			for ( var i = 0; i < this.tracks.length; i ++ ) {
44325  
44326				this.tracks[ i ].trim( 0, this.duration );
44327  
44328			}
44329  
44330			return this;
44331  
44332		},
44333  
44334		optimize: function () {
44335  
44336			for ( var i = 0; i < this.tracks.length; i ++ ) {
44337  
44338				this.tracks[ i ].optimize();
44339  
44340			}
44341  
44342			return this;
44343  
44344		}
44345  
44346	} );
44347  
44348	/**
44349	 * @author mrdoob / http://mrdoob.com/
44350	 */
44351  
44352	function MaterialLoader( manager ) {
44353  
44354		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
44355		this.textures = {};
44356  
44357	}
44358  
44359	Object.assign( MaterialLoader.prototype, {
44360  
44361		load: function ( url, onLoad, onProgress, onError ) {
44362  
44363			var scope = this;
44364  
44365			var loader = new FileLoader( scope.manager );
44366			loader.load( url, function ( text ) {
44367  
44368				onLoad( scope.parse( JSON.parse( text ) ) );
44369  
44370			}, onProgress, onError );
44371  
44372		},
44373  
44374		setTextures: function ( value ) {
44375  
44376			this.textures = value;
44377  
44378		},
44379  
44380		parse: function ( json ) {
44381  
44382			var textures = this.textures;
44383  
44384			function getTexture( name ) {
44385  
44386				if ( textures[ name ] === undefined ) {
44387  
44388					console.warn( 'THREE.MaterialLoader: Undefined texture', name );
44389  
44390				}
44391  
44392				return textures[ name ];
44393  
44394			}
44395  
44396			var material = new Materials[ json.type ]();
44397  
44398			if ( json.uuid !== undefined ) material.uuid = json.uuid;
44399			if ( json.name !== undefined ) material.name = json.name;
44400			if ( json.color !== undefined ) material.color.setHex( json.color );
44401			if ( json.roughness !== undefined ) material.roughness = json.roughness;
44402			if ( json.metalness !== undefined ) material.metalness = json.metalness;
44403			if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
44404			if ( json.specular !== undefined ) material.specular.setHex( json.specular );
44405			if ( json.shininess !== undefined ) material.shininess = json.shininess;
44406			if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
44407			if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
44408			if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
44409			if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
44410			if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
44411			if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
44412			if ( json.fog !== undefined ) material.fog = json.fog;
44413			if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
44414			if ( json.blending !== undefined ) material.blending = json.blending;
44415			if ( json.side !== undefined ) material.side = json.side;
44416			if ( json.opacity !== undefined ) material.opacity = json.opacity;
44417			if ( json.transparent !== undefined ) material.transparent = json.transparent;
44418			if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
44419			if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
44420			if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
44421			if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
44422			if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
44423			if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
44424			if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
44425			if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
44426  
44427			if ( json.rotation !== undefined ) material.rotation = json.rotation;
44428  
44429			if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
44430			if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
44431			if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
44432			if ( json.scale !== undefined ) material.scale = json.scale;
44433  
44434			if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
44435			if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
44436			if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
44437  
44438			if ( json.skinning !== undefined ) material.skinning = json.skinning;
44439			if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
44440			if ( json.dithering !== undefined ) material.dithering = json.dithering;
44441  
44442			if ( json.visible !== undefined ) material.visible = json.visible;
44443			if ( json.userData !== undefined ) material.userData = json.userData;
44444  
44445			// Deprecated
44446  
44447			if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
44448  
44449			// for PointsMaterial
44450  
44451			if ( json.size !== undefined ) material.size = json.size;
44452			if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
44453  
44454			// maps
44455  
44456			if ( json.map !== undefined ) material.map = getTexture( json.map );
44457  
44458			if ( json.alphaMap !== undefined ) {
44459  
44460				material.alphaMap = getTexture( json.alphaMap );
44461				material.transparent = true;
44462  
44463			}
44464  
44465			if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
44466			if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
44467  
44468			if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
44469			if ( json.normalScale !== undefined ) {
44470  
44471				var normalScale = json.normalScale;
44472  
44473				if ( Array.isArray( normalScale ) === false ) {
44474  
44475					// Blender exporter used to export a scalar. See #7459
44476  
44477					normalScale = [ normalScale, normalScale ];
44478  
44479				}
44480  
44481				material.normalScale = new Vector2().fromArray( normalScale );
44482  
44483			}
44484  
44485			if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
44486			if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
44487			if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
44488  
44489			if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
44490			if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
44491  
44492			if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
44493			if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
44494  
44495			if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
44496  
44497			if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
44498  
44499			if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
44500  
44501			if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
44502			if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
44503  
44504			if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
44505			if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
44506  
44507			if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
44508  
44509			return material;
44510  
44511		}
44512  
44513	} );
44514  
44515	/**
44516	 * @author mrdoob / http://mrdoob.com/
44517	 */
44518  
44519	function BufferGeometryLoader( manager ) {
44520  
44521		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
44522  
44523	}
44524  
44525	Object.assign( BufferGeometryLoader.prototype, {
44526  
44527		load: function ( url, onLoad, onProgress, onError ) {
44528  
44529			var scope = this;
44530  
44531			var loader = new FileLoader( scope.manager );
44532			loader.load( url, function ( text ) {
44533  
44534				onLoad( scope.parse( JSON.parse( text ) ) );
44535  
44536			}, onProgress, onError );
44537  
44538		},
44539  
44540		parse: function ( json ) {
44541  
44542			var geometry = new BufferGeometry();
44543  
44544			var index = json.data.index;
44545  
44546			if ( index !== undefined ) {
44547  
44548				var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
44549				geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
44550  
44551			}
44552  
44553			var attributes = json.data.attributes;
44554  
44555			for ( var key in attributes ) {
44556  
44557				var attribute = attributes[ key ];
44558				var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
44559  
44560				geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
44561  
44562			}
44563  
44564			var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
44565  
44566			if ( groups !== undefined ) {
44567  
44568				for ( var i = 0, n = groups.length; i !== n; ++ i ) {
44569  
44570					var group = groups[ i ];
44571  
44572					geometry.addGroup( group.start, group.count, group.materialIndex );
44573  
44574				}
44575  
44576			}
44577  
44578			var boundingSphere = json.data.boundingSphere;
44579  
44580			if ( boundingSphere !== undefined ) {
44581  
44582				var center = new Vector3();
44583  
44584				if ( boundingSphere.center !== undefined ) {
44585  
44586					center.fromArray( boundingSphere.center );
44587  
44588				}
44589  
44590				geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
44591  
44592			}
44593  
44594			return geometry;
44595  
44596		}
44597  
44598	} );
44599  
44600	var TYPED_ARRAYS = {
44601		Int8Array: Int8Array,
44602		Uint8Array: Uint8Array,
44603		// Workaround for IE11 pre KB2929437. See #11440
44604		Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
44605		Int16Array: Int16Array,
44606		Uint16Array: Uint16Array,
44607		Int32Array: Int32Array,
44608		Uint32Array: Uint32Array,
44609		Float32Array: Float32Array,
44610		Float64Array: Float64Array
44611	};
44612  
44613	/**
44614	 * @author alteredq / http://alteredqualia.com/
44615	 */
44616  
44617	function Loader() {}
44618  
44619	Loader.Handlers = {
44620  
44621		handlers: [],
44622  
44623		add: function ( regex, loader ) {
44624  
44625			this.handlers.push( regex, loader );
44626  
44627		},
44628  
44629		get: function ( file ) {
44630  
44631			var handlers = this.handlers;
44632  
44633			for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
44634  
44635				var regex = handlers[ i ];
44636				var loader = handlers[ i + 1 ];
44637  
44638				if ( regex.test( file ) ) {
44639  
44640					return loader;
44641  
44642				}
44643  
44644			}
44645  
44646			return null;
44647  
44648		}
44649  
44650	};
44651  
44652	Object.assign( Loader.prototype, {
44653  
44654		crossOrigin: undefined,
44655  
44656		onLoadStart: function () {},
44657  
44658		onLoadProgress: function () {},
44659  
44660		onLoadComplete: function () {},
44661  
44662		initMaterials: function ( materials, texturePath, crossOrigin ) {
44663  
44664			var array = [];
44665  
44666			for ( var i = 0; i < materials.length; ++ i ) {
44667  
44668				array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
44669  
44670			}
44671  
44672			return array;
44673  
44674		},
44675  
44676		createMaterial: ( function () {
44677  
44678			var BlendingMode = {
44679				NoBlending: NoBlending,
44680				NormalBlending: NormalBlending,
44681				AdditiveBlending: AdditiveBlending,
44682				SubtractiveBlending: SubtractiveBlending,
44683				MultiplyBlending: MultiplyBlending,
44684				CustomBlending: CustomBlending
44685			};
44686  
44687			var color = new Color();
44688			var textureLoader = new TextureLoader();
44689			var materialLoader = new MaterialLoader();
44690  
44691			return function createMaterial( m, texturePath, crossOrigin ) {
44692  
44693				// convert from old material format
44694  
44695				var textures = {};
44696  
44697				function loadTexture( path, repeat, offset, wrap, anisotropy ) {
44698  
44699					var fullPath = texturePath + path;
44700					var loader = Loader.Handlers.get( fullPath );
44701  
44702					var texture;
44703  
44704					if ( loader !== null ) {
44705  
44706						texture = loader.load( fullPath );
44707  
44708					} else {
44709  
44710						textureLoader.setCrossOrigin( crossOrigin );
44711						texture = textureLoader.load( fullPath );
44712  
44713					}
44714  
44715					if ( repeat !== undefined ) {
44716  
44717						texture.repeat.fromArray( repeat );
44718  
44719						if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
44720						if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
44721  
44722					}
44723  
44724					if ( offset !== undefined ) {
44725  
44726						texture.offset.fromArray( offset );
44727  
44728					}
44729  
44730					if ( wrap !== undefined ) {
44731  
44732						if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
44733						if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
44734  
44735						if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
44736						if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
44737  
44738					}
44739  
44740					if ( anisotropy !== undefined ) {
44741  
44742						texture.anisotropy = anisotropy;
44743  
44744					}
44745  
44746					var uuid = _Math.generateUUID();
44747  
44748					textures[ uuid ] = texture;
44749  
44750					return uuid;
44751  
44752				}
44753  
44754				//
44755  
44756				var json = {
44757					uuid: _Math.generateUUID(),
44758					type: 'MeshLambertMaterial'
44759				};
44760  
44761				for ( var name in m ) {
44762  
44763					var value = m[ name ];
44764  
44765					switch ( name ) {
44766  
44767						case 'DbgColor':
44768						case 'DbgIndex':
44769						case 'opticalDensity':
44770						case 'illumination':
44771							break;
44772						case 'DbgName':
44773							json.name = value;
44774							break;
44775						case 'blending':
44776							json.blending = BlendingMode[ value ];
44777							break;
44778						case 'colorAmbient':
44779						case 'mapAmbient':
44780							console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
44781							break;
44782						case 'colorDiffuse':
44783							json.color = color.fromArray( value ).getHex();
44784							break;
44785						case 'colorSpecular':
44786							json.specular = color.fromArray( value ).getHex();
44787							break;
44788						case 'colorEmissive':
44789							json.emissive = color.fromArray( value ).getHex();
44790							break;
44791						case 'specularCoef':
44792							json.shininess = value;
44793							break;
44794						case 'shading':
44795							if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
44796							if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
44797							if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
44798							break;
44799						case 'mapDiffuse':
44800							json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
44801							break;
44802						case 'mapDiffuseRepeat':
44803						case 'mapDiffuseOffset':
44804						case 'mapDiffuseWrap':
44805						case 'mapDiffuseAnisotropy':
44806							break;
44807						case 'mapEmissive':
44808							json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
44809							break;
44810						case 'mapEmissiveRepeat':
44811						case 'mapEmissiveOffset':
44812						case 'mapEmissiveWrap':
44813						case 'mapEmissiveAnisotropy':
44814							break;
44815						case 'mapLight':
44816							json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
44817							break;
44818						case 'mapLightRepeat':
44819						case 'mapLightOffset':
44820						case 'mapLightWrap':
44821						case 'mapLightAnisotropy':
44822							break;
44823						case 'mapAO':
44824							json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
44825							break;
44826						case 'mapAORepeat':
44827						case 'mapAOOffset':
44828						case 'mapAOWrap':
44829						case 'mapAOAnisotropy':
44830							break;
44831						case 'mapBump':
44832							json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
44833							break;
44834						case 'mapBumpScale':
44835							json.bumpScale = value;
44836							break;
44837						case 'mapBumpRepeat':
44838						case 'mapBumpOffset':
44839						case 'mapBumpWrap':
44840						case 'mapBumpAnisotropy':
44841							break;
44842						case 'mapNormal':
44843							json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
44844							break;
44845						case 'mapNormalFactor':
44846							json.normalScale = value;
44847							break;
44848						case 'mapNormalRepeat':
44849						case 'mapNormalOffset':
44850						case 'mapNormalWrap':
44851						case 'mapNormalAnisotropy':
44852							break;
44853						case 'mapSpecular':
44854							json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
44855							break;
44856						case 'mapSpecularRepeat':
44857						case 'mapSpecularOffset':
44858						case 'mapSpecularWrap':
44859						case 'mapSpecularAnisotropy':
44860							break;
44861						case 'mapMetalness':
44862							json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
44863							break;
44864						case 'mapMetalnessRepeat':
44865						case 'mapMetalnessOffset':
44866						case 'mapMetalnessWrap':
44867						case 'mapMetalnessAnisotropy':
44868							break;
44869						case 'mapRoughness':
44870							json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
44871							break;
44872						case 'mapRoughnessRepeat':
44873						case 'mapRoughnessOffset':
44874						case 'mapRoughnessWrap':
44875						case 'mapRoughnessAnisotropy':
44876							break;
44877						case 'mapAlpha':
44878							json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
44879							break;
44880						case 'mapAlphaRepeat':
44881						case 'mapAlphaOffset':
44882						case 'mapAlphaWrap':
44883						case 'mapAlphaAnisotropy':
44884							break;
44885						case 'flipSided':
44886							json.side = BackSide;
44887							break;
44888						case 'doubleSided':
44889							json.side = DoubleSide;
44890							break;
44891						case 'transparency':
44892							console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
44893							json.opacity = value;
44894							break;
44895						case 'depthTest':
44896						case 'depthWrite':
44897						case 'colorWrite':
44898						case 'opacity':
44899						case 'reflectivity':
44900						case 'transparent':
44901						case 'visible':
44902						case 'wireframe':
44903							json[ name ] = value;
44904							break;
44905						case 'vertexColors':
44906							if ( value === true ) json.vertexColors = VertexColors;
44907							if ( value === 'face' ) json.vertexColors = FaceColors;
44908							break;
44909						default:
44910							console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
44911							break;
44912  
44913					}
44914  
44915				}
44916  
44917				if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
44918				if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
44919  
44920				if ( json.opacity < 1 ) json.transparent = true;
44921  
44922				materialLoader.setTextures( textures );
44923  
44924				return materialLoader.parse( json );
44925  
44926			};
44927  
44928		} )()
44929  
44930	} );
44931  
44932	/**
44933	 * @author Don McCurdy / https://www.donmccurdy.com
44934	 */
44935  
44936	var LoaderUtils = {
44937  
44938		decodeText: function ( array ) {
44939  
44940			if ( typeof TextDecoder !== 'undefined' ) {
44941  
44942				return new TextDecoder().decode( array );
44943  
44944			}
44945  
44946			// Avoid the String.fromCharCode.apply(null, array) shortcut, which
44947			// throws a "maximum call stack size exceeded" error for large arrays.
44948  
44949			var s = '';
44950  
44951			for ( var i = 0, il = array.length; i < il; i ++ ) {
44952  
44953				// Implicitly assumes little-endian.
44954				s += String.fromCharCode( array[ i ] );
44955  
44956			}
44957  
44958			// Merges multi-byte utf-8 characters.
44959			return decodeURIComponent( escape( s ) );
44960  
44961		},
44962  
44963		extractUrlBase: function ( url ) {
44964  
44965			var index = url.lastIndexOf( '/' );
44966  
44967			if ( index === - 1 ) return './';
44968  
44969			return url.substr( 0, index + 1 );
44970  
44971		}
44972  
44973	};
44974  
44975	/**
44976	 * @author mrdoob / http://mrdoob.com/
44977	 * @author alteredq / http://alteredqualia.com/
44978	 */
44979  
44980	function JSONLoader( manager ) {
44981  
44982		if ( typeof manager === 'boolean' ) {
44983  
44984			console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
44985			manager = undefined;
44986  
44987		}
44988  
44989		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
44990  
44991		this.withCredentials = false;
44992  
44993	}
44994  
44995	Object.assign( JSONLoader.prototype, {
44996  
vendor: 4,715 bytes, lines 44997-45214
44997		load: function ( url, onLoad, onProgress, onError ) {
44998  
44999			var scope = this;
45000  
45001			var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url );
45002  
45003			var loader = new FileLoader( this.manager );
45004			loader.setWithCredentials( this.withCredentials );
45005			loader.load( url, function ( text ) {
45006  
45007				var json = JSON.parse( text );
45008				var metadata = json.metadata;
45009  
45010				if ( metadata !== undefined ) {
45011  
45012					var type = metadata.type;
45013  
45014					if ( type !== undefined ) {
45015  
45016						if ( type.toLowerCase() === 'object' ) {
45017  
45018							console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
45019							return;
45020  
45021						}
45022  
45023					}
45024  
45025				}
45026  
45027				var object = scope.parse( json, texturePath );
45028				onLoad( object.geometry, object.materials );
45029  
45030			}, onProgress, onError );
45031  
45032		},
45033  
45034		setTexturePath: function ( value ) {
45035  
45036			this.texturePath = value;
45037  
45038		},
45039  
45040		parse: ( function () {
45041  
45042			function parseModel( json, geometry ) {
45043  
45044				function isBitSet( value, position ) {
45045  
45046					return value & ( 1 << position );
45047  
45048				}
45049  
45050				var i, j, fi,
45051  
45052					offset, zLength,
45053  
45054					colorIndex, normalIndex, uvIndex, materialIndex,
45055  
45056					type,
45057					isQuad,
45058					hasMaterial,
45059					hasFaceVertexUv,
45060					hasFaceNormal, hasFaceVertexNormal,
45061					hasFaceColor, hasFaceVertexColor,
45062  
45063					vertex, face, faceA, faceB, hex, normal,
45064  
45065					uvLayer, uv, u, v,
45066  
45067					faces = json.faces,
45068					vertices = json.vertices,
45069					normals = json.normals,
45070					colors = json.colors,
45071  
45072					scale = json.scale,
45073  
45074					nUvLayers = 0;
45075  
45076  
45077				if ( json.uvs !== undefined ) {
45078  
45079					// disregard empty arrays
45080  
45081					for ( i = 0; i < json.uvs.length; i ++ ) {
45082  
45083						if ( json.uvs[ i ].length ) nUvLayers ++;
45084  
45085					}
45086  
45087					for ( i = 0; i < nUvLayers; i ++ ) {
45088  
45089						geometry.faceVertexUvs[ i ] = [];
45090  
45091					}
45092  
45093				}
45094  
45095				offset = 0;
45096				zLength = vertices.length;
45097  
45098				while ( offset < zLength ) {
45099  
45100					vertex = new Vector3();
45101  
45102					vertex.x = vertices[ offset ++ ] * scale;
45103					vertex.y = vertices[ offset ++ ] * scale;
45104					vertex.z = vertices[ offset ++ ] * scale;
45105  
45106					geometry.vertices.push( vertex );
45107  
45108				}
45109  
45110				offset = 0;
45111				zLength = faces.length;
45112  
45113				while ( offset < zLength ) {
45114  
45115					type = faces[ offset ++ ];
45116  
45117					isQuad = isBitSet( type, 0 );
45118					hasMaterial = isBitSet( type, 1 );
45119					hasFaceVertexUv = isBitSet( type, 3 );
45120					hasFaceNormal = isBitSet( type, 4 );
45121					hasFaceVertexNormal = isBitSet( type, 5 );
45122					hasFaceColor = isBitSet( type, 6 );
45123					hasFaceVertexColor = isBitSet( type, 7 );
45124  
45125					// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
45126  
45127					if ( isQuad ) {
45128  
45129						faceA = new Face3();
45130						faceA.a = faces[ offset ];
45131						faceA.b = faces[ offset + 1 ];
45132						faceA.c = faces[ offset + 3 ];
45133  
45134						faceB = new Face3();
45135						faceB.a = faces[ offset + 1 ];
45136						faceB.b = faces[ offset + 2 ];
45137						faceB.c = faces[ offset + 3 ];
45138  
45139						offset += 4;
45140  
45141						if ( hasMaterial ) {
45142  
45143							materialIndex = faces[ offset ++ ];
45144							faceA.materialIndex = materialIndex;
45145							faceB.materialIndex = materialIndex;
45146  
45147						}
45148  
45149						// to get face <=> uv index correspondence
45150  
45151						fi = geometry.faces.length;
45152  
45153						if ( hasFaceVertexUv ) {
45154  
45155							for ( i = 0; i < nUvLayers; i ++ ) {
45156  
45157								uvLayer = json.uvs[ i ];
45158  
45159								geometry.faceVertexUvs[ i ][ fi ] = [];
45160								geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
45161  
45162								for ( j = 0; j < 4; j ++ ) {
45163  
45164									uvIndex = faces[ offset ++ ];
45165  
45166									u = uvLayer[ uvIndex * 2 ];
45167									v = uvLayer[ uvIndex * 2 + 1 ];
45168  
45169									uv = new Vector2( u, v );
45170  
45171									if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
45172									if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
45173  
45174								}
45175  
45176							}
45177  
45178						}
45179  
45180						if ( hasFaceNormal ) {
45181  
45182							normalIndex = faces[ offset ++ ] * 3;
45183  
45184							faceA.normal.set(
45185								normals[ normalIndex ++ ],
45186								normals[ normalIndex ++ ],
45187								normals[ normalIndex ]
45188							);
45189  
45190							faceB.normal.copy( faceA.normal );
45191  
45192						}
45193  
45194						if ( hasFaceVertexNormal ) {
45195  
45196							for ( i = 0; i < 4; i ++ ) {
45197  
45198								normalIndex = faces[ offset ++ ] * 3;
45199  
45200								normal = new Vector3(
45201									normals[ normalIndex ++ ],
45202									normals[ normalIndex ++ ],
45203									normals[ normalIndex ]
45204								);
45205  
45206  
45207								if ( i !== 2 ) faceA.vertexNormals.push( normal );
45208								if ( i !== 0 ) faceB.vertexNormals.push( normal );
45209  
45210							}
45211  
45212						}
45213  
45214  
45215						if ( hasFaceColor ) {
45216  
45217							colorIndex = faces[ offset ++ ];
45218							hex = colors[ colorIndex ];
45219  
45220							faceA.color.setHex( hex );
45221							faceB.color.setHex( hex );
45222  
45223						}
45224  
45225  
45226						if ( hasFaceVertexColor ) {
45227  
45228							for ( i = 0; i < 4; i ++ ) {
45229  
45230								colorIndex = faces[ offset ++ ];
45231								hex = colors[ colorIndex ];
45232  
45233								if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
45234								if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
45235  
45236							}
45237  
45238						}
45239  
45240						geometry.faces.push( faceA );
45241						geometry.faces.push( faceB );
45242  
45243					} else {
45244  
45245						face = new Face3();
45246						face.a = faces[ offset ++ ];
45247						face.b = faces[ offset ++ ];
45248						face.c = faces[ offset ++ ];
45249  
45250						if ( hasMaterial ) {
45251  
45252							materialIndex = faces[ offset ++ ];
45253							face.materialIndex = materialIndex;
45254  
45255						}
45256  
45257						// to get face <=> uv index correspondence
45258  
45259						fi = geometry.faces.length;
45260  
45261						if ( hasFaceVertexUv ) {
45262  
45263							for ( i = 0; i < nUvLayers; i ++ ) {
45264  
45265								uvLayer = json.uvs[ i ];
45266  
45267								geometry.faceVertexUvs[ i ][ fi ] = [];
45268  
45269								for ( j = 0; j < 3; j ++ ) {
45270  
45271									uvIndex = faces[ offset ++ ];
45272  
45273									u = uvLayer[ uvIndex * 2 ];
45274									v = uvLayer[ uvIndex * 2 + 1 ];
45275  
45276									uv = new Vector2( u, v );
45277  
45278									geometry.faceVertexUvs[ i ][ fi ].push( uv );
45279  
45280								}
45281  
45282							}
45283  
45284						}
45285  
45286						if ( hasFaceNormal ) {
45287  
45288							normalIndex = faces[ offset ++ ] * 3;
45289  
45290							face.normal.set(
45291								normals[ normalIndex ++ ],
45292								normals[ normalIndex ++ ],
45293								normals[ normalIndex ]
45294							);
45295  
45296						}
45297  
45298						if ( hasFaceVertexNormal ) {
45299  
45300							for ( i = 0; i < 3; i ++ ) {
45301  
45302								normalIndex = faces[ offset ++ ] * 3;
45303  
45304								normal = new Vector3(
45305									normals[ normalIndex ++ ],
45306									normals[ normalIndex ++ ],
45307									normals[ normalIndex ]
45308								);
45309  
45310								face.vertexNormals.push( normal );
45311  
45312							}
45313  
45314						}
45315  
45316  
vendor: 4,621 bytes, lines 45317-45497
45317						if ( hasFaceColor ) {
45318  
45319							colorIndex = faces[ offset ++ ];
45320							face.color.setHex( colors[ colorIndex ] );
45321  
45322						}
45323  
45324  
45325						if ( hasFaceVertexColor ) {
45326  
45327							for ( i = 0; i < 3; i ++ ) {
45328  
45329								colorIndex = faces[ offset ++ ];
45330								face.vertexColors.push( new Color( colors[ colorIndex ] ) );
45331  
45332							}
45333  
45334						}
45335  
45336						geometry.faces.push( face );
45337  
45338					}
45339  
45340				}
45341  
45342			}
45343  
45344			function parseSkin( json, geometry ) {
45345  
45346				var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
45347  
45348				if ( json.skinWeights ) {
45349  
45350					for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
45351  
45352						var x = json.skinWeights[ i ];
45353						var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
45354						var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
45355						var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
45356  
45357						geometry.skinWeights.push( new Vector4( x, y, z, w ) );
45358  
45359					}
45360  
45361				}
45362  
45363				if ( json.skinIndices ) {
45364  
45365					for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
45366  
45367						var a = json.skinIndices[ i ];
45368						var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
45369						var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
45370						var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
45371  
45372						geometry.skinIndices.push( new Vector4( a, b, c, d ) );
45373  
45374					}
45375  
45376				}
45377  
45378				geometry.bones = json.bones;
45379  
45380				if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
45381  
45382					console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
45383						geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
45384  
45385				}
45386  
45387			}
45388  
45389			function parseMorphing( json, geometry ) {
45390  
45391				var scale = json.scale;
45392  
45393				if ( json.morphTargets !== undefined ) {
45394  
45395					for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
45396  
45397						geometry.morphTargets[ i ] = {};
45398						geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
45399						geometry.morphTargets[ i ].vertices = [];
45400  
45401						var dstVertices = geometry.morphTargets[ i ].vertices;
45402						var srcVertices = json.morphTargets[ i ].vertices;
45403  
45404						for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
45405  
45406							var vertex = new Vector3();
45407							vertex.x = srcVertices[ v ] * scale;
45408							vertex.y = srcVertices[ v + 1 ] * scale;
45409							vertex.z = srcVertices[ v + 2 ] * scale;
45410  
45411							dstVertices.push( vertex );
45412  
45413						}
45414  
45415					}
45416  
45417				}
45418  
45419				if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
45420  
45421					console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
45422  
45423					var faces = geometry.faces;
45424					var morphColors = json.morphColors[ 0 ].colors;
45425  
45426					for ( var i = 0, l = faces.length; i < l; i ++ ) {
45427  
45428						faces[ i ].color.fromArray( morphColors, i * 3 );
45429  
45430					}
45431  
45432				}
45433  
45434			}
45435  
45436			function parseAnimations( json, geometry ) {
45437  
45438				var outputAnimations = [];
45439  
45440				// parse old style Bone/Hierarchy animations
45441				var animations = [];
45442  
45443				if ( json.animation !== undefined ) {
45444  
45445					animations.push( json.animation );
45446  
45447				}
45448  
45449				if ( json.animations !== undefined ) {
45450  
45451					if ( json.animations.length ) {
45452  
45453						animations = animations.concat( json.animations );
45454  
45455					} else {
45456  
45457						animations.push( json.animations );
45458  
45459					}
45460  
45461				}
45462  
45463				for ( var i = 0; i < animations.length; i ++ ) {
45464  
45465					var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
45466					if ( clip ) outputAnimations.push( clip );
45467  
45468				}
45469  
45470				// parse implicit morph animations
45471				if ( geometry.morphTargets ) {
45472  
45473					// TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
45474					var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
45475					outputAnimations = outputAnimations.concat( morphAnimationClips );
45476  
45477				}
45478  
45479				if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
45480  
45481			}
45482  
45483			return function parse( json, texturePath ) {
45484  
45485				if ( json.data !== undefined ) {
45486  
45487					// Geometry 4.0 spec
45488					json = json.data;
45489  
45490				}
45491  
45492				if ( json.scale !== undefined ) {
45493  
45494					json.scale = 1.0 / json.scale;
45495  
45496				} else {
45497  
vendor: 20,413 bytes, lines 45498-46423
45498					json.scale = 1.0;
45499  
45500				}
45501  
45502				var geometry = new Geometry();
45503  
45504				parseModel( json, geometry );
45505				parseSkin( json, geometry );
45506				parseMorphing( json, geometry );
45507				parseAnimations( json, geometry );
45508  
45509				geometry.computeFaceNormals();
45510				geometry.computeBoundingSphere();
45511  
45512				if ( json.materials === undefined || json.materials.length === 0 ) {
45513  
45514					return { geometry: geometry };
45515  
45516				} else {
45517  
45518					var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
45519  
45520					return { geometry: geometry, materials: materials };
45521  
45522				}
45523  
45524			};
45525  
45526		} )()
45527  
45528	} );
45529  
45530	/**
45531	 * @author mrdoob / http://mrdoob.com/
45532	 */
45533  
45534	function ObjectLoader( manager ) {
45535  
45536		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
45537		this.texturePath = '';
45538  
45539	}
45540  
45541	Object.assign( ObjectLoader.prototype, {
45542  
45543		load: function ( url, onLoad, onProgress, onError ) {
45544  
45545			if ( this.texturePath === '' ) {
45546  
45547				this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
45548  
45549			}
45550  
45551			var scope = this;
45552  
45553			var loader = new FileLoader( scope.manager );
45554			loader.load( url, function ( text ) {
45555  
45556				var json = null;
45557  
45558				try {
45559  
45560					json = JSON.parse( text );
45561  
45562				} catch ( error ) {
45563  
45564					if ( onError !== undefined ) onError( error );
45565  
45566					console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
45567  
45568					return;
45569  
45570				}
45571  
45572				var metadata = json.metadata;
45573  
45574				if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
45575  
45576					console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
45577					return;
45578  
45579				}
45580  
45581				scope.parse( json, onLoad );
45582  
45583			}, onProgress, onError );
45584  
45585		},
45586  
45587		setTexturePath: function ( value ) {
45588  
45589			this.texturePath = value;
45590			return this;
45591  
45592		},
45593  
45594		setCrossOrigin: function ( value ) {
45595  
45596			this.crossOrigin = value;
45597			return this;
45598  
45599		},
45600  
45601		parse: function ( json, onLoad ) {
45602  
45603			var shapes = this.parseShape( json.shapes );
45604			var geometries = this.parseGeometries( json.geometries, shapes );
45605  
45606			var images = this.parseImages( json.images, function () {
45607  
45608				if ( onLoad !== undefined ) onLoad( object );
45609  
45610			} );
45611  
45612			var textures = this.parseTextures( json.textures, images );
45613			var materials = this.parseMaterials( json.materials, textures );
45614  
45615			var object = this.parseObject( json.object, geometries, materials );
45616  
45617			if ( json.animations ) {
45618  
45619				object.animations = this.parseAnimations( json.animations );
45620  
45621			}
45622  
45623			if ( json.images === undefined || json.images.length === 0 ) {
45624  
45625				if ( onLoad !== undefined ) onLoad( object );
45626  
45627			}
45628  
45629			return object;
45630  
45631		},
45632  
45633		parseShape: function ( json ) {
45634  
45635			var shapes = {};
45636  
45637			if ( json !== undefined ) {
45638  
45639				for ( var i = 0, l = json.length; i < l; i ++ ) {
45640  
45641					var shape = new Shape().fromJSON( json[ i ] );
45642  
45643					shapes[ shape.uuid ] = shape;
45644  
45645				}
45646  
45647			}
45648  
45649			return shapes;
45650  
45651		},
45652  
45653		parseGeometries: function ( json, shapes ) {
45654  
45655			var geometries = {};
45656  
45657			if ( json !== undefined ) {
45658  
45659				var geometryLoader = new JSONLoader();
45660				var bufferGeometryLoader = new BufferGeometryLoader();
45661  
45662				for ( var i = 0, l = json.length; i < l; i ++ ) {
45663  
45664					var geometry;
45665					var data = json[ i ];
45666  
45667					switch ( data.type ) {
45668  
45669						case 'PlaneGeometry':
45670						case 'PlaneBufferGeometry':
45671  
45672							geometry = new Geometries[ data.type ](
45673								data.width,
45674								data.height,
45675								data.widthSegments,
45676								data.heightSegments
45677							);
45678  
45679							break;
45680  
45681						case 'BoxGeometry':
45682						case 'BoxBufferGeometry':
45683						case 'CubeGeometry': // backwards compatible
45684  
45685							geometry = new Geometries[ data.type ](
45686								data.width,
45687								data.height,
45688								data.depth,
45689								data.widthSegments,
45690								data.heightSegments,
45691								data.depthSegments
45692							);
45693  
45694							break;
45695  
45696						case 'CircleGeometry':
45697						case 'CircleBufferGeometry':
45698  
45699							geometry = new Geometries[ data.type ](
45700								data.radius,
45701								data.segments,
45702								data.thetaStart,
45703								data.thetaLength
45704							);
45705  
45706							break;
45707  
45708						case 'CylinderGeometry':
45709						case 'CylinderBufferGeometry':
45710  
45711							geometry = new Geometries[ data.type ](
45712								data.radiusTop,
45713								data.radiusBottom,
45714								data.height,
45715								data.radialSegments,
45716								data.heightSegments,
45717								data.openEnded,
45718								data.thetaStart,
45719								data.thetaLength
45720							);
45721  
45722							break;
45723  
45724						case 'ConeGeometry':
45725						case 'ConeBufferGeometry':
45726  
45727							geometry = new Geometries[ data.type ](
45728								data.radius,
45729								data.height,
45730								data.radialSegments,
45731								data.heightSegments,
45732								data.openEnded,
45733								data.thetaStart,
45734								data.thetaLength
45735							);
45736  
45737							break;
45738  
45739						case 'SphereGeometry':
45740						case 'SphereBufferGeometry':
45741  
45742							geometry = new Geometries[ data.type ](
45743								data.radius,
45744								data.widthSegments,
45745								data.heightSegments,
45746								data.phiStart,
45747								data.phiLength,
45748								data.thetaStart,
45749								data.thetaLength
45750							);
45751  
45752							break;
45753  
45754						case 'DodecahedronGeometry':
45755						case 'DodecahedronBufferGeometry':
45756						case 'IcosahedronGeometry':
45757						case 'IcosahedronBufferGeometry':
45758						case 'OctahedronGeometry':
45759						case 'OctahedronBufferGeometry':
45760						case 'TetrahedronGeometry':
45761						case 'TetrahedronBufferGeometry':
45762  
45763							geometry = new Geometries[ data.type ](
45764								data.radius,
45765								data.detail
45766							);
45767  
45768							break;
45769  
45770						case 'RingGeometry':
45771						case 'RingBufferGeometry':
45772  
45773							geometry = new Geometries[ data.type ](
45774								data.innerRadius,
45775								data.outerRadius,
45776								data.thetaSegments,
45777								data.phiSegments,
45778								data.thetaStart,
45779								data.thetaLength
45780							);
45781  
45782							break;
45783  
45784						case 'TorusGeometry':
45785						case 'TorusBufferGeometry':
45786  
45787							geometry = new Geometries[ data.type ](
45788								data.radius,
45789								data.tube,
45790								data.radialSegments,
45791								data.tubularSegments,
45792								data.arc
45793							);
45794  
45795							break;
45796  
45797						case 'TorusKnotGeometry':
45798						case 'TorusKnotBufferGeometry':
45799  
45800							geometry = new Geometries[ data.type ](
45801								data.radius,
45802								data.tube,
45803								data.tubularSegments,
45804								data.radialSegments,
45805								data.p,
45806								data.q
45807							);
45808  
45809							break;
45810  
45811						case 'LatheGeometry':
45812						case 'LatheBufferGeometry':
45813  
45814							geometry = new Geometries[ data.type ](
45815								data.points,
45816								data.segments,
45817								data.phiStart,
45818								data.phiLength
45819							);
45820  
45821							break;
45822  
45823						case 'PolyhedronGeometry':
45824						case 'PolyhedronBufferGeometry':
45825  
45826							geometry = new Geometries[ data.type ](
45827								data.vertices,
45828								data.indices,
45829								data.radius,
45830								data.details
45831							);
45832  
45833							break;
45834  
45835						case 'ShapeGeometry':
45836						case 'ShapeBufferGeometry':
45837  
45838							var geometryShapes = [];
45839  
45840							for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
45841  
45842								var shape = shapes[ data.shapes[ j ] ];
45843  
45844								geometryShapes.push( shape );
45845  
45846							}
45847  
45848							geometry = new Geometries[ data.type ](
45849								geometryShapes,
45850								data.curveSegments
45851							);
45852  
45853							break;
45854  
45855  
45856						case 'ExtrudeGeometry':
45857						case 'ExtrudeBufferGeometry':
45858  
45859							var geometryShapes = [];
45860  
45861							for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
45862  
45863								var shape = shapes[ data.shapes[ j ] ];
45864  
45865								geometryShapes.push( shape );
45866  
45867							}
45868  
45869							var extrudePath = data.options.extrudePath;
45870  
45871							if ( extrudePath !== undefined ) {
45872  
45873								data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
45874  
45875							}
45876  
45877							geometry = new Geometries[ data.type ](
45878								geometryShapes,
45879								data.options
45880							);
45881  
45882							break;
45883  
45884						case 'BufferGeometry':
45885  
45886							geometry = bufferGeometryLoader.parse( data );
45887  
45888							break;
45889  
45890						case 'Geometry':
45891  
45892							geometry = geometryLoader.parse( data, this.texturePath ).geometry;
45893  
45894							break;
45895  
45896						default:
45897  
45898							console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
45899  
45900							continue;
45901  
45902					}
45903  
45904					geometry.uuid = data.uuid;
45905  
45906					if ( data.name !== undefined ) geometry.name = data.name;
45907					if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
45908  
45909					geometries[ data.uuid ] = geometry;
45910  
45911				}
45912  
45913			}
45914  
45915			return geometries;
45916  
45917		},
45918  
45919		parseMaterials: function ( json, textures ) {
45920  
45921			var materials = {};
45922  
45923			if ( json !== undefined ) {
45924  
45925				var loader = new MaterialLoader();
45926				loader.setTextures( textures );
45927  
45928				for ( var i = 0, l = json.length; i < l; i ++ ) {
45929  
45930					var data = json[ i ];
45931  
45932					if ( data.type === 'MultiMaterial' ) {
45933  
45934						// Deprecated
45935  
45936						var array = [];
45937  
45938						for ( var j = 0; j < data.materials.length; j ++ ) {
45939  
45940							array.push( loader.parse( data.materials[ j ] ) );
45941  
45942						}
45943  
45944						materials[ data.uuid ] = array;
45945  
45946					} else {
45947  
45948						materials[ data.uuid ] = loader.parse( data );
45949  
45950					}
45951  
45952				}
45953  
45954			}
45955  
45956			return materials;
45957  
45958		},
45959  
45960		parseAnimations: function ( json ) {
45961  
45962			var animations = [];
45963  
45964			for ( var i = 0; i < json.length; i ++ ) {
45965  
45966				var data = json[ i ];
45967  
45968				var clip = AnimationClip.parse( data );
45969  
45970				if ( data.uuid !== undefined ) clip.uuid = data.uuid;
45971  
45972				animations.push( clip );
45973  
45974			}
45975  
45976			return animations;
45977  
45978		},
45979  
45980		parseImages: function ( json, onLoad ) {
45981  
45982			var scope = this;
45983			var images = {};
45984  
45985			function loadImage( url ) {
45986  
45987				scope.manager.itemStart( url );
45988  
45989				return loader.load( url, function () {
45990  
45991					scope.manager.itemEnd( url );
45992  
45993				}, undefined, function () {
45994  
45995					scope.manager.itemEnd( url );
45996					scope.manager.itemError( url );
45997  
45998				} );
45999  
46000			}
46001  
46002			if ( json !== undefined && json.length > 0 ) {
46003  
46004				var manager = new LoadingManager( onLoad );
46005  
46006				var loader = new ImageLoader( manager );
46007				loader.setCrossOrigin( this.crossOrigin );
46008  
46009				for ( var i = 0, l = json.length; i < l; i ++ ) {
46010  
46011					var image = json[ i ];
46012					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
46013  
46014					images[ image.uuid ] = loadImage( path );
46015  
46016				}
46017  
46018			}
46019  
46020			return images;
46021  
46022		},
46023  
46024		parseTextures: function ( json, images ) {
46025  
46026			function parseConstant( value, type ) {
46027  
46028				if ( typeof value === 'number' ) return value;
46029  
46030				console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
46031  
46032				return type[ value ];
46033  
46034			}
46035  
46036			var textures = {};
46037  
46038			if ( json !== undefined ) {
46039  
46040				for ( var i = 0, l = json.length; i < l; i ++ ) {
46041  
46042					var data = json[ i ];
46043  
46044					if ( data.image === undefined ) {
46045  
46046						console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
46047  
46048					}
46049  
46050					if ( images[ data.image ] === undefined ) {
46051  
46052						console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
46053  
46054					}
46055  
46056					var texture = new Texture( images[ data.image ] );
46057					texture.needsUpdate = true;
46058  
46059					texture.uuid = data.uuid;
46060  
46061					if ( data.name !== undefined ) texture.name = data.name;
46062  
46063					if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
46064  
46065					if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
46066					if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
46067					if ( data.center !== undefined ) texture.center.fromArray( data.center );
46068					if ( data.rotation !== undefined ) texture.rotation = data.rotation;
46069  
46070					if ( data.wrap !== undefined ) {
46071  
46072						texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
46073						texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
46074  
46075					}
46076  
46077					if ( data.format !== undefined ) texture.format = data.format;
46078  
46079					if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
46080					if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
46081					if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
46082  
46083					if ( data.flipY !== undefined ) texture.flipY = data.flipY;
46084  
46085					textures[ data.uuid ] = texture;
46086  
46087				}
46088  
46089			}
46090  
46091			return textures;
46092  
46093		},
46094  
46095		parseObject: function ( data, geometries, materials ) {
46096  
46097			var object;
46098  
46099			function getGeometry( name ) {
46100  
46101				if ( geometries[ name ] === undefined ) {
46102  
46103					console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
46104  
46105				}
46106  
46107				return geometries[ name ];
46108  
46109			}
46110  
46111			function getMaterial( name ) {
46112  
46113				if ( name === undefined ) return undefined;
46114  
46115				if ( Array.isArray( name ) ) {
46116  
46117					var array = [];
46118  
46119					for ( var i = 0, l = name.length; i < l; i ++ ) {
46120  
46121						var uuid = name[ i ];
46122  
46123						if ( materials[ uuid ] === undefined ) {
46124  
46125							console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
46126  
46127						}
46128  
46129						array.push( materials[ uuid ] );
46130  
46131					}
46132  
46133					return array;
46134  
46135				}
46136  
46137				if ( materials[ name ] === undefined ) {
46138  
46139					console.warn( 'THREE.ObjectLoader: Undefined material', name );
46140  
46141				}
46142  
46143				return materials[ name ];
46144  
46145			}
46146  
46147			switch ( data.type ) {
46148  
46149				case 'Scene':
46150  
46151					object = new Scene();
46152  
46153					if ( data.background !== undefined ) {
46154  
46155						if ( Number.isInteger( data.background ) ) {
46156  
46157							object.background = new Color( data.background );
46158  
46159						}
46160  
46161					}
46162  
46163					if ( data.fog !== undefined ) {
46164  
46165						if ( data.fog.type === 'Fog' ) {
46166  
46167							object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
46168  
46169						} else if ( data.fog.type === 'FogExp2' ) {
46170  
46171							object.fog = new FogExp2( data.fog.color, data.fog.density );
46172  
46173						}
46174  
46175					}
46176  
46177					break;
46178  
46179				case 'PerspectiveCamera':
46180  
46181					object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
46182  
46183					if ( data.focus !== undefined ) object.focus = data.focus;
46184					if ( data.zoom !== undefined ) object.zoom = data.zoom;
46185					if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
46186					if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
46187					if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46188  
46189					break;
46190  
46191				case 'OrthographicCamera':
46192  
46193					object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
46194  
46195					if ( data.zoom !== undefined ) object.zoom = data.zoom;
46196					if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46197  
46198					break;
46199  
46200				case 'AmbientLight':
46201  
46202					object = new AmbientLight( data.color, data.intensity );
46203  
46204					break;
46205  
46206				case 'DirectionalLight':
46207  
46208					object = new DirectionalLight( data.color, data.intensity );
46209  
46210					break;
46211  
46212				case 'PointLight':
46213  
46214					object = new PointLight( data.color, data.intensity, data.distance, data.decay );
46215  
46216					break;
46217  
46218				case 'RectAreaLight':
46219  
46220					object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
46221  
46222					break;
46223  
46224				case 'SpotLight':
46225  
46226					object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
46227  
46228					break;
46229  
46230				case 'HemisphereLight':
46231  
46232					object = new HemisphereLight( data.color, data.groundColor, data.intensity );
46233  
46234					break;
46235  
46236				case 'SkinnedMesh':
46237  
46238					console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
46239  
46240				case 'Mesh':
46241  
46242					var geometry = getGeometry( data.geometry );
46243					var material = getMaterial( data.material );
46244  
46245					if ( geometry.bones && geometry.bones.length > 0 ) {
46246  
46247						object = new SkinnedMesh( geometry, material );
46248  
46249					} else {
46250  
46251						object = new Mesh( geometry, material );
46252  
46253					}
46254  
46255					break;
46256  
46257				case 'LOD':
46258  
46259					object = new LOD();
46260  
46261					break;
46262  
46263				case 'Line':
46264  
46265					object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
46266  
46267					break;
46268  
46269				case 'LineLoop':
46270  
46271					object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
46272  
46273					break;
46274  
46275				case 'LineSegments':
46276  
46277					object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
46278  
46279					break;
46280  
46281				case 'PointCloud':
46282				case 'Points':
46283  
46284					object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
46285  
46286					break;
46287  
46288				case 'Sprite':
46289  
46290					object = new Sprite( getMaterial( data.material ) );
46291  
46292					break;
46293  
46294				case 'Group':
46295  
46296					object = new Group();
46297  
46298					break;
46299  
46300				default:
46301  
46302					object = new Object3D();
46303  
46304			}
46305  
46306			object.uuid = data.uuid;
46307  
46308			if ( data.name !== undefined ) object.name = data.name;
46309  
46310			if ( data.matrix !== undefined ) {
46311  
46312				object.matrix.fromArray( data.matrix );
46313  
46314				if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
46315				if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
46316  
46317			} else {
46318  
46319				if ( data.position !== undefined ) object.position.fromArray( data.position );
46320				if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
46321				if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
46322				if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
46323  
46324			}
46325  
46326			if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
46327			if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
46328  
46329			if ( data.shadow ) {
46330  
46331				if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
46332				if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
46333				if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
46334				if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
46335  
46336			}
46337  
46338			if ( data.visible !== undefined ) object.visible = data.visible;
46339			if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
46340			if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
46341			if ( data.userData !== undefined ) object.userData = data.userData;
46342  
46343			if ( data.children !== undefined ) {
46344  
46345				var children = data.children;
46346  
46347				for ( var i = 0; i < children.length; i ++ ) {
46348  
46349					object.add( this.parseObject( children[ i ], geometries, materials ) );
46350  
46351				}
46352  
46353			}
46354  
46355			if ( data.type === 'LOD' ) {
46356  
46357				var levels = data.levels;
46358  
46359				for ( var l = 0; l < levels.length; l ++ ) {
46360  
46361					var level = levels[ l ];
46362					var child = object.getObjectByProperty( 'uuid', level.object );
46363  
46364					if ( child !== undefined ) {
46365  
46366						object.addLevel( child, level.distance );
46367  
46368					}
46369  
46370				}
46371  
46372			}
46373  
46374			return object;
46375  
46376		}
46377  
46378	} );
46379  
46380	var TEXTURE_MAPPING = {
46381		UVMapping: UVMapping,
46382		CubeReflectionMapping: CubeReflectionMapping,
46383		CubeRefractionMapping: CubeRefractionMapping,
46384		EquirectangularReflectionMapping: EquirectangularReflectionMapping,
46385		EquirectangularRefractionMapping: EquirectangularRefractionMapping,
46386		SphericalReflectionMapping: SphericalReflectionMapping,
46387		CubeUVReflectionMapping: CubeUVReflectionMapping,
46388		CubeUVRefractionMapping: CubeUVRefractionMapping
46389	};
46390  
46391	var TEXTURE_WRAPPING = {
46392		RepeatWrapping: RepeatWrapping,
46393		ClampToEdgeWrapping: ClampToEdgeWrapping,
46394		MirroredRepeatWrapping: MirroredRepeatWrapping
46395	};
46396  
46397	var TEXTURE_FILTER = {
46398		NearestFilter: NearestFilter,
46399		NearestMipMapNearestFilter: NearestMipMapNearestFilter,
46400		NearestMipMapLinearFilter: NearestMipMapLinearFilter,
46401		LinearFilter: LinearFilter,
46402		LinearMipMapNearestFilter: LinearMipMapNearestFilter,
46403		LinearMipMapLinearFilter: LinearMipMapLinearFilter
46404	};
46405  
46406	/**
46407	 * @author zz85 / http://www.lab4games.net/zz85/blog
46408	 * minimal class for proxing functions to Path. Replaces old "extractSubpaths()"
46409	 **/
46410  
46411	function ShapePath() {
46412  
46413		this.type = 'ShapePath';
46414  
46415		this.color = new Color();
46416  
46417		this.subPaths = [];
46418		this.currentPath = null;
46419  
46420	}
46421  
46422	Object.assign( ShapePath.prototype, {
46423  
46424		moveTo: function ( x, y ) {
46425  
46426			this.currentPath = new Path();
46427			this.subPaths.push( this.currentPath );
46428			this.currentPath.moveTo( x, y );
46429  
46430		},
46431  
46432		lineTo: function ( x, y ) {
46433  
46434			this.currentPath.lineTo( x, y );
46435  
46436		},
46437  
46438		quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
46439  
46440			this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
46441  
46442		},
46443  
46444		bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
46445  
46446			this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
46447  
46448		},
46449  
46450		splineThru: function ( pts ) {
46451  
46452			this.currentPath.splineThru( pts );
46453  
46454		},
46455  
46456		toShapes: function ( isCCW, noHoles ) {
46457  
46458			function toShapesNoHoles( inSubpaths ) {
46459  
46460				var shapes = [];
46461  
46462				for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
46463  
46464					var tmpPath = inSubpaths[ i ];
46465  
46466					var tmpShape = new Shape();
46467					tmpShape.curves = tmpPath.curves;
46468  
46469					shapes.push( tmpShape );
46470  
46471				}
46472  
46473				return shapes;
46474  
46475			}
46476  
46477			function isPointInsidePolygon( inPt, inPolygon ) {
46478  
46479				var polyLen = inPolygon.length;
46480  
46481				// inPt on polygon contour => immediate success    or
46482				// toggling of inside/outside at every single! intersection point of an edge
46483				//  with the horizontal line through inPt, left of inPt
46484				//  not counting lowerY endpoints of edges and whole edges on that line
46485				var inside = false;
vendor: 4,871 bytes, lines 46486-46700
46486				for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
46487  
46488					var edgeLowPt = inPolygon[ p ];
46489					var edgeHighPt = inPolygon[ q ];
46490  
46491					var edgeDx = edgeHighPt.x - edgeLowPt.x;
46492					var edgeDy = edgeHighPt.y - edgeLowPt.y;
46493  
46494					if ( Math.abs( edgeDy ) > Number.EPSILON ) {
46495  
46496						// not parallel
46497						if ( edgeDy < 0 ) {
46498  
46499							edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
46500							edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
46501  
46502						}
46503						if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
46504  
46505						if ( inPt.y === edgeLowPt.y ) {
46506  
46507							if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
46508							// continue;				// no intersection or edgeLowPt => doesn't count !!!
46509  
46510						} else {
46511  
46512							var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
46513							if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
46514							if ( perpEdge < 0 ) 				continue;
46515							inside = ! inside;		// true intersection left of inPt
46516  
46517						}
46518  
46519					} else {
46520  
46521						// parallel or collinear
46522						if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
46523						// edge lies on the same horizontal line as inPt
46524						if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
46525							 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
46526						// continue;
46527  
46528					}
46529  
46530				}
46531  
46532				return	inside;
46533  
46534			}
46535  
46536			var isClockWise = ShapeUtils.isClockWise;
46537  
46538			var subPaths = this.subPaths;
46539			if ( subPaths.length === 0 ) return [];
46540  
46541			if ( noHoles === true )	return	toShapesNoHoles( subPaths );
46542  
46543  
46544			var solid, tmpPath, tmpShape, shapes = [];
46545  
46546			if ( subPaths.length === 1 ) {
46547  
46548				tmpPath = subPaths[ 0 ];
46549				tmpShape = new Shape();
46550				tmpShape.curves = tmpPath.curves;
46551				shapes.push( tmpShape );
46552				return shapes;
46553  
46554			}
46555  
46556			var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
46557			holesFirst = isCCW ? ! holesFirst : holesFirst;
46558  
46559			// console.log("Holes first", holesFirst);
46560  
46561			var betterShapeHoles = [];
46562			var newShapes = [];
46563			var newShapeHoles = [];
46564			var mainIdx = 0;
46565			var tmpPoints;
46566  
46567			newShapes[ mainIdx ] = undefined;
46568			newShapeHoles[ mainIdx ] = [];
46569  
46570			for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
46571  
46572				tmpPath = subPaths[ i ];
46573				tmpPoints = tmpPath.getPoints();
46574				solid = isClockWise( tmpPoints );
46575				solid = isCCW ? ! solid : solid;
46576  
46577				if ( solid ) {
46578  
46579					if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
46580  
46581					newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
46582					newShapes[ mainIdx ].s.curves = tmpPath.curves;
46583  
46584					if ( holesFirst )	mainIdx ++;
46585					newShapeHoles[ mainIdx ] = [];
46586  
46587					//console.log('cw', i);
46588  
46589				} else {
46590  
46591					newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
46592  
46593					//console.log('ccw', i);
46594  
46595				}
46596  
46597			}
46598  
46599			// only Holes? -> probably all Shapes with wrong orientation
46600			if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
46601  
46602  
46603			if ( newShapes.length > 1 ) {
46604  
46605				var ambiguous = false;
46606				var toChange = [];
46607  
46608				for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
46609  
46610					betterShapeHoles[ sIdx ] = [];
46611  
46612				}
46613  
46614				for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
46615  
46616					var sho = newShapeHoles[ sIdx ];
46617  
46618					for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
46619  
46620						var ho = sho[ hIdx ];
46621						var hole_unassigned = true;
46622  
46623						for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
46624  
46625							if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
46626  
46627								if ( sIdx !== s2Idx )	toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
46628								if ( hole_unassigned ) {
46629  
46630									hole_unassigned = false;
46631									betterShapeHoles[ s2Idx ].push( ho );
46632  
46633								} else {
46634  
46635									ambiguous = true;
46636  
46637								}
46638  
46639							}
46640  
46641						}
46642						if ( hole_unassigned ) {
46643  
46644							betterShapeHoles[ sIdx ].push( ho );
46645  
46646						}
46647  
46648					}
46649  
46650				}
46651				// console.log("ambiguous: ", ambiguous);
46652				if ( toChange.length > 0 ) {
46653  
46654					// console.log("to change: ", toChange);
46655					if ( ! ambiguous )	newShapeHoles = betterShapeHoles;
46656  
46657				}
46658  
46659			}
46660  
46661			var tmpHoles;
46662  
46663			for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
46664  
46665				tmpShape = newShapes[ i ].s;
46666				shapes.push( tmpShape );
46667				tmpHoles = newShapeHoles[ i ];
46668  
46669				for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
46670  
46671					tmpShape.holes.push( tmpHoles[ j ].h );
46672  
46673				}
46674  
46675			}
46676  
46677			//console.log("shape", shapes);
46678  
46679			return shapes;
46680  
46681		}
46682  
46683	} );
46684  
46685	/**
46686	 * @author zz85 / http://www.lab4games.net/zz85/blog
46687	 * @author mrdoob / http://mrdoob.com/
46688	 */
46689  
46690  
46691	function Font( data ) {
46692  
46693		this.type = 'Font';
46694  
46695		this.data = data;
46696  
46697	}
46698  
46699	Object.assign( Font.prototype, {
46700  
46701		isFont: true,
46702  
46703		generateShapes: function ( text, size, divisions ) {
46704  
46705			if ( size === undefined ) size = 100;
46706			if ( divisions === undefined ) divisions = 4;
46707  
46708			var shapes = [];
46709			var paths = createPaths( text, size, divisions, this.data );
46710  
46711			for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
46712  
46713				Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
46714  
46715			}
46716  
46717			return shapes;
46718  
46719		}
46720  
46721	} );
46722  
46723	function createPaths( text, size, divisions, data ) {
46724  
46725		var chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // see #13988
46726		var scale = size / data.resolution;
46727		var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
46728  
46729		var paths = [];
46730  
46731		var offsetX = 0, offsetY = 0;
46732  
46733		for ( var i = 0; i < chars.length; i ++ ) {
46734  
46735			var char = chars[ i ];
46736  
46737			if ( char === '\n' ) {
46738  
46739				offsetX = 0;
46740				offsetY -= line_height;
46741  
46742			} else {
46743  
46744				var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
46745				offsetX += ret.offsetX;
46746				paths.push( ret.path );
46747  
46748			}
46749  
46750		}
46751  
46752		return paths;
46753  
46754	}
46755  
46756	function createPath( char, divisions, scale, offsetX, offsetY, data ) {
46757  
46758		var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
46759  
46760		if ( ! glyph ) return;
46761  
46762		var path = new ShapePath();
46763  
46764		var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
46765  
46766		if ( glyph.o ) {
46767  
46768			var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
46769  
46770			for ( var i = 0, l = outline.length; i < l; ) {
46771  
46772				var action = outline[ i ++ ];
46773  
46774				switch ( action ) {
46775  
46776					case 'm': // moveTo
46777  
46778						x = outline[ i ++ ] * scale + offsetX;
46779						y = outline[ i ++ ] * scale + offsetY;
46780  
46781						path.moveTo( x, y );
46782  
46783						break;
46784  
46785					case 'l': // lineTo
46786  
46787						x = outline[ i ++ ] * scale + offsetX;
46788						y = outline[ i ++ ] * scale + offsetY;
46789  
46790						path.lineTo( x, y );
46791  
46792						break;
46793  
46794					case 'q': // quadraticCurveTo
46795  
46796						cpx = outline[ i ++ ] * scale + offsetX;
46797						cpy = outline[ i ++ ] * scale + offsetY;
46798						cpx1 = outline[ i ++ ] * scale + offsetX;
46799						cpy1 = outline[ i ++ ] * scale + offsetY;
46800  
46801						path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
46802  
46803						break;
46804  
46805					case 'b': // bezierCurveTo
46806  
46807						cpx = outline[ i ++ ] * scale + offsetX;
46808						cpy = outline[ i ++ ] * scale + offsetY;
46809						cpx1 = outline[ i ++ ] * scale + offsetX;
46810						cpy1 = outline[ i ++ ] * scale + offsetY;
46811						cpx2 = outline[ i ++ ] * scale + offsetX;
46812						cpy2 = outline[ i ++ ] * scale + offsetY;
46813  
46814						path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
46815  
46816						break;
46817  
46818				}
46819  
46820			}
46821  
46822		}
46823  
46824		return { offsetX: glyph.ha * scale, path: path };
46825  
46826	}
46827  
46828	/**
46829	 * @author mrdoob / http://mrdoob.com/
46830	 */
46831  
46832	function FontLoader( manager ) {
46833  
46834		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
46835  
46836	}
46837  
46838	Object.assign( FontLoader.prototype, {
46839  
46840		load: function ( url, onLoad, onProgress, onError ) {
46841  
46842			var scope = this;
46843  
46844			var loader = new FileLoader( this.manager );
46845			loader.setPath( this.path );
46846			loader.load( url, function ( text ) {
46847  
46848				var json;
46849  
46850				try {
46851  
46852					json = JSON.parse( text );
46853  
46854				} catch ( e ) {
46855  
46856					console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
46857					json = JSON.parse( text.substring( 65, text.length - 2 ) );
46858  
46859				}
46860  
46861				var font = scope.parse( json );
46862  
46863				if ( onLoad ) onLoad( font );
46864  
46865			}, onProgress, onError );
46866  
46867		},
46868  
46869		parse: function ( json ) {
46870  
46871			return new Font( json );
46872  
46873		},
46874  
46875		setPath: function ( value ) {
46876  
46877			this.path = value;
46878			return this;
46879  
46880		}
46881  
46882	} );
46883  
46884	/**
46885	 * @author mrdoob / http://mrdoob.com/
46886	 */
46887  
46888	var context;
46889  
46890	var AudioContext = {
46891  
46892		getContext: function () {
46893  
46894			if ( context === undefined ) {
46895  
46896				context = new ( window.AudioContext || window.webkitAudioContext )();
46897  
46898			}
46899  
46900			return context;
46901  
46902		},
46903  
46904		setContext: function ( value ) {
46905  
46906			context = value;
46907  
46908		}
46909  
46910	};
46911  
46912	/**
46913	 * @author Reece Aaron Lecrivain / http://reecenotes.com/
46914	 */
46915  
46916	function AudioLoader( manager ) {
46917  
46918		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
46919  
46920	}
46921  
46922	Object.assign( AudioLoader.prototype, {
46923  
46924		load: function ( url, onLoad, onProgress, onError ) {
46925  
46926			var loader = new FileLoader( this.manager );
46927			loader.setResponseType( 'arraybuffer' );
46928			loader.load( url, function ( buffer ) {
46929  
46930				var context = AudioContext.getContext();
46931  
46932				context.decodeAudioData( buffer, function ( audioBuffer ) {
46933  
46934					onLoad( audioBuffer );
46935  
46936				} );
46937  
46938			}, onProgress, onError );
46939  
46940		}
46941  
46942	} );
46943  
46944	/**
46945	 * @author mrdoob / http://mrdoob.com/
46946	 */
46947  
46948	function StereoCamera() {
46949  
46950		this.type = 'StereoCamera';
46951  
46952		this.aspect = 1;
46953  
46954		this.eyeSep = 0.064;
46955  
46956		this.cameraL = new PerspectiveCamera();
46957		this.cameraL.layers.enable( 1 );
46958		this.cameraL.matrixAutoUpdate = false;
46959  
46960		this.cameraR = new PerspectiveCamera();
46961		this.cameraR.layers.enable( 2 );
46962		this.cameraR.matrixAutoUpdate = false;
46963  
46964	}
46965  
46966	Object.assign( StereoCamera.prototype, {
46967  
46968		update: ( function () {
46969  
46970			var instance, focus, fov, aspect, near, far, zoom, eyeSep;
46971  
46972			var eyeRight = new Matrix4();
46973			var eyeLeft = new Matrix4();
46974  
46975			return function update( camera ) {
46976  
46977				var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
46978													aspect !== camera.aspect * this.aspect || near !== camera.near ||
46979													far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
46980  
46981				if ( needsUpdate ) {
46982  
46983					instance = this;
46984					focus = camera.focus;
46985					fov = camera.fov;
46986					aspect = camera.aspect * this.aspect;
46987					near = camera.near;
46988					far = camera.far;
46989					zoom = camera.zoom;
46990  
46991					// Off-axis stereoscopic effect based on
46992					// http://paulbourke.net/stereographics/stereorender/
46993  
46994					var projectionMatrix = camera.projectionMatrix.clone();
46995					eyeSep = this.eyeSep / 2;
46996					var eyeSepOnProjection = eyeSep * near / focus;
46997					var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
46998					var xmin, xmax;
46999  
47000					// translate xOffset
47001  
47002					eyeLeft.elements[ 12 ] = - eyeSep;
47003					eyeRight.elements[ 12 ] = eyeSep;
47004  
47005					// for left eye
47006  
47007					xmin = - ymax * aspect + eyeSepOnProjection;
47008					xmax = ymax * aspect + eyeSepOnProjection;
47009  
47010					projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
47011					projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47012  
47013					this.cameraL.projectionMatrix.copy( projectionMatrix );
47014  
47015					// for right eye
47016  
47017					xmin = - ymax * aspect - eyeSepOnProjection;
47018					xmax = ymax * aspect - eyeSepOnProjection;
47019  
47020					projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
47021					projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47022  
47023					this.cameraR.projectionMatrix.copy( projectionMatrix );
47024  
47025				}
47026  
47027				this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
47028				this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
47029  
47030			};
47031  
47032		} )()
47033  
47034	} );
47035  
47036	/**
47037	 * Camera for rendering cube maps
47038	 *	- renders scene into axis-aligned cube
47039	 *
47040	 * @author alteredq / http://alteredqualia.com/
47041	 */
47042  
47043	function CubeCamera( near, far, cubeResolution ) {
47044  
47045		Object3D.call( this );
47046  
47047		this.type = 'CubeCamera';
47048  
47049		var fov = 90, aspect = 1;
47050  
47051		var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
47052		cameraPX.up.set( 0, - 1, 0 );
47053		cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
47054		this.add( cameraPX );
47055  
47056		var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
47057		cameraNX.up.set( 0, - 1, 0 );
47058		cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
47059		this.add( cameraNX );
47060  
47061		var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
47062		cameraPY.up.set( 0, 0, 1 );
47063		cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
47064		this.add( cameraPY );
47065  
47066		var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
47067		cameraNY.up.set( 0, 0, - 1 );
47068		cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
47069		this.add( cameraNY );
47070  
47071		var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
47072		cameraPZ.up.set( 0, - 1, 0 );
47073		cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
47074		this.add( cameraPZ );
47075  
47076		var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
47077		cameraNZ.up.set( 0, - 1, 0 );
47078		cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
47079		this.add( cameraNZ );
47080  
47081		var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
47082  
47083		this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
47084		this.renderTarget.texture.name = "CubeCamera";
47085  
47086		this.update = function ( renderer, scene ) {
47087  
47088			if ( this.parent === null ) this.updateMatrixWorld();
47089  
47090			var renderTarget = this.renderTarget;
47091			var generateMipmaps = renderTarget.texture.generateMipmaps;
47092  
47093			renderTarget.texture.generateMipmaps = false;
47094  
47095			renderTarget.activeCubeFace = 0;
47096			renderer.render( scene, cameraPX, renderTarget );
47097  
47098			renderTarget.activeCubeFace = 1;
47099			renderer.render( scene, cameraNX, renderTarget );
47100  
47101			renderTarget.activeCubeFace = 2;
47102			renderer.render( scene, cameraPY, renderTarget );
47103  
47104			renderTarget.activeCubeFace = 3;
47105			renderer.render( scene, cameraNY, renderTarget );
47106  
47107			renderTarget.activeCubeFace = 4;
47108			renderer.render( scene, cameraPZ, renderTarget );
47109  
47110			renderTarget.texture.generateMipmaps = generateMipmaps;
47111  
47112			renderTarget.activeCubeFace = 5;
47113			renderer.render( scene, cameraNZ, renderTarget );
47114  
47115			renderer.setRenderTarget( null );
47116  
47117		};
47118  
47119		this.clear = function ( renderer, color, depth, stencil ) {
47120  
47121			var renderTarget = this.renderTarget;
47122  
47123			for ( var i = 0; i < 6; i ++ ) {
47124  
47125				renderTarget.activeCubeFace = i;
47126				renderer.setRenderTarget( renderTarget );
47127  
47128				renderer.clear( color, depth, stencil );
47129  
47130			}
47131  
47132			renderer.setRenderTarget( null );
47133  
47134		};
47135  
47136	}
47137  
47138	CubeCamera.prototype = Object.create( Object3D.prototype );
47139	CubeCamera.prototype.constructor = CubeCamera;
47140  
47141	/**
47142	 * @author mrdoob / http://mrdoob.com/
47143	 */
47144  
47145	function AudioListener() {
47146  
47147		Object3D.call( this );
47148  
47149		this.type = 'AudioListener';
47150  
47151		this.context = AudioContext.getContext();
47152  
47153		this.gain = this.context.createGain();
47154		this.gain.connect( this.context.destination );
47155  
47156		this.filter = null;
47157  
47158	}
47159  
47160	AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
47161  
47162		constructor: AudioListener,
47163  
47164		getInput: function () {
47165  
47166			return this.gain;
47167  
47168		},
47169  
47170		removeFilter: function ( ) {
47171  
47172			if ( this.filter !== null ) {
47173  
47174				this.gain.disconnect( this.filter );
47175				this.filter.disconnect( this.context.destination );
47176				this.gain.connect( this.context.destination );
47177				this.filter = null;
47178  
47179			}
47180  
47181		},
47182  
47183		getFilter: function () {
47184  
47185			return this.filter;
47186  
47187		},
47188  
47189		setFilter: function ( value ) {
47190  
47191			if ( this.filter !== null ) {
47192  
47193				this.gain.disconnect( this.filter );
47194				this.filter.disconnect( this.context.destination );
47195  
47196			} else {
47197  
47198				this.gain.disconnect( this.context.destination );
47199  
47200			}
47201  
47202			this.filter = value;
47203			this.gain.connect( this.filter );
47204			this.filter.connect( this.context.destination );
47205  
47206		},
47207  
47208		getMasterVolume: function () {
47209  
47210			return this.gain.gain.value;
47211  
47212		},
47213  
47214		setMasterVolume: function ( value ) {
47215  
47216			this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47217  
47218		},
47219  
47220		updateMatrixWorld: ( function () {
47221  
47222			var position = new Vector3();
47223			var quaternion = new Quaternion();
47224			var scale = new Vector3();
47225  
47226			var orientation = new Vector3();
47227  
47228			return function updateMatrixWorld( force ) {
47229  
47230				Object3D.prototype.updateMatrixWorld.call( this, force );
47231  
47232				var listener = this.context.listener;
47233				var up = this.up;
47234  
47235				this.matrixWorld.decompose( position, quaternion, scale );
47236  
47237				orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
47238  
47239				if ( listener.positionX ) {
47240  
47241					listener.positionX.setValueAtTime( position.x, this.context.currentTime );
47242					listener.positionY.setValueAtTime( position.y, this.context.currentTime );
47243					listener.positionZ.setValueAtTime( position.z, this.context.currentTime );
47244					listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime );
47245					listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime );
47246					listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime );
47247					listener.upX.setValueAtTime( up.x, this.context.currentTime );
47248					listener.upY.setValueAtTime( up.y, this.context.currentTime );
47249					listener.upZ.setValueAtTime( up.z, this.context.currentTime );
47250  
47251				} else {
47252  
47253					listener.setPosition( position.x, position.y, position.z );
47254					listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
47255  
47256				}
47257  
47258			};
47259  
47260		} )()
47261  
47262	} );
47263  
47264	/**
47265	 * @author mrdoob / http://mrdoob.com/
47266	 * @author Reece Aaron Lecrivain / http://reecenotes.com/
47267	 */
47268  
47269	function Audio( listener ) {
47270  
47271		Object3D.call( this );
47272  
47273		this.type = 'Audio';
47274  
47275		this.context = listener.context;
47276  
47277		this.gain = this.context.createGain();
47278		this.gain.connect( listener.getInput() );
47279  
47280		this.autoplay = false;
47281  
47282		this.buffer = null;
47283		this.loop = false;
47284		this.startTime = 0;
47285		this.offset = 0;
47286		this.playbackRate = 1;
47287		this.isPlaying = false;
47288		this.hasPlaybackControl = true;
47289		this.sourceType = 'empty';
47290  
47291		this.filters = [];
47292  
47293	}
47294  
47295	Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
47296  
47297		constructor: Audio,
47298  
47299		getOutput: function () {
47300  
47301			return this.gain;
47302  
47303		},
47304  
47305		setNodeSource: function ( audioNode ) {
47306  
47307			this.hasPlaybackControl = false;
47308			this.sourceType = 'audioNode';
47309			this.source = audioNode;
47310			this.connect();
47311  
47312			return this;
47313  
47314		},
47315  
47316		setMediaElementSource: function ( mediaElement ) {
47317  
47318			this.hasPlaybackControl = false;
47319			this.sourceType = 'mediaNode';
47320			this.source = this.context.createMediaElementSource( mediaElement );
47321			this.connect();
47322  
47323			return this;
47324  
47325		},
47326  
47327		setBuffer: function ( audioBuffer ) {
47328  
47329			this.buffer = audioBuffer;
47330			this.sourceType = 'buffer';
47331  
47332			if ( this.autoplay ) this.play();
47333  
47334			return this;
47335  
47336		},
47337  
47338		play: function () {
47339  
47340			if ( this.isPlaying === true ) {
47341  
47342				console.warn( 'THREE.Audio: Audio is already playing.' );
47343				return;
47344  
47345			}
47346  
47347			if ( this.hasPlaybackControl === false ) {
47348  
47349				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47350				return;
47351  
47352			}
47353  
47354			var source = this.context.createBufferSource();
47355  
47356			source.buffer = this.buffer;
47357			source.loop = this.loop;
47358			source.onended = this.onEnded.bind( this );
47359			source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
47360			this.startTime = this.context.currentTime;
47361			source.start( this.startTime, this.offset );
47362  
47363			this.isPlaying = true;
47364  
47365			this.source = source;
47366  
47367			return this.connect();
47368  
47369		},
47370  
47371		pause: function () {
47372  
47373			if ( this.hasPlaybackControl === false ) {
47374  
47375				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47376				return;
47377  
47378			}
47379  
47380			if ( this.isPlaying === true ) {
47381  
47382				this.source.stop();
47383				this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
47384				this.isPlaying = false;
47385  
47386			}
47387  
47388			return this;
47389  
47390		},
47391  
47392		stop: function () {
47393  
47394			if ( this.hasPlaybackControl === false ) {
47395  
47396				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47397				return;
47398  
47399			}
47400  
47401			this.source.stop();
47402			this.offset = 0;
47403			this.isPlaying = false;
47404  
47405			return this;
47406  
47407		},
47408  
47409		connect: function () {
47410  
47411			if ( this.filters.length > 0 ) {
47412  
47413				this.source.connect( this.filters[ 0 ] );
47414  
47415				for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
47416  
47417					this.filters[ i - 1 ].connect( this.filters[ i ] );
47418  
47419				}
47420  
47421				this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
47422  
47423			} else {
47424  
47425				this.source.connect( this.getOutput() );
47426  
47427			}
47428  
47429			return this;
47430  
47431		},
47432  
47433		disconnect: function () {
47434  
47435			if ( this.filters.length > 0 ) {
47436  
47437				this.source.disconnect( this.filters[ 0 ] );
47438  
47439				for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
47440  
47441					this.filters[ i - 1 ].disconnect( this.filters[ i ] );
47442  
47443				}
47444  
47445				this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
47446  
47447			} else {
47448  
47449				this.source.disconnect( this.getOutput() );
47450  
47451			}
47452  
47453			return this;
47454  
47455		},
47456  
47457		getFilters: function () {
47458  
47459			return this.filters;
47460  
47461		},
47462  
47463		setFilters: function ( value ) {
47464  
47465			if ( ! value ) value = [];
47466  
47467			if ( this.isPlaying === true ) {
47468  
47469				this.disconnect();
47470				this.filters = value;
47471				this.connect();
47472  
47473			} else {
47474  
47475				this.filters = value;
47476  
47477			}
47478  
47479			return this;
47480  
47481		},
47482  
47483		getFilter: function () {
47484  
47485			return this.getFilters()[ 0 ];
47486  
47487		},
47488  
47489		setFilter: function ( filter ) {
47490  
47491			return this.setFilters( filter ? [ filter ] : [] );
47492  
47493		},
47494  
47495		setPlaybackRate: function ( value ) {
47496  
47497			if ( this.hasPlaybackControl === false ) {
47498  
47499				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47500				return;
47501  
47502			}
47503  
47504			this.playbackRate = value;
47505  
47506			if ( this.isPlaying === true ) {
47507  
47508				this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime );
47509  
47510			}
47511  
47512			return this;
47513  
47514		},
47515  
47516		getPlaybackRate: function () {
47517  
47518			return this.playbackRate;
47519  
47520		},
47521  
47522		onEnded: function () {
47523  
47524			this.isPlaying = false;
47525  
47526		},
47527  
47528		getLoop: function () {
47529  
47530			if ( this.hasPlaybackControl === false ) {
47531  
47532				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47533				return false;
47534  
47535			}
47536  
47537			return this.loop;
47538  
47539		},
47540  
47541		setLoop: function ( value ) {
47542  
47543			if ( this.hasPlaybackControl === false ) {
47544  
47545				console.warn( 'THREE.Audio: this Audio has no playback control.' );
47546				return;
47547  
47548			}
47549  
47550			this.loop = value;
47551  
47552			if ( this.isPlaying === true ) {
47553  
47554				this.source.loop = this.loop;
47555  
47556			}
47557  
47558			return this;
47559  
47560		},
47561  
47562		getVolume: function () {
47563  
47564			return this.gain.gain.value;
47565  
47566		},
47567  
47568		setVolume: function ( value ) {
47569  
47570			this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47571  
47572			return this;
47573  
47574		}
47575  
47576	} );
47577  
47578	/**
47579	 * @author mrdoob / http://mrdoob.com/
47580	 */
47581  
47582	function PositionalAudio( listener ) {
47583  
47584		Audio.call( this, listener );
47585  
47586		this.panner = this.context.createPanner();
47587		this.panner.connect( this.gain );
47588  
47589	}
47590  
47591	PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
47592  
47593		constructor: PositionalAudio,
47594  
47595		getOutput: function () {
47596  
47597			return this.panner;
47598  
47599		},
47600  
47601		getRefDistance: function () {
47602  
47603			return this.panner.refDistance;
47604  
47605		},
47606  
47607		setRefDistance: function ( value ) {
47608  
47609			this.panner.refDistance = value;
47610  
47611		},
47612  
47613		getRolloffFactor: function () {
47614  
47615			return this.panner.rolloffFactor;
47616  
47617		},
47618  
47619		setRolloffFactor: function ( value ) {
47620  
47621			this.panner.rolloffFactor = value;
47622  
47623		},
47624  
47625		getDistanceModel: function () {
47626  
47627			return this.panner.distanceModel;
47628  
47629		},
47630  
47631		setDistanceModel: function ( value ) {
47632  
47633			this.panner.distanceModel = value;
47634  
47635		},
47636  
47637		getMaxDistance: function () {
47638  
47639			return this.panner.maxDistance;
47640  
47641		},
47642  
47643		setMaxDistance: function ( value ) {
47644  
47645			this.panner.maxDistance = value;
47646  
47647		},
47648  
47649		updateMatrixWorld: ( function () {
47650  
47651			var position = new Vector3();
47652  
47653			return function updateMatrixWorld( force ) {
47654  
47655				Object3D.prototype.updateMatrixWorld.call( this, force );
47656  
47657				position.setFromMatrixPosition( this.matrixWorld );
47658  
47659				this.panner.setPosition( position.x, position.y, position.z );
47660  
47661			};
47662  
47663		} )()
47664  
47665  
47666	} );
47667  
47668	/**
47669	 * @author mrdoob / http://mrdoob.com/
47670	 */
47671  
47672	function AudioAnalyser( audio, fftSize ) {
47673  
47674		this.analyser = audio.context.createAnalyser();
47675		this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
47676  
47677		this.data = new Uint8Array( this.analyser.frequencyBinCount );
47678  
47679		audio.getOutput().connect( this.analyser );
47680  
47681	}
47682  
47683	Object.assign( AudioAnalyser.prototype, {
47684  
vendor: 37,856 bytes, lines 47685-49303
47685		getFrequencyData: function () {
47686  
47687			this.analyser.getByteFrequencyData( this.data );
47688  
47689			return this.data;
47690  
47691		},
47692  
47693		getAverageFrequency: function () {
47694  
47695			var value = 0, data = this.getFrequencyData();
47696  
47697			for ( var i = 0; i < data.length; i ++ ) {
47698  
47699				value += data[ i ];
47700  
47701			}
47702  
47703			return value / data.length;
47704  
47705		}
47706  
47707	} );
47708  
47709	/**
47710	 *
47711	 * Buffered scene graph property that allows weighted accumulation.
47712	 *
47713	 *
47714	 * @author Ben Houston / http://clara.io/
47715	 * @author David Sarno / http://lighthaus.us/
47716	 * @author tschw
47717	 */
47718  
47719	function PropertyMixer( binding, typeName, valueSize ) {
47720  
47721		this.binding = binding;
47722		this.valueSize = valueSize;
47723  
47724		var bufferType = Float64Array,
47725			mixFunction;
47726  
47727		switch ( typeName ) {
47728  
47729			case 'quaternion':
47730				mixFunction = this._slerp;
47731				break;
47732  
47733			case 'string':
47734			case 'bool':
47735				bufferType = Array;
47736				mixFunction = this._select;
47737				break;
47738  
47739			default:
47740				mixFunction = this._lerp;
47741  
47742		}
47743  
47744		this.buffer = new bufferType( valueSize * 4 );
47745		// layout: [ incoming | accu0 | accu1 | orig ]
47746		//
47747		// interpolators can use .buffer as their .result
47748		// the data then goes to 'incoming'
47749		//
47750		// 'accu0' and 'accu1' are used frame-interleaved for
47751		// the cumulative result and are compared to detect
47752		// changes
47753		//
47754		// 'orig' stores the original state of the property
47755  
47756		this._mixBufferRegion = mixFunction;
47757  
47758		this.cumulativeWeight = 0;
47759  
47760		this.useCount = 0;
47761		this.referenceCount = 0;
47762  
47763	}
47764  
47765	Object.assign( PropertyMixer.prototype, {
47766  
47767		// accumulate data in the 'incoming' region into 'accu<i>'
47768		accumulate: function ( accuIndex, weight ) {
47769  
47770			// note: happily accumulating nothing when weight = 0, the caller knows
47771			// the weight and shouldn't have made the call in the first place
47772  
47773			var buffer = this.buffer,
47774				stride = this.valueSize,
47775				offset = accuIndex * stride + stride,
47776  
47777				currentWeight = this.cumulativeWeight;
47778  
47779			if ( currentWeight === 0 ) {
47780  
47781				// accuN := incoming * weight
47782  
47783				for ( var i = 0; i !== stride; ++ i ) {
47784  
47785					buffer[ offset + i ] = buffer[ i ];
47786  
47787				}
47788  
47789				currentWeight = weight;
47790  
47791			} else {
47792  
47793				// accuN := accuN + incoming * weight
47794  
47795				currentWeight += weight;
47796				var mix = weight / currentWeight;
47797				this._mixBufferRegion( buffer, offset, 0, mix, stride );
47798  
47799			}
47800  
47801			this.cumulativeWeight = currentWeight;
47802  
47803		},
47804  
47805		// apply the state of 'accu<i>' to the binding when accus differ
47806		apply: function ( accuIndex ) {
47807  
47808			var stride = this.valueSize,
47809				buffer = this.buffer,
47810				offset = accuIndex * stride + stride,
47811  
47812				weight = this.cumulativeWeight,
47813  
47814				binding = this.binding;
47815  
47816			this.cumulativeWeight = 0;
47817  
47818			if ( weight < 1 ) {
47819  
47820				// accuN := accuN + original * ( 1 - cumulativeWeight )
47821  
47822				var originalValueOffset = stride * 3;
47823  
47824				this._mixBufferRegion(
47825					buffer, offset, originalValueOffset, 1 - weight, stride );
47826  
47827			}
47828  
47829			for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
47830  
47831				if ( buffer[ i ] !== buffer[ i + stride ] ) {
47832  
47833					// value has changed -> update scene graph
47834  
47835					binding.setValue( buffer, offset );
47836					break;
47837  
47838				}
47839  
47840			}
47841  
47842		},
47843  
47844		// remember the state of the bound property and copy it to both accus
47845		saveOriginalState: function () {
47846  
47847			var binding = this.binding;
47848  
47849			var buffer = this.buffer,
47850				stride = this.valueSize,
47851  
47852				originalValueOffset = stride * 3;
47853  
47854			binding.getValue( buffer, originalValueOffset );
47855  
47856			// accu[0..1] := orig -- initially detect changes against the original
47857			for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
47858  
47859				buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
47860  
47861			}
47862  
47863			this.cumulativeWeight = 0;
47864  
47865		},
47866  
47867		// apply the state previously taken via 'saveOriginalState' to the binding
47868		restoreOriginalState: function () {
47869  
47870			var originalValueOffset = this.valueSize * 3;
47871			this.binding.setValue( this.buffer, originalValueOffset );
47872  
47873		},
47874  
47875  
47876		// mix functions
47877  
47878		_select: function ( buffer, dstOffset, srcOffset, t, stride ) {
47879  
47880			if ( t >= 0.5 ) {
47881  
47882				for ( var i = 0; i !== stride; ++ i ) {
47883  
47884					buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
47885  
47886				}
47887  
47888			}
47889  
47890		},
47891  
47892		_slerp: function ( buffer, dstOffset, srcOffset, t ) {
47893  
47894			Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
47895  
47896		},
47897  
47898		_lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
47899  
47900			var s = 1 - t;
47901  
47902			for ( var i = 0; i !== stride; ++ i ) {
47903  
47904				var j = dstOffset + i;
47905  
47906				buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
47907  
47908			}
47909  
47910		}
47911  
47912	} );
47913  
47914	/**
47915	 *
47916	 * A reference to a real property in the scene graph.
47917	 *
47918	 *
47919	 * @author Ben Houston / http://clara.io/
47920	 * @author David Sarno / http://lighthaus.us/
47921	 * @author tschw
47922	 */
47923  
47924	// Characters [].:/ are reserved for track binding syntax.
47925	var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
47926  
47927	function Composite( targetGroup, path, optionalParsedPath ) {
47928  
47929		var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
47930  
47931		this._targetGroup = targetGroup;
47932		this._bindings = targetGroup.subscribe_( path, parsedPath );
47933  
47934	}
47935  
47936	Object.assign( Composite.prototype, {
47937  
47938		getValue: function ( array, offset ) {
47939  
47940			this.bind(); // bind all binding
47941  
47942			var firstValidIndex = this._targetGroup.nCachedObjects_,
47943				binding = this._bindings[ firstValidIndex ];
47944  
47945			// and only call .getValue on the first
47946			if ( binding !== undefined ) binding.getValue( array, offset );
47947  
47948		},
47949  
47950		setValue: function ( array, offset ) {
47951  
47952			var bindings = this._bindings;
47953  
47954			for ( var i = this._targetGroup.nCachedObjects_,
47955					  n = bindings.length; i !== n; ++ i ) {
47956  
47957				bindings[ i ].setValue( array, offset );
47958  
47959			}
47960  
47961		},
47962  
47963		bind: function () {
47964  
47965			var bindings = this._bindings;
47966  
47967			for ( var i = this._targetGroup.nCachedObjects_,
47968					  n = bindings.length; i !== n; ++ i ) {
47969  
47970				bindings[ i ].bind();
47971  
47972			}
47973  
47974		},
47975  
47976		unbind: function () {
47977  
47978			var bindings = this._bindings;
47979  
47980			for ( var i = this._targetGroup.nCachedObjects_,
47981					  n = bindings.length; i !== n; ++ i ) {
47982  
47983				bindings[ i ].unbind();
47984  
47985			}
47986  
47987		}
47988  
47989	} );
47990  
47991  
47992	function PropertyBinding( rootNode, path, parsedPath ) {
47993  
47994		this.path = path;
47995		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
47996  
47997		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
47998  
47999		this.rootNode = rootNode;
48000  
48001	}
48002  
48003	Object.assign( PropertyBinding, {
48004  
48005		Composite: Composite,
48006  
48007		create: function ( root, path, parsedPath ) {
48008  
48009			if ( ! ( root && root.isAnimationObjectGroup ) ) {
48010  
48011				return new PropertyBinding( root, path, parsedPath );
48012  
48013			} else {
48014  
48015				return new PropertyBinding.Composite( root, path, parsedPath );
48016  
48017			}
48018  
48019		},
48020  
48021		/**
48022		 * Replaces spaces with underscores and removes unsupported characters from
48023		 * node names, to ensure compatibility with parseTrackName().
48024		 *
48025		 * @param  {string} name Node name to be sanitized.
48026		 * @return {string}
48027		 */
48028		sanitizeNodeName: ( function () {
48029  
48030			var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
48031  
48032			return function sanitizeNodeName( name ) {
48033  
48034				return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
48035  
48036			};
48037  
48038		}() ),
48039  
48040		parseTrackName: function () {
48041  
48042			// Attempts to allow node names from any language. ES5's `\w` regexp matches
48043			// only latin characters, and the unicode \p{L} is not yet supported. So
48044			// instead, we exclude reserved characters and match everything else.
48045			var wordChar = '[^' + RESERVED_CHARS_RE + ']';
48046			var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
48047  
48048			// Parent directories, delimited by '/' or ':'. Currently unused, but must
48049			// be matched to parse the rest of the track name.
48050			var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
48051  
48052			// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
48053			var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
48054  
48055			// Object on target node, and accessor. May not contain reserved
48056			// characters. Accessor may contain any character except closing bracket.
48057			var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
48058  
48059			// Property and accessor. May not contain reserved characters. Accessor may
48060			// contain any non-bracket characters.
48061			var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
48062  
48063			var trackRe = new RegExp( ''
48064				+ '^'
48065				+ directoryRe
48066				+ nodeRe
48067				+ objectRe
48068				+ propertyRe
48069				+ '$'
48070			);
48071  
48072			var supportedObjectNames = [ 'material', 'materials', 'bones' ];
48073  
48074			return function parseTrackName( trackName ) {
48075  
48076				var matches = trackRe.exec( trackName );
48077  
48078				if ( ! matches ) {
48079  
48080					throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
48081  
48082				}
48083  
48084				var results = {
48085					// directoryName: matches[ 1 ], // (tschw) currently unused
48086					nodeName: matches[ 2 ],
48087					objectName: matches[ 3 ],
48088					objectIndex: matches[ 4 ],
48089					propertyName: matches[ 5 ], // required
48090					propertyIndex: matches[ 6 ]
48091				};
48092  
48093				var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
48094  
48095				if ( lastDot !== undefined && lastDot !== - 1 ) {
48096  
48097					var objectName = results.nodeName.substring( lastDot + 1 );
48098  
48099					// Object names must be checked against a whitelist. Otherwise, there
48100					// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
48101					// 'bar' could be the objectName, or part of a nodeName (which can
48102					// include '.' characters).
48103					if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) {
48104  
48105						results.nodeName = results.nodeName.substring( 0, lastDot );
48106						results.objectName = objectName;
48107  
48108					}
48109  
48110				}
48111  
48112				if ( results.propertyName === null || results.propertyName.length === 0 ) {
48113  
48114					throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
48115  
48116				}
48117  
48118				return results;
48119  
48120			};
48121  
48122		}(),
48123  
48124		findNode: function ( root, nodeName ) {
48125  
48126			if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
48127  
48128				return root;
48129  
48130			}
48131  
48132			// search into skeleton bones.
48133			if ( root.skeleton ) {
48134  
48135				var bone = root.skeleton.getBoneByName( nodeName );
48136  
48137				if ( bone !== undefined ) {
48138  
48139					return bone;
48140  
48141				}
48142  
48143			}
48144  
48145			// search into node subtree.
48146			if ( root.children ) {
48147  
48148				var searchNodeSubtree = function ( children ) {
48149  
48150					for ( var i = 0; i < children.length; i ++ ) {
48151  
48152						var childNode = children[ i ];
48153  
48154						if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
48155  
48156							return childNode;
48157  
48158						}
48159  
48160						var result = searchNodeSubtree( childNode.children );
48161  
48162						if ( result ) return result;
48163  
48164					}
48165  
48166					return null;
48167  
48168				};
48169  
48170				var subTreeNode = searchNodeSubtree( root.children );
48171  
48172				if ( subTreeNode ) {
48173  
48174					return subTreeNode;
48175  
48176				}
48177  
48178			}
48179  
48180			return null;
48181  
48182		}
48183  
48184	} );
48185  
48186	Object.assign( PropertyBinding.prototype, { // prototype, continued
48187  
48188		// these are used to "bind" a nonexistent property
48189		_getValue_unavailable: function () {},
48190		_setValue_unavailable: function () {},
48191  
48192		BindingType: {
48193			Direct: 0,
48194			EntireArray: 1,
48195			ArrayElement: 2,
48196			HasFromToArray: 3
48197		},
48198  
48199		Versioning: {
48200			None: 0,
48201			NeedsUpdate: 1,
48202			MatrixWorldNeedsUpdate: 2
48203		},
48204  
48205		GetterByBindingType: [
48206  
48207			function getValue_direct( buffer, offset ) {
48208  
48209				buffer[ offset ] = this.node[ this.propertyName ];
48210  
48211			},
48212  
48213			function getValue_array( buffer, offset ) {
48214  
48215				var source = this.resolvedProperty;
48216  
48217				for ( var i = 0, n = source.length; i !== n; ++ i ) {
48218  
48219					buffer[ offset ++ ] = source[ i ];
48220  
48221				}
48222  
48223			},
48224  
48225			function getValue_arrayElement( buffer, offset ) {
48226  
48227				buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
48228  
48229			},
48230  
48231			function getValue_toArray( buffer, offset ) {
48232  
48233				this.resolvedProperty.toArray( buffer, offset );
48234  
48235			}
48236  
48237		],
48238  
48239		SetterByBindingTypeAndVersioning: [
48240  
48241			[
48242				// Direct
48243  
48244				function setValue_direct( buffer, offset ) {
48245  
48246					this.targetObject[ this.propertyName ] = buffer[ offset ];
48247  
48248				},
48249  
48250				function setValue_direct_setNeedsUpdate( buffer, offset ) {
48251  
48252					this.targetObject[ this.propertyName ] = buffer[ offset ];
48253					this.targetObject.needsUpdate = true;
48254  
48255				},
48256  
48257				function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
48258  
48259					this.targetObject[ this.propertyName ] = buffer[ offset ];
48260					this.targetObject.matrixWorldNeedsUpdate = true;
48261  
48262				}
48263  
48264			], [
48265  
48266				// EntireArray
48267  
48268				function setValue_array( buffer, offset ) {
48269  
48270					var dest = this.resolvedProperty;
48271  
48272					for ( var i = 0, n = dest.length; i !== n; ++ i ) {
48273  
48274						dest[ i ] = buffer[ offset ++ ];
48275  
48276					}
48277  
48278				},
48279  
48280				function setValue_array_setNeedsUpdate( buffer, offset ) {
48281  
48282					var dest = this.resolvedProperty;
48283  
48284					for ( var i = 0, n = dest.length; i !== n; ++ i ) {
48285  
48286						dest[ i ] = buffer[ offset ++ ];
48287  
48288					}
48289  
48290					this.targetObject.needsUpdate = true;
48291  
48292				},
48293  
48294				function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
48295  
48296					var dest = this.resolvedProperty;
48297  
48298					for ( var i = 0, n = dest.length; i !== n; ++ i ) {
48299  
48300						dest[ i ] = buffer[ offset ++ ];
48301  
48302					}
48303  
48304					this.targetObject.matrixWorldNeedsUpdate = true;
48305  
48306				}
48307  
48308			], [
48309  
48310				// ArrayElement
48311  
48312				function setValue_arrayElement( buffer, offset ) {
48313  
48314					this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48315  
48316				},
48317  
48318				function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
48319  
48320					this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48321					this.targetObject.needsUpdate = true;
48322  
48323				},
48324  
48325				function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
48326  
48327					this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48328					this.targetObject.matrixWorldNeedsUpdate = true;
48329  
48330				}
48331  
48332			], [
48333  
48334				// HasToFromArray
48335  
48336				function setValue_fromArray( buffer, offset ) {
48337  
48338					this.resolvedProperty.fromArray( buffer, offset );
48339  
48340				},
48341  
48342				function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
48343  
48344					this.resolvedProperty.fromArray( buffer, offset );
48345					this.targetObject.needsUpdate = true;
48346  
48347				},
48348  
48349				function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
48350  
48351					this.resolvedProperty.fromArray( buffer, offset );
48352					this.targetObject.matrixWorldNeedsUpdate = true;
48353  
48354				}
48355  
48356			]
48357  
48358		],
48359  
48360		getValue: function getValue_unbound( targetArray, offset ) {
48361  
48362			this.bind();
48363			this.getValue( targetArray, offset );
48364  
48365			// Note: This class uses a State pattern on a per-method basis:
48366			// 'bind' sets 'this.getValue' / 'setValue' and shadows the
48367			// prototype version of these methods with one that represents
48368			// the bound state. When the property is not found, the methods
48369			// become no-ops.
48370  
48371		},
48372  
48373		setValue: function getValue_unbound( sourceArray, offset ) {
48374  
48375			this.bind();
48376			this.setValue( sourceArray, offset );
48377  
48378		},
48379  
48380		// create getter / setter pair for a property in the scene graph
48381		bind: function () {
48382  
48383			var targetObject = this.node,
48384				parsedPath = this.parsedPath,
48385  
48386				objectName = parsedPath.objectName,
48387				propertyName = parsedPath.propertyName,
48388				propertyIndex = parsedPath.propertyIndex;
48389  
48390			if ( ! targetObject ) {
48391  
48392				targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
48393  
48394				this.node = targetObject;
48395  
48396			}
48397  
48398			// set fail state so we can just 'return' on error
48399			this.getValue = this._getValue_unavailable;
48400			this.setValue = this._setValue_unavailable;
48401  
48402			// ensure there is a value node
48403			if ( ! targetObject ) {
48404  
48405				console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
48406				return;
48407  
48408			}
48409  
48410			if ( objectName ) {
48411  
48412				var objectIndex = parsedPath.objectIndex;
48413  
48414				// special cases were we need to reach deeper into the hierarchy to get the face materials....
48415				switch ( objectName ) {
48416  
48417					case 'materials':
48418  
48419						if ( ! targetObject.material ) {
48420  
48421							console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
48422							return;
48423  
48424						}
48425  
48426						if ( ! targetObject.material.materials ) {
48427  
48428							console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
48429							return;
48430  
48431						}
48432  
48433						targetObject = targetObject.material.materials;
48434  
48435						break;
48436  
48437					case 'bones':
48438  
48439						if ( ! targetObject.skeleton ) {
48440  
48441							console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
48442							return;
48443  
48444						}
48445  
48446						// potential future optimization: skip this if propertyIndex is already an integer
48447						// and convert the integer string to a true integer.
48448  
48449						targetObject = targetObject.skeleton.bones;
48450  
48451						// support resolving morphTarget names into indices.
48452						for ( var i = 0; i < targetObject.length; i ++ ) {
48453  
48454							if ( targetObject[ i ].name === objectIndex ) {
48455  
48456								objectIndex = i;
48457								break;
48458  
48459							}
48460  
48461						}
48462  
48463						break;
48464  
48465					default:
48466  
48467						if ( targetObject[ objectName ] === undefined ) {
48468  
48469							console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
48470							return;
48471  
48472						}
48473  
48474						targetObject = targetObject[ objectName ];
48475  
48476				}
48477  
48478  
48479				if ( objectIndex !== undefined ) {
48480  
48481					if ( targetObject[ objectIndex ] === undefined ) {
48482  
48483						console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
48484						return;
48485  
48486					}
48487  
48488					targetObject = targetObject[ objectIndex ];
48489  
48490				}
48491  
48492			}
48493  
48494			// resolve property
48495			var nodeProperty = targetObject[ propertyName ];
48496  
48497			if ( nodeProperty === undefined ) {
48498  
48499				var nodeName = parsedPath.nodeName;
48500  
48501				console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
48502					'.' + propertyName + ' but it wasn\'t found.', targetObject );
48503				return;
48504  
48505			}
48506  
48507			// determine versioning scheme
48508			var versioning = this.Versioning.None;
48509  
48510			if ( targetObject.needsUpdate !== undefined ) { // material
48511  
48512				versioning = this.Versioning.NeedsUpdate;
48513				this.targetObject = targetObject;
48514  
48515			} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
48516  
48517				versioning = this.Versioning.MatrixWorldNeedsUpdate;
48518				this.targetObject = targetObject;
48519  
48520			}
48521  
48522			// determine how the property gets bound
48523			var bindingType = this.BindingType.Direct;
48524  
48525			if ( propertyIndex !== undefined ) {
48526  
48527				// access a sub element of the property array (only primitives are supported right now)
48528  
48529				if ( propertyName === "morphTargetInfluences" ) {
48530  
48531					// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
48532  
48533					// support resolving morphTarget names into indices.
48534					if ( ! targetObject.geometry ) {
48535  
48536						console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
48537						return;
48538  
48539					}
48540  
48541					if ( targetObject.geometry.isBufferGeometry ) {
48542  
48543						if ( ! targetObject.geometry.morphAttributes ) {
48544  
48545							console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
48546							return;
48547  
48548						}
48549  
48550						for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
48551  
48552							if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
48553  
48554								propertyIndex = i;
48555								break;
48556  
48557							}
48558  
48559						}
48560  
48561  
48562					} else {
48563  
48564						if ( ! targetObject.geometry.morphTargets ) {
48565  
48566							console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
48567							return;
48568  
48569						}
48570  
48571						for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
48572  
48573							if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
48574  
48575								propertyIndex = i;
48576								break;
48577  
48578							}
48579  
48580						}
48581  
48582					}
48583  
48584				}
48585  
48586				bindingType = this.BindingType.ArrayElement;
48587  
48588				this.resolvedProperty = nodeProperty;
48589				this.propertyIndex = propertyIndex;
48590  
48591			} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
48592  
48593				// must use copy for Object3D.Euler/Quaternion
48594  
48595				bindingType = this.BindingType.HasFromToArray;
48596  
48597				this.resolvedProperty = nodeProperty;
48598  
48599			} else if ( Array.isArray( nodeProperty ) ) {
48600  
48601				bindingType = this.BindingType.EntireArray;
48602  
48603				this.resolvedProperty = nodeProperty;
48604  
48605			} else {
48606  
48607				this.propertyName = propertyName;
48608  
48609			}
48610  
48611			// select getter / setter
48612			this.getValue = this.GetterByBindingType[ bindingType ];
48613			this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
48614  
48615		},
48616  
48617		unbind: function () {
48618  
48619			this.node = null;
48620  
48621			// back to the prototype version of getValue / setValue
48622			// note: avoiding to mutate the shape of 'this' via 'delete'
48623			this.getValue = this._getValue_unbound;
48624			this.setValue = this._setValue_unbound;
48625  
48626		}
48627  
48628	} );
48629  
48630	//!\ DECLARE ALIAS AFTER assign prototype !
48631	Object.assign( PropertyBinding.prototype, {
48632  
48633		// initial state of these methods that calls 'bind'
48634		_getValue_unbound: PropertyBinding.prototype.getValue,
48635		_setValue_unbound: PropertyBinding.prototype.setValue,
48636  
48637	} );
48638  
48639	/**
48640	 *
48641	 * A group of objects that receives a shared animation state.
48642	 *
48643	 * Usage:
48644	 *
48645	 * 	-	Add objects you would otherwise pass as 'root' to the
48646	 * 		constructor or the .clipAction method of AnimationMixer.
48647	 *
48648	 * 	-	Instead pass this object as 'root'.
48649	 *
48650	 * 	-	You can also add and remove objects later when the mixer
48651	 * 		is running.
48652	 *
48653	 * Note:
48654	 *
48655	 *  	Objects of this class appear as one object to the mixer,
48656	 *  	so cache control of the individual objects must be done
48657	 *  	on the group.
48658	 *
48659	 * Limitation:
48660	 *
48661	 * 	- 	The animated properties must be compatible among the
48662	 * 		all objects in the group.
48663	 *
48664	 *  -	A single property can either be controlled through a
48665	 *  	target group or directly, but not both.
48666	 *
48667	 * @author tschw
48668	 */
48669  
48670	function AnimationObjectGroup() {
48671  
48672		this.uuid = _Math.generateUUID();
48673  
48674		// cached objects followed by the active ones
48675		this._objects = Array.prototype.slice.call( arguments );
48676  
48677		this.nCachedObjects_ = 0;			// threshold
48678		// note: read by PropertyBinding.Composite
48679  
48680		var indices = {};
48681		this._indicesByUUID = indices;		// for bookkeeping
48682  
48683		for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
48684  
48685			indices[ arguments[ i ].uuid ] = i;
48686  
48687		}
48688  
48689		this._paths = [];					// inside: string
48690		this._parsedPaths = [];				// inside: { we don't care, here }
48691		this._bindings = []; 				// inside: Array< PropertyBinding >
48692		this._bindingsIndicesByPath = {}; 	// inside: indices in these arrays
48693  
48694		var scope = this;
48695  
48696		this.stats = {
48697  
48698			objects: {
48699				get total() {
48700  
48701					return scope._objects.length;
48702  
48703				},
48704				get inUse() {
48705  
48706					return this.total - scope.nCachedObjects_;
48707  
48708				}
48709			},
48710			get bindingsPerObject() {
48711  
48712				return scope._bindings.length;
48713  
48714			}
48715  
48716		};
48717  
48718	}
48719  
48720	Object.assign( AnimationObjectGroup.prototype, {
48721  
48722		isAnimationObjectGroup: true,
48723  
48724		add: function () {
48725  
48726			var objects = this._objects,
48727				nObjects = objects.length,
48728				nCachedObjects = this.nCachedObjects_,
48729				indicesByUUID = this._indicesByUUID,
48730				paths = this._paths,
48731				parsedPaths = this._parsedPaths,
48732				bindings = this._bindings,
48733				nBindings = bindings.length,
48734				knownObject = undefined;
48735  
48736			for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
48737  
48738				var object = arguments[ i ],
48739					uuid = object.uuid,
48740					index = indicesByUUID[ uuid ];
48741  
48742				if ( index === undefined ) {
48743  
48744					// unknown object -> add it to the ACTIVE region
48745  
48746					index = nObjects ++;
48747					indicesByUUID[ uuid ] = index;
48748					objects.push( object );
48749  
48750					// accounting is done, now do the same for all bindings
48751  
48752					for ( var j = 0, m = nBindings; j !== m; ++ j ) {
48753  
48754						bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
48755  
48756					}
48757  
48758				} else if ( index < nCachedObjects ) {
48759  
48760					knownObject = objects[ index ];
48761  
48762					// move existing object to the ACTIVE region
48763  
48764					var firstActiveIndex = -- nCachedObjects,
48765						lastCachedObject = objects[ firstActiveIndex ];
48766  
48767					indicesByUUID[ lastCachedObject.uuid ] = index;
48768					objects[ index ] = lastCachedObject;
48769  
48770					indicesByUUID[ uuid ] = firstActiveIndex;
48771					objects[ firstActiveIndex ] = object;
48772  
48773					// accounting is done, now do the same for all bindings
48774  
48775					for ( var j = 0, m = nBindings; j !== m; ++ j ) {
48776  
48777						var bindingsForPath = bindings[ j ],
48778							lastCached = bindingsForPath[ firstActiveIndex ],
48779							binding = bindingsForPath[ index ];
48780  
48781						bindingsForPath[ index ] = lastCached;
48782  
48783						if ( binding === undefined ) {
48784  
48785							// since we do not bother to create new bindings
48786							// for objects that are cached, the binding may
48787							// or may not exist
48788  
48789							binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
48790  
48791						}
48792  
48793						bindingsForPath[ firstActiveIndex ] = binding;
48794  
48795					}
48796  
48797				} else if ( objects[ index ] !== knownObject ) {
48798  
48799					console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
48800							'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
48801  
48802				} // else the object is already where we want it to be
48803  
48804			} // for arguments
48805  
48806			this.nCachedObjects_ = nCachedObjects;
48807  
48808		},
48809  
48810		remove: function () {
48811  
48812			var objects = this._objects,
48813				nCachedObjects = this.nCachedObjects_,
48814				indicesByUUID = this._indicesByUUID,
48815				bindings = this._bindings,
48816				nBindings = bindings.length;
48817  
48818			for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
48819  
48820				var object = arguments[ i ],
48821					uuid = object.uuid,
48822					index = indicesByUUID[ uuid ];
48823  
48824				if ( index !== undefined && index >= nCachedObjects ) {
48825  
48826					// move existing object into the CACHED region
48827  
48828					var lastCachedIndex = nCachedObjects ++,
48829						firstActiveObject = objects[ lastCachedIndex ];
48830  
48831					indicesByUUID[ firstActiveObject.uuid ] = index;
48832					objects[ index ] = firstActiveObject;
48833  
48834					indicesByUUID[ uuid ] = lastCachedIndex;
48835					objects[ lastCachedIndex ] = object;
48836  
48837					// accounting is done, now do the same for all bindings
48838  
48839					for ( var j = 0, m = nBindings; j !== m; ++ j ) {
48840  
48841						var bindingsForPath = bindings[ j ],
48842							firstActive = bindingsForPath[ lastCachedIndex ],
48843							binding = bindingsForPath[ index ];
48844  
48845						bindingsForPath[ index ] = firstActive;
48846						bindingsForPath[ lastCachedIndex ] = binding;
48847  
48848					}
48849  
48850				}
48851  
48852			} // for arguments
48853  
48854			this.nCachedObjects_ = nCachedObjects;
48855  
48856		},
48857  
48858		// remove & forget
48859		uncache: function () {
48860  
48861			var objects = this._objects,
48862				nObjects = objects.length,
48863				nCachedObjects = this.nCachedObjects_,
48864				indicesByUUID = this._indicesByUUID,
48865				bindings = this._bindings,
48866				nBindings = bindings.length;
48867  
48868			for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
48869  
48870				var object = arguments[ i ],
48871					uuid = object.uuid,
48872					index = indicesByUUID[ uuid ];
48873  
48874				if ( index !== undefined ) {
48875  
48876					delete indicesByUUID[ uuid ];
48877  
48878					if ( index < nCachedObjects ) {
48879  
48880						// object is cached, shrink the CACHED region
48881  
48882						var firstActiveIndex = -- nCachedObjects,
48883							lastCachedObject = objects[ firstActiveIndex ],
48884							lastIndex = -- nObjects,
48885							lastObject = objects[ lastIndex ];
48886  
48887						// last cached object takes this object's place
48888						indicesByUUID[ lastCachedObject.uuid ] = index;
48889						objects[ index ] = lastCachedObject;
48890  
48891						// last object goes to the activated slot and pop
48892						indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
48893						objects[ firstActiveIndex ] = lastObject;
48894						objects.pop();
48895  
48896						// accounting is done, now do the same for all bindings
48897  
48898						for ( var j = 0, m = nBindings; j !== m; ++ j ) {
48899  
48900							var bindingsForPath = bindings[ j ],
48901								lastCached = bindingsForPath[ firstActiveIndex ],
48902								last = bindingsForPath[ lastIndex ];
48903  
48904							bindingsForPath[ index ] = lastCached;
48905							bindingsForPath[ firstActiveIndex ] = last;
48906							bindingsForPath.pop();
48907  
48908						}
48909  
48910					} else {
48911  
48912						// object is active, just swap with the last and pop
48913  
48914						var lastIndex = -- nObjects,
48915							lastObject = objects[ lastIndex ];
48916  
48917						indicesByUUID[ lastObject.uuid ] = index;
48918						objects[ index ] = lastObject;
48919						objects.pop();
48920  
48921						// accounting is done, now do the same for all bindings
48922  
48923						for ( var j = 0, m = nBindings; j !== m; ++ j ) {
48924  
48925							var bindingsForPath = bindings[ j ];
48926  
48927							bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
48928							bindingsForPath.pop();
48929  
48930						}
48931  
48932					} // cached or active
48933  
48934				} // if object is known
48935  
48936			} // for arguments
48937  
48938			this.nCachedObjects_ = nCachedObjects;
48939  
48940		},
48941  
48942		// Internal interface used by befriended PropertyBinding.Composite:
48943  
48944		subscribe_: function ( path, parsedPath ) {
48945  
48946			// returns an array of bindings for the given path that is changed
48947			// according to the contained objects in the group
48948  
48949			var indicesByPath = this._bindingsIndicesByPath,
48950				index = indicesByPath[ path ],
48951				bindings = this._bindings;
48952  
48953			if ( index !== undefined ) return bindings[ index ];
48954  
48955			var paths = this._paths,
48956				parsedPaths = this._parsedPaths,
48957				objects = this._objects,
48958				nObjects = objects.length,
48959				nCachedObjects = this.nCachedObjects_,
48960				bindingsForPath = new Array( nObjects );
48961  
48962			index = bindings.length;
48963  
48964			indicesByPath[ path ] = index;
48965  
48966			paths.push( path );
48967			parsedPaths.push( parsedPath );
48968			bindings.push( bindingsForPath );
48969  
48970			for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
48971  
48972				var object = objects[ i ];
48973				bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
48974  
48975			}
48976  
48977			return bindingsForPath;
48978  
48979		},
48980  
48981		unsubscribe_: function ( path ) {
48982  
48983			// tells the group to forget about a property path and no longer
48984			// update the array previously obtained with 'subscribe_'
48985  
48986			var indicesByPath = this._bindingsIndicesByPath,
48987				index = indicesByPath[ path ];
48988  
48989			if ( index !== undefined ) {
48990  
48991				var paths = this._paths,
48992					parsedPaths = this._parsedPaths,
48993					bindings = this._bindings,
48994					lastBindingsIndex = bindings.length - 1,
48995					lastBindings = bindings[ lastBindingsIndex ],
48996					lastBindingsPath = path[ lastBindingsIndex ];
48997  
48998				indicesByPath[ lastBindingsPath ] = index;
48999  
49000				bindings[ index ] = lastBindings;
49001				bindings.pop();
49002  
49003				parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
49004				parsedPaths.pop();
49005  
49006				paths[ index ] = paths[ lastBindingsIndex ];
49007				paths.pop();
49008  
49009			}
49010  
49011		}
49012  
49013	} );
49014  
49015	/**
49016	 *
49017	 * Action provided by AnimationMixer for scheduling clip playback on specific
49018	 * objects.
49019	 *
49020	 * @author Ben Houston / http://clara.io/
49021	 * @author David Sarno / http://lighthaus.us/
49022	 * @author tschw
49023	 *
49024	 */
49025  
49026	function AnimationAction( mixer, clip, localRoot ) {
49027  
49028		this._mixer = mixer;
49029		this._clip = clip;
49030		this._localRoot = localRoot || null;
49031  
49032		var tracks = clip.tracks,
49033			nTracks = tracks.length,
49034			interpolants = new Array( nTracks );
49035  
49036		var interpolantSettings = {
49037			endingStart: ZeroCurvatureEnding,
49038			endingEnd: ZeroCurvatureEnding
49039		};
49040  
49041		for ( var i = 0; i !== nTracks; ++ i ) {
49042  
49043			var interpolant = tracks[ i ].createInterpolant( null );
49044			interpolants[ i ] = interpolant;
49045			interpolant.settings = interpolantSettings;
49046  
49047		}
49048  
49049		this._interpolantSettings = interpolantSettings;
49050  
49051		this._interpolants = interpolants;	// bound by the mixer
49052  
49053		// inside: PropertyMixer (managed by the mixer)
49054		this._propertyBindings = new Array( nTracks );
49055  
49056		this._cacheIndex = null;			// for the memory manager
49057		this._byClipCacheIndex = null;		// for the memory manager
49058  
49059		this._timeScaleInterpolant = null;
49060		this._weightInterpolant = null;
49061  
49062		this.loop = LoopRepeat;
49063		this._loopCount = - 1;
49064  
49065		// global mixer time when the action is to be started
49066		// it's set back to 'null' upon start of the action
49067		this._startTime = null;
49068  
49069		// scaled local time of the action
49070		// gets clamped or wrapped to 0..clip.duration according to loop
49071		this.time = 0;
49072  
49073		this.timeScale = 1;
49074		this._effectiveTimeScale = 1;
49075  
49076		this.weight = 1;
49077		this._effectiveWeight = 1;
49078  
49079		this.repetitions = Infinity; 		// no. of repetitions when looping
49080  
49081		this.paused = false;				// true -> zero effective time scale
49082		this.enabled = true;				// false -> zero effective weight
49083  
49084		this.clampWhenFinished 	= false;	// keep feeding the last frame?
49085  
49086		this.zeroSlopeAtStart 	= true;		// for smooth interpolation w/o separate
49087		this.zeroSlopeAtEnd		= true;		// clips for start, loop and end
49088  
49089	}
49090  
49091	Object.assign( AnimationAction.prototype, {
49092  
49093		// State & Scheduling
49094  
49095		play: function () {
49096  
49097			this._mixer._activateAction( this );
49098  
49099			return this;
49100  
49101		},
49102  
49103		stop: function () {
49104  
49105			this._mixer._deactivateAction( this );
49106  
49107			return this.reset();
49108  
49109		},
49110  
49111		reset: function () {
49112  
49113			this.paused = false;
49114			this.enabled = true;
49115  
49116			this.time = 0;			// restart clip
49117			this._loopCount = - 1;	// forget previous loops
49118			this._startTime = null;	// forget scheduling
49119  
49120			return this.stopFading().stopWarping();
49121  
49122		},
49123  
49124		isRunning: function () {
49125  
49126			return this.enabled && ! this.paused && this.timeScale !== 0 &&
49127					this._startTime === null && this._mixer._isActiveAction( this );
49128  
49129		},
49130  
49131		// return true when play has been called
49132		isScheduled: function () {
49133  
49134			return this._mixer._isActiveAction( this );
49135  
49136		},
49137  
49138		startAt: function ( time ) {
49139  
49140			this._startTime = time;
49141  
49142			return this;
49143  
49144		},
49145  
49146		setLoop: function ( mode, repetitions ) {
49147  
49148			this.loop = mode;
49149			this.repetitions = repetitions;
49150  
49151			return this;
49152  
49153		},
49154  
49155		// Weight
49156  
49157		// set the weight stopping any scheduled fading
49158		// although .enabled = false yields an effective weight of zero, this
49159		// method does *not* change .enabled, because it would be confusing
49160		setEffectiveWeight: function ( weight ) {
49161  
49162			this.weight = weight;
49163  
49164			// note: same logic as when updated at runtime
49165			this._effectiveWeight = this.enabled ? weight : 0;
49166  
49167			return this.stopFading();
49168  
49169		},
49170  
49171		// return the weight considering fading and .enabled
49172		getEffectiveWeight: function () {
49173  
49174			return this._effectiveWeight;
49175  
49176		},
49177  
49178		fadeIn: function ( duration ) {
49179  
49180			return this._scheduleFading( duration, 0, 1 );
49181  
49182		},
49183  
49184		fadeOut: function ( duration ) {
49185  
49186			return this._scheduleFading( duration, 1, 0 );
49187  
49188		},
49189  
49190		crossFadeFrom: function ( fadeOutAction, duration, warp ) {
49191  
49192			fadeOutAction.fadeOut( duration );
49193			this.fadeIn( duration );
49194  
49195			if ( warp ) {
49196  
49197				var fadeInDuration = this._clip.duration,
49198					fadeOutDuration = fadeOutAction._clip.duration,
49199  
49200					startEndRatio = fadeOutDuration / fadeInDuration,
49201					endStartRatio = fadeInDuration / fadeOutDuration;
49202  
49203				fadeOutAction.warp( 1.0, startEndRatio, duration );
49204				this.warp( endStartRatio, 1.0, duration );
49205  
49206			}
49207  
49208			return this;
49209  
49210		},
49211  
49212		crossFadeTo: function ( fadeInAction, duration, warp ) {
49213  
49214			return fadeInAction.crossFadeFrom( this, duration, warp );
49215  
49216		},
49217  
49218		stopFading: function () {
49219  
49220			var weightInterpolant = this._weightInterpolant;
49221  
49222			if ( weightInterpolant !== null ) {
49223  
49224				this._weightInterpolant = null;
49225				this._mixer._takeBackControlInterpolant( weightInterpolant );
49226  
49227			}
49228  
49229			return this;
49230  
49231		},
49232  
49233		// Time Scale Control
49234  
49235		// set the time scale stopping any scheduled warping
49236		// although .paused = true yields an effective time scale of zero, this
49237		// method does *not* change .paused, because it would be confusing
49238		setEffectiveTimeScale: function ( timeScale ) {
49239  
49240			this.timeScale = timeScale;
49241			this._effectiveTimeScale = this.paused ? 0 : timeScale;
49242  
49243			return this.stopWarping();
49244  
49245		},
49246  
49247		// return the time scale considering warping and .paused
49248		getEffectiveTimeScale: function () {
49249  
49250			return this._effectiveTimeScale;
49251  
49252		},
49253  
49254		setDuration: function ( duration ) {
49255  
49256			this.timeScale = this._clip.duration / duration;
49257  
49258			return this.stopWarping();
49259  
49260		},
49261  
49262		syncWith: function ( action ) {
49263  
49264			this.time = action.time;
49265			this.timeScale = action.timeScale;
49266  
49267			return this.stopWarping();
49268  
49269		},
49270  
49271		halt: function ( duration ) {
49272  
49273			return this.warp( this._effectiveTimeScale, 0, duration );
49274  
49275		},
49276  
49277		warp: function ( startTimeScale, endTimeScale, duration ) {
49278  
49279			var mixer = this._mixer, now = mixer.time,
49280				interpolant = this._timeScaleInterpolant,
49281  
49282				timeScale = this.timeScale;
49283  
49284			if ( interpolant === null ) {
49285  
49286				interpolant = mixer._lendControlInterpolant();
49287				this._timeScaleInterpolant = interpolant;
49288  
49289			}
49290  
49291			var times = interpolant.parameterPositions,
49292				values = interpolant.sampleValues;
49293  
49294			times[ 0 ] = now;
49295			times[ 1 ] = now + duration;
49296  
49297			values[ 0 ] = startTimeScale / timeScale;
49298			values[ 1 ] = endTimeScale / timeScale;
49299  
49300			return this;
49301  
49302		},
49303  
vendor: 4,213 bytes, lines 49304-49539
49304		stopWarping: function () {
49305  
49306			var timeScaleInterpolant = this._timeScaleInterpolant;
49307  
49308			if ( timeScaleInterpolant !== null ) {
49309  
49310				this._timeScaleInterpolant = null;
49311				this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
49312  
49313			}
49314  
49315			return this;
49316  
49317		},
49318  
49319		// Object Accessors
49320  
49321		getMixer: function () {
49322  
49323			return this._mixer;
49324  
49325		},
49326  
49327		getClip: function () {
49328  
49329			return this._clip;
49330  
49331		},
49332  
49333		getRoot: function () {
49334  
49335			return this._localRoot || this._mixer._root;
49336  
49337		},
49338  
49339		// Interna
49340  
49341		_update: function ( time, deltaTime, timeDirection, accuIndex ) {
49342  
49343			// called by the mixer
49344  
49345			if ( ! this.enabled ) {
49346  
49347				// call ._updateWeight() to update ._effectiveWeight
49348  
49349				this._updateWeight( time );
49350				return;
49351  
49352			}
49353  
49354			var startTime = this._startTime;
49355  
49356			if ( startTime !== null ) {
49357  
49358				// check for scheduled start of action
49359  
49360				var timeRunning = ( time - startTime ) * timeDirection;
49361				if ( timeRunning < 0 || timeDirection === 0 ) {
49362  
49363					return; // yet to come / don't decide when delta = 0
49364  
49365				}
49366  
49367				// start
49368  
49369				this._startTime = null; // unschedule
49370				deltaTime = timeDirection * timeRunning;
49371  
49372			}
49373  
49374			// apply time scale and advance time
49375  
49376			deltaTime *= this._updateTimeScale( time );
49377			var clipTime = this._updateTime( deltaTime );
49378  
49379			// note: _updateTime may disable the action resulting in
49380			// an effective weight of 0
49381  
49382			var weight = this._updateWeight( time );
49383  
49384			if ( weight > 0 ) {
49385  
49386				var interpolants = this._interpolants;
49387				var propertyMixers = this._propertyBindings;
49388  
49389				for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
49390  
49391					interpolants[ j ].evaluate( clipTime );
49392					propertyMixers[ j ].accumulate( accuIndex, weight );
49393  
49394				}
49395  
49396			}
49397  
49398		},
49399  
49400		_updateWeight: function ( time ) {
49401  
49402			var weight = 0;
49403  
49404			if ( this.enabled ) {
49405  
49406				weight = this.weight;
49407				var interpolant = this._weightInterpolant;
49408  
49409				if ( interpolant !== null ) {
49410  
49411					var interpolantValue = interpolant.evaluate( time )[ 0 ];
49412  
49413					weight *= interpolantValue;
49414  
49415					if ( time > interpolant.parameterPositions[ 1 ] ) {
49416  
49417						this.stopFading();
49418  
49419						if ( interpolantValue === 0 ) {
49420  
49421							// faded out, disable
49422							this.enabled = false;
49423  
49424						}
49425  
49426					}
49427  
49428				}
49429  
49430			}
49431  
49432			this._effectiveWeight = weight;
49433			return weight;
49434  
49435		},
49436  
49437		_updateTimeScale: function ( time ) {
49438  
49439			var timeScale = 0;
49440  
49441			if ( ! this.paused ) {
49442  
49443				timeScale = this.timeScale;
49444  
49445				var interpolant = this._timeScaleInterpolant;
49446  
49447				if ( interpolant !== null ) {
49448  
49449					var interpolantValue = interpolant.evaluate( time )[ 0 ];
49450  
49451					timeScale *= interpolantValue;
49452  
49453					if ( time > interpolant.parameterPositions[ 1 ] ) {
49454  
49455						this.stopWarping();
49456  
49457						if ( timeScale === 0 ) {
49458  
49459							// motion has halted, pause
49460							this.paused = true;
49461  
49462						} else {
49463  
49464							// warp done - apply final time scale
49465							this.timeScale = timeScale;
49466  
49467						}
49468  
49469					}
49470  
49471				}
49472  
49473			}
49474  
49475			this._effectiveTimeScale = timeScale;
49476			return timeScale;
49477  
49478		},
49479  
49480		_updateTime: function ( deltaTime ) {
49481  
49482			var time = this.time + deltaTime;
49483  
49484			if ( deltaTime === 0 ) return time;
49485  
49486			var duration = this._clip.duration,
49487  
49488				loop = this.loop,
49489				loopCount = this._loopCount;
49490  
49491			if ( loop === LoopOnce ) {
49492  
49493				if ( loopCount === - 1 ) {
49494  
49495					// just started
49496  
49497					this._loopCount = 0;
49498					this._setEndings( true, true, false );
49499  
49500				}
49501  
49502				handle_stop: {
49503  
49504					if ( time >= duration ) {
49505  
49506						time = duration;
49507  
49508					} else if ( time < 0 ) {
49509  
49510						time = 0;
49511  
49512					} else break handle_stop;
49513  
49514					if ( this.clampWhenFinished ) this.paused = true;
49515					else this.enabled = false;
49516  
49517					this._mixer.dispatchEvent( {
49518						type: 'finished', action: this,
49519						direction: deltaTime < 0 ? - 1 : 1
49520					} );
49521  
49522				}
49523  
49524			} else { // repetitive Repeat or PingPong
49525  
49526				var pingPong = ( loop === LoopPingPong );
49527  
49528				if ( loopCount === - 1 ) {
49529  
49530					// just started
49531  
49532					if ( deltaTime >= 0 ) {
49533  
49534						loopCount = 0;
49535  
49536						this._setEndings( true, this.repetitions === 0, pingPong );
49537  
49538					} else {
49539  
vendor: 8,768 bytes, lines 49540-49968
49540						// when looping in reverse direction, the initial
49541						// transition through zero counts as a repetition,
49542						// so leave loopCount at -1
49543  
49544						this._setEndings( this.repetitions === 0, true, pingPong );
49545  
49546					}
49547  
49548				}
49549  
49550				if ( time >= duration || time < 0 ) {
49551  
49552					// wrap around
49553  
49554					var loopDelta = Math.floor( time / duration ); // signed
49555					time -= duration * loopDelta;
49556  
49557					loopCount += Math.abs( loopDelta );
49558  
49559					var pending = this.repetitions - loopCount;
49560  
49561					if ( pending <= 0 ) {
49562  
49563						// have to stop (switch state, clamp time, fire event)
49564  
49565						if ( this.clampWhenFinished ) this.paused = true;
49566						else this.enabled = false;
49567  
49568						time = deltaTime > 0 ? duration : 0;
49569  
49570						this._mixer.dispatchEvent( {
49571							type: 'finished', action: this,
49572							direction: deltaTime > 0 ? 1 : - 1
49573						} );
49574  
49575					} else {
49576  
49577						// keep running
49578  
49579						if ( pending === 1 ) {
49580  
49581							// entering the last round
49582  
49583							var atStart = deltaTime < 0;
49584							this._setEndings( atStart, ! atStart, pingPong );
49585  
49586						} else {
49587  
49588							this._setEndings( false, false, pingPong );
49589  
49590						}
49591  
49592						this._loopCount = loopCount;
49593  
49594						this._mixer.dispatchEvent( {
49595							type: 'loop', action: this, loopDelta: loopDelta
49596						} );
49597  
49598					}
49599  
49600				}
49601  
49602				if ( pingPong && ( loopCount & 1 ) === 1 ) {
49603  
49604					// invert time for the "pong round"
49605  
49606					this.time = time;
49607					return duration - time;
49608  
49609				}
49610  
49611			}
49612  
49613			this.time = time;
49614			return time;
49615  
49616		},
49617  
49618		_setEndings: function ( atStart, atEnd, pingPong ) {
49619  
49620			var settings = this._interpolantSettings;
49621  
49622			if ( pingPong ) {
49623  
49624				settings.endingStart 	= ZeroSlopeEnding;
49625				settings.endingEnd		= ZeroSlopeEnding;
49626  
49627			} else {
49628  
49629				// assuming for LoopOnce atStart == atEnd == true
49630  
49631				if ( atStart ) {
49632  
49633					settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
49634  
49635				} else {
49636  
49637					settings.endingStart = WrapAroundEnding;
49638  
49639				}
49640  
49641				if ( atEnd ) {
49642  
49643					settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
49644  
49645				} else {
49646  
49647					settings.endingEnd 	 = WrapAroundEnding;
49648  
49649				}
49650  
49651			}
49652  
49653		},
49654  
49655		_scheduleFading: function ( duration, weightNow, weightThen ) {
49656  
49657			var mixer = this._mixer, now = mixer.time,
49658				interpolant = this._weightInterpolant;
49659  
49660			if ( interpolant === null ) {
49661  
49662				interpolant = mixer._lendControlInterpolant();
49663				this._weightInterpolant = interpolant;
49664  
49665			}
49666  
49667			var times = interpolant.parameterPositions,
49668				values = interpolant.sampleValues;
49669  
49670			times[ 0 ] = now; 				values[ 0 ] = weightNow;
49671			times[ 1 ] = now + duration;	values[ 1 ] = weightThen;
49672  
49673			return this;
49674  
49675		}
49676  
49677	} );
49678  
49679	/**
49680	 *
49681	 * Player for AnimationClips.
49682	 *
49683	 *
49684	 * @author Ben Houston / http://clara.io/
49685	 * @author David Sarno / http://lighthaus.us/
49686	 * @author tschw
49687	 */
49688  
49689	function AnimationMixer( root ) {
49690  
49691		this._root = root;
49692		this._initMemoryManager();
49693		this._accuIndex = 0;
49694  
49695		this.time = 0;
49696  
49697		this.timeScale = 1.0;
49698  
49699	}
49700  
49701	AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
49702  
49703		constructor: AnimationMixer,
49704  
49705		_bindAction: function ( action, prototypeAction ) {
49706  
49707			var root = action._localRoot || this._root,
49708				tracks = action._clip.tracks,
49709				nTracks = tracks.length,
49710				bindings = action._propertyBindings,
49711				interpolants = action._interpolants,
49712				rootUuid = root.uuid,
49713				bindingsByRoot = this._bindingsByRootAndName,
49714				bindingsByName = bindingsByRoot[ rootUuid ];
49715  
49716			if ( bindingsByName === undefined ) {
49717  
49718				bindingsByName = {};
49719				bindingsByRoot[ rootUuid ] = bindingsByName;
49720  
49721			}
49722  
49723			for ( var i = 0; i !== nTracks; ++ i ) {
49724  
49725				var track = tracks[ i ],
49726					trackName = track.name,
49727					binding = bindingsByName[ trackName ];
49728  
49729				if ( binding !== undefined ) {
49730  
49731					bindings[ i ] = binding;
49732  
49733				} else {
49734  
49735					binding = bindings[ i ];
49736  
49737					if ( binding !== undefined ) {
49738  
49739						// existing binding, make sure the cache knows
49740  
49741						if ( binding._cacheIndex === null ) {
49742  
49743							++ binding.referenceCount;
49744							this._addInactiveBinding( binding, rootUuid, trackName );
49745  
49746						}
49747  
49748						continue;
49749  
49750					}
49751  
49752					var path = prototypeAction && prototypeAction.
49753						_propertyBindings[ i ].binding.parsedPath;
49754  
49755					binding = new PropertyMixer(
49756						PropertyBinding.create( root, trackName, path ),
49757						track.ValueTypeName, track.getValueSize() );
49758  
49759					++ binding.referenceCount;
49760					this._addInactiveBinding( binding, rootUuid, trackName );
49761  
49762					bindings[ i ] = binding;
49763  
49764				}
49765  
49766				interpolants[ i ].resultBuffer = binding.buffer;
49767  
49768			}
49769  
49770		},
49771  
49772		_activateAction: function ( action ) {
49773  
49774			if ( ! this._isActiveAction( action ) ) {
49775  
49776				if ( action._cacheIndex === null ) {
49777  
49778					// this action has been forgotten by the cache, but the user
49779					// appears to be still using it -> rebind
49780  
49781					var rootUuid = ( action._localRoot || this._root ).uuid,
49782						clipUuid = action._clip.uuid,
49783						actionsForClip = this._actionsByClip[ clipUuid ];
49784  
49785					this._bindAction( action,
49786						actionsForClip && actionsForClip.knownActions[ 0 ] );
49787  
49788					this._addInactiveAction( action, clipUuid, rootUuid );
49789  
49790				}
49791  
49792				var bindings = action._propertyBindings;
49793  
49794				// increment reference counts / sort out state
49795				for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
49796  
49797					var binding = bindings[ i ];
49798  
49799					if ( binding.useCount ++ === 0 ) {
49800  
49801						this._lendBinding( binding );
49802						binding.saveOriginalState();
49803  
49804					}
49805  
49806				}
49807  
49808				this._lendAction( action );
49809  
49810			}
49811  
49812		},
49813  
49814		_deactivateAction: function ( action ) {
49815  
49816			if ( this._isActiveAction( action ) ) {
49817  
49818				var bindings = action._propertyBindings;
49819  
49820				// decrement reference counts / sort out state
49821				for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
49822  
49823					var binding = bindings[ i ];
49824  
49825					if ( -- binding.useCount === 0 ) {
49826  
49827						binding.restoreOriginalState();
49828						this._takeBackBinding( binding );
49829  
49830					}
49831  
49832				}
49833  
49834				this._takeBackAction( action );
49835  
49836			}
49837  
49838		},
49839  
49840		// Memory manager
49841  
49842		_initMemoryManager: function () {
49843  
49844			this._actions = []; // 'nActiveActions' followed by inactive ones
49845			this._nActiveActions = 0;
49846  
49847			this._actionsByClip = {};
49848			// inside:
49849			// {
49850			// 		knownActions: Array< AnimationAction >	- used as prototypes
49851			// 		actionByRoot: AnimationAction			- lookup
49852			// }
49853  
49854  
49855			this._bindings = []; // 'nActiveBindings' followed by inactive ones
49856			this._nActiveBindings = 0;
49857  
49858			this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
49859  
49860  
49861			this._controlInterpolants = []; // same game as above
49862			this._nActiveControlInterpolants = 0;
49863  
49864			var scope = this;
49865  
49866			this.stats = {
49867  
49868				actions: {
49869					get total() {
49870  
49871						return scope._actions.length;
49872  
49873					},
49874					get inUse() {
49875  
49876						return scope._nActiveActions;
49877  
49878					}
49879				},
49880				bindings: {
49881					get total() {
49882  
49883						return scope._bindings.length;
49884  
49885					},
49886					get inUse() {
49887  
49888						return scope._nActiveBindings;
49889  
49890					}
49891				},
49892				controlInterpolants: {
49893					get total() {
49894  
49895						return scope._controlInterpolants.length;
49896  
49897					},
49898					get inUse() {
49899  
49900						return scope._nActiveControlInterpolants;
49901  
49902					}
49903				}
49904  
49905			};
49906  
49907		},
49908  
49909		// Memory management for AnimationAction objects
49910  
49911		_isActiveAction: function ( action ) {
49912  
49913			var index = action._cacheIndex;
49914			return index !== null && index < this._nActiveActions;
49915  
49916		},
49917  
49918		_addInactiveAction: function ( action, clipUuid, rootUuid ) {
49919  
49920			var actions = this._actions,
49921				actionsByClip = this._actionsByClip,
49922				actionsForClip = actionsByClip[ clipUuid ];
49923  
49924			if ( actionsForClip === undefined ) {
49925  
49926				actionsForClip = {
49927  
49928					knownActions: [ action ],
49929					actionByRoot: {}
49930  
49931				};
49932  
49933				action._byClipCacheIndex = 0;
49934  
49935				actionsByClip[ clipUuid ] = actionsForClip;
49936  
49937			} else {
49938  
49939				var knownActions = actionsForClip.knownActions;
49940  
49941				action._byClipCacheIndex = knownActions.length;
49942				knownActions.push( action );
49943  
49944			}
49945  
49946			action._cacheIndex = actions.length;
49947			actions.push( action );
49948  
49949			actionsForClip.actionByRoot[ rootUuid ] = action;
49950  
49951		},
49952  
49953		_removeInactiveAction: function ( action ) {
49954  
49955			var actions = this._actions,
49956				lastInactiveAction = actions[ actions.length - 1 ],
49957				cacheIndex = action._cacheIndex;
49958  
49959			lastInactiveAction._cacheIndex = cacheIndex;
49960			actions[ cacheIndex ] = lastInactiveAction;
49961			actions.pop();
49962  
49963			action._cacheIndex = null;
49964  
49965  
49966			var clipUuid = action._clip.uuid,
49967				actionsByClip = this._actionsByClip,
49968				actionsForClip = actionsByClip[ clipUuid ],
vendor: 4,311 bytes, lines 49969-50145
49969				knownActionsForClip = actionsForClip.knownActions,
49970  
49971				lastKnownAction =
49972					knownActionsForClip[ knownActionsForClip.length - 1 ],
49973  
49974				byClipCacheIndex = action._byClipCacheIndex;
49975  
49976			lastKnownAction._byClipCacheIndex = byClipCacheIndex;
49977			knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
49978			knownActionsForClip.pop();
49979  
49980			action._byClipCacheIndex = null;
49981  
49982  
49983			var actionByRoot = actionsForClip.actionByRoot,
49984				rootUuid = ( action._localRoot || this._root ).uuid;
49985  
49986			delete actionByRoot[ rootUuid ];
49987  
49988			if ( knownActionsForClip.length === 0 ) {
49989  
49990				delete actionsByClip[ clipUuid ];
49991  
49992			}
49993  
49994			this._removeInactiveBindingsForAction( action );
49995  
49996		},
49997  
49998		_removeInactiveBindingsForAction: function ( action ) {
49999  
50000			var bindings = action._propertyBindings;
50001			for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
50002  
50003				var binding = bindings[ i ];
50004  
50005				if ( -- binding.referenceCount === 0 ) {
50006  
50007					this._removeInactiveBinding( binding );
50008  
50009				}
50010  
50011			}
50012  
50013		},
50014  
50015		_lendAction: function ( action ) {
50016  
50017			// [ active actions |  inactive actions  ]
50018			// [  active actions >| inactive actions ]
50019			//                 s        a
50020			//                  <-swap->
50021			//                 a        s
50022  
50023			var actions = this._actions,
50024				prevIndex = action._cacheIndex,
50025  
50026				lastActiveIndex = this._nActiveActions ++,
50027  
50028				firstInactiveAction = actions[ lastActiveIndex ];
50029  
50030			action._cacheIndex = lastActiveIndex;
50031			actions[ lastActiveIndex ] = action;
50032  
50033			firstInactiveAction._cacheIndex = prevIndex;
50034			actions[ prevIndex ] = firstInactiveAction;
50035  
50036		},
50037  
50038		_takeBackAction: function ( action ) {
50039  
50040			// [  active actions  | inactive actions ]
50041			// [ active actions |< inactive actions  ]
50042			//        a        s
50043			//         <-swap->
50044			//        s        a
50045  
50046			var actions = this._actions,
50047				prevIndex = action._cacheIndex,
50048  
50049				firstInactiveIndex = -- this._nActiveActions,
50050  
50051				lastActiveAction = actions[ firstInactiveIndex ];
50052  
50053			action._cacheIndex = firstInactiveIndex;
50054			actions[ firstInactiveIndex ] = action;
50055  
50056			lastActiveAction._cacheIndex = prevIndex;
50057			actions[ prevIndex ] = lastActiveAction;
50058  
50059		},
50060  
50061		// Memory management for PropertyMixer objects
50062  
50063		_addInactiveBinding: function ( binding, rootUuid, trackName ) {
50064  
50065			var bindingsByRoot = this._bindingsByRootAndName,
50066				bindingByName = bindingsByRoot[ rootUuid ],
50067  
50068				bindings = this._bindings;
50069  
50070			if ( bindingByName === undefined ) {
50071  
50072				bindingByName = {};
50073				bindingsByRoot[ rootUuid ] = bindingByName;
50074  
50075			}
50076  
50077			bindingByName[ trackName ] = binding;
50078  
50079			binding._cacheIndex = bindings.length;
50080			bindings.push( binding );
50081  
50082		},
50083  
50084		_removeInactiveBinding: function ( binding ) {
50085  
50086			var bindings = this._bindings,
50087				propBinding = binding.binding,
50088				rootUuid = propBinding.rootNode.uuid,
50089				trackName = propBinding.path,
50090				bindingsByRoot = this._bindingsByRootAndName,
50091				bindingByName = bindingsByRoot[ rootUuid ],
50092  
50093				lastInactiveBinding = bindings[ bindings.length - 1 ],
50094				cacheIndex = binding._cacheIndex;
50095  
50096			lastInactiveBinding._cacheIndex = cacheIndex;
50097			bindings[ cacheIndex ] = lastInactiveBinding;
50098			bindings.pop();
50099  
50100			delete bindingByName[ trackName ];
50101  
50102			remove_empty_map: {
50103  
50104				for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars
50105  
50106				delete bindingsByRoot[ rootUuid ];
50107  
50108			}
50109  
50110		},
50111  
50112		_lendBinding: function ( binding ) {
50113  
50114			var bindings = this._bindings,
50115				prevIndex = binding._cacheIndex,
50116  
50117				lastActiveIndex = this._nActiveBindings ++,
50118  
50119				firstInactiveBinding = bindings[ lastActiveIndex ];
50120  
50121			binding._cacheIndex = lastActiveIndex;
50122			bindings[ lastActiveIndex ] = binding;
50123  
50124			firstInactiveBinding._cacheIndex = prevIndex;
50125			bindings[ prevIndex ] = firstInactiveBinding;
50126  
50127		},
50128  
50129		_takeBackBinding: function ( binding ) {
50130  
50131			var bindings = this._bindings,
50132				prevIndex = binding._cacheIndex,
50133  
50134				firstInactiveIndex = -- this._nActiveBindings,
50135  
50136				lastActiveBinding = bindings[ firstInactiveIndex ];
50137  
50138			binding._cacheIndex = firstInactiveIndex;
50139			bindings[ firstInactiveIndex ] = binding;
50140  
50141			lastActiveBinding._cacheIndex = prevIndex;
50142			bindings[ prevIndex ] = lastActiveBinding;
50143  
50144		},
50145  
vendor: 17,907 bytes, lines 50146-51017
50146  
50147		// Memory management of Interpolants for weight and time scale
50148  
50149		_lendControlInterpolant: function () {
50150  
50151			var interpolants = this._controlInterpolants,
50152				lastActiveIndex = this._nActiveControlInterpolants ++,
50153				interpolant = interpolants[ lastActiveIndex ];
50154  
50155			if ( interpolant === undefined ) {
50156  
50157				interpolant = new LinearInterpolant(
50158					new Float32Array( 2 ), new Float32Array( 2 ),
50159					1, this._controlInterpolantsResultBuffer );
50160  
50161				interpolant.__cacheIndex = lastActiveIndex;
50162				interpolants[ lastActiveIndex ] = interpolant;
50163  
50164			}
50165  
50166			return interpolant;
50167  
50168		},
50169  
50170		_takeBackControlInterpolant: function ( interpolant ) {
50171  
50172			var interpolants = this._controlInterpolants,
50173				prevIndex = interpolant.__cacheIndex,
50174  
50175				firstInactiveIndex = -- this._nActiveControlInterpolants,
50176  
50177				lastActiveInterpolant = interpolants[ firstInactiveIndex ];
50178  
50179			interpolant.__cacheIndex = firstInactiveIndex;
50180			interpolants[ firstInactiveIndex ] = interpolant;
50181  
50182			lastActiveInterpolant.__cacheIndex = prevIndex;
50183			interpolants[ prevIndex ] = lastActiveInterpolant;
50184  
50185		},
50186  
50187		_controlInterpolantsResultBuffer: new Float32Array( 1 ),
50188  
50189		// return an action for a clip optionally using a custom root target
50190		// object (this method allocates a lot of dynamic memory in case a
50191		// previously unknown clip/root combination is specified)
50192		clipAction: function ( clip, optionalRoot ) {
50193  
50194			var root = optionalRoot || this._root,
50195				rootUuid = root.uuid,
50196  
50197				clipObject = typeof clip === 'string' ?
50198					AnimationClip.findByName( root, clip ) : clip,
50199  
50200				clipUuid = clipObject !== null ? clipObject.uuid : clip,
50201  
50202				actionsForClip = this._actionsByClip[ clipUuid ],
50203				prototypeAction = null;
50204  
50205			if ( actionsForClip !== undefined ) {
50206  
50207				var existingAction =
50208						actionsForClip.actionByRoot[ rootUuid ];
50209  
50210				if ( existingAction !== undefined ) {
50211  
50212					return existingAction;
50213  
50214				}
50215  
50216				// we know the clip, so we don't have to parse all
50217				// the bindings again but can just copy
50218				prototypeAction = actionsForClip.knownActions[ 0 ];
50219  
50220				// also, take the clip from the prototype action
50221				if ( clipObject === null )
50222					clipObject = prototypeAction._clip;
50223  
50224			}
50225  
50226			// clip must be known when specified via string
50227			if ( clipObject === null ) return null;
50228  
50229			// allocate all resources required to run it
50230			var newAction = new AnimationAction( this, clipObject, optionalRoot );
50231  
50232			this._bindAction( newAction, prototypeAction );
50233  
50234			// and make the action known to the memory manager
50235			this._addInactiveAction( newAction, clipUuid, rootUuid );
50236  
50237			return newAction;
50238  
50239		},
50240  
50241		// get an existing action
50242		existingAction: function ( clip, optionalRoot ) {
50243  
50244			var root = optionalRoot || this._root,
50245				rootUuid = root.uuid,
50246  
50247				clipObject = typeof clip === 'string' ?
50248					AnimationClip.findByName( root, clip ) : clip,
50249  
50250				clipUuid = clipObject ? clipObject.uuid : clip,
50251  
50252				actionsForClip = this._actionsByClip[ clipUuid ];
50253  
50254			if ( actionsForClip !== undefined ) {
50255  
50256				return actionsForClip.actionByRoot[ rootUuid ] || null;
50257  
50258			}
50259  
50260			return null;
50261  
50262		},
50263  
50264		// deactivates all previously scheduled actions
50265		stopAllAction: function () {
50266  
50267			var actions = this._actions,
50268				nActions = this._nActiveActions,
50269				bindings = this._bindings,
50270				nBindings = this._nActiveBindings;
50271  
50272			this._nActiveActions = 0;
50273			this._nActiveBindings = 0;
50274  
50275			for ( var i = 0; i !== nActions; ++ i ) {
50276  
50277				actions[ i ].reset();
50278  
50279			}
50280  
50281			for ( var i = 0; i !== nBindings; ++ i ) {
50282  
50283				bindings[ i ].useCount = 0;
50284  
50285			}
50286  
50287			return this;
50288  
50289		},
50290  
50291		// advance the time and update apply the animation
50292		update: function ( deltaTime ) {
50293  
50294			deltaTime *= this.timeScale;
50295  
50296			var actions = this._actions,
50297				nActions = this._nActiveActions,
50298  
50299				time = this.time += deltaTime,
50300				timeDirection = Math.sign( deltaTime ),
50301  
50302				accuIndex = this._accuIndex ^= 1;
50303  
50304			// run active actions
50305  
50306			for ( var i = 0; i !== nActions; ++ i ) {
50307  
50308				var action = actions[ i ];
50309  
50310				action._update( time, deltaTime, timeDirection, accuIndex );
50311  
50312			}
50313  
50314			// update scene graph
50315  
50316			var bindings = this._bindings,
50317				nBindings = this._nActiveBindings;
50318  
50319			for ( var i = 0; i !== nBindings; ++ i ) {
50320  
50321				bindings[ i ].apply( accuIndex );
50322  
50323			}
50324  
50325			return this;
50326  
50327		},
50328  
50329		// return this mixer's root target object
50330		getRoot: function () {
50331  
50332			return this._root;
50333  
50334		},
50335  
50336		// free all resources specific to a particular clip
50337		uncacheClip: function ( clip ) {
50338  
50339			var actions = this._actions,
50340				clipUuid = clip.uuid,
50341				actionsByClip = this._actionsByClip,
50342				actionsForClip = actionsByClip[ clipUuid ];
50343  
50344			if ( actionsForClip !== undefined ) {
50345  
50346				// note: just calling _removeInactiveAction would mess up the
50347				// iteration state and also require updating the state we can
50348				// just throw away
50349  
50350				var actionsToRemove = actionsForClip.knownActions;
50351  
50352				for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
50353  
50354					var action = actionsToRemove[ i ];
50355  
50356					this._deactivateAction( action );
50357  
50358					var cacheIndex = action._cacheIndex,
50359						lastInactiveAction = actions[ actions.length - 1 ];
50360  
50361					action._cacheIndex = null;
50362					action._byClipCacheIndex = null;
50363  
50364					lastInactiveAction._cacheIndex = cacheIndex;
50365					actions[ cacheIndex ] = lastInactiveAction;
50366					actions.pop();
50367  
50368					this._removeInactiveBindingsForAction( action );
50369  
50370				}
50371  
50372				delete actionsByClip[ clipUuid ];
50373  
50374			}
50375  
50376		},
50377  
50378		// free all resources specific to a particular root target object
50379		uncacheRoot: function ( root ) {
50380  
50381			var rootUuid = root.uuid,
50382				actionsByClip = this._actionsByClip;
50383  
50384			for ( var clipUuid in actionsByClip ) {
50385  
50386				var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
50387					action = actionByRoot[ rootUuid ];
50388  
50389				if ( action !== undefined ) {
50390  
50391					this._deactivateAction( action );
50392					this._removeInactiveAction( action );
50393  
50394				}
50395  
50396			}
50397  
50398			var bindingsByRoot = this._bindingsByRootAndName,
50399				bindingByName = bindingsByRoot[ rootUuid ];
50400  
50401			if ( bindingByName !== undefined ) {
50402  
50403				for ( var trackName in bindingByName ) {
50404  
50405					var binding = bindingByName[ trackName ];
50406					binding.restoreOriginalState();
50407					this._removeInactiveBinding( binding );
50408  
50409				}
50410  
50411			}
50412  
50413		},
50414  
50415		// remove a targeted clip from the cache
50416		uncacheAction: function ( clip, optionalRoot ) {
50417  
50418			var action = this.existingAction( clip, optionalRoot );
50419  
50420			if ( action !== null ) {
50421  
50422				this._deactivateAction( action );
50423				this._removeInactiveAction( action );
50424  
50425			}
50426  
50427		}
50428  
50429	} );
50430  
50431	/**
50432	 * @author mrdoob / http://mrdoob.com/
50433	 */
50434  
50435	function Uniform( value ) {
50436  
50437		if ( typeof value === 'string' ) {
50438  
50439			console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
50440			value = arguments[ 1 ];
50441  
50442		}
50443  
50444		this.value = value;
50445  
50446	}
50447  
50448	Uniform.prototype.clone = function () {
50449  
50450		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
50451  
50452	};
50453  
50454	/**
50455	 * @author benaadams / https://twitter.com/ben_a_adams
50456	 */
50457  
50458	function InstancedBufferGeometry() {
50459  
50460		BufferGeometry.call( this );
50461  
50462		this.type = 'InstancedBufferGeometry';
50463		this.maxInstancedCount = undefined;
50464  
50465	}
50466  
50467	InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
50468  
50469		constructor: InstancedBufferGeometry,
50470  
50471		isInstancedBufferGeometry: true,
50472  
50473		copy: function ( source ) {
50474  
50475			BufferGeometry.prototype.copy.call( this, source );
50476  
50477			this.maxInstancedCount = source.maxInstancedCount;
50478  
50479			return this;
50480  
50481		},
50482  
50483		clone: function () {
50484  
50485			return new this.constructor().copy( this );
50486  
50487		}
50488  
50489	} );
50490  
50491	/**
50492	 * @author benaadams / https://twitter.com/ben_a_adams
50493	 */
50494  
50495	function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
50496  
50497		this.data = interleavedBuffer;
50498		this.itemSize = itemSize;
50499		this.offset = offset;
50500  
50501		this.normalized = normalized === true;
50502  
50503	}
50504  
50505	Object.defineProperties( InterleavedBufferAttribute.prototype, {
50506  
50507		count: {
50508  
50509			get: function () {
50510  
50511				return this.data.count;
50512  
50513			}
50514  
50515		},
50516  
50517		array: {
50518  
50519			get: function () {
50520  
50521				return this.data.array;
50522  
50523			}
50524  
50525		}
50526  
50527	} );
50528  
50529	Object.assign( InterleavedBufferAttribute.prototype, {
50530  
50531		isInterleavedBufferAttribute: true,
50532  
50533		setX: function ( index, x ) {
50534  
50535			this.data.array[ index * this.data.stride + this.offset ] = x;
50536  
50537			return this;
50538  
50539		},
50540  
50541		setY: function ( index, y ) {
50542  
50543			this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
50544  
50545			return this;
50546  
50547		},
50548  
50549		setZ: function ( index, z ) {
50550  
50551			this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
50552  
50553			return this;
50554  
50555		},
50556  
50557		setW: function ( index, w ) {
50558  
50559			this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
50560  
50561			return this;
50562  
50563		},
50564  
50565		getX: function ( index ) {
50566  
50567			return this.data.array[ index * this.data.stride + this.offset ];
50568  
50569		},
50570  
50571		getY: function ( index ) {
50572  
50573			return this.data.array[ index * this.data.stride + this.offset + 1 ];
50574  
50575		},
50576  
50577		getZ: function ( index ) {
50578  
50579			return this.data.array[ index * this.data.stride + this.offset + 2 ];
50580  
50581		},
50582  
50583		getW: function ( index ) {
50584  
50585			return this.data.array[ index * this.data.stride + this.offset + 3 ];
50586  
50587		},
50588  
50589		setXY: function ( index, x, y ) {
50590  
50591			index = index * this.data.stride + this.offset;
50592  
50593			this.data.array[ index + 0 ] = x;
50594			this.data.array[ index + 1 ] = y;
50595  
50596			return this;
50597  
50598		},
50599  
50600		setXYZ: function ( index, x, y, z ) {
50601  
50602			index = index * this.data.stride + this.offset;
50603  
50604			this.data.array[ index + 0 ] = x;
50605			this.data.array[ index + 1 ] = y;
50606			this.data.array[ index + 2 ] = z;
50607  
50608			return this;
50609  
50610		},
50611  
50612		setXYZW: function ( index, x, y, z, w ) {
50613  
50614			index = index * this.data.stride + this.offset;
50615  
50616			this.data.array[ index + 0 ] = x;
50617			this.data.array[ index + 1 ] = y;
50618			this.data.array[ index + 2 ] = z;
50619			this.data.array[ index + 3 ] = w;
50620  
50621			return this;
50622  
50623		}
50624  
50625	} );
50626  
50627	/**
50628	 * @author benaadams / https://twitter.com/ben_a_adams
50629	 */
50630  
50631	function InterleavedBuffer( array, stride ) {
50632  
50633		this.array = array;
50634		this.stride = stride;
50635		this.count = array !== undefined ? array.length / stride : 0;
50636  
50637		this.dynamic = false;
50638		this.updateRange = { offset: 0, count: - 1 };
50639  
50640		this.version = 0;
50641  
50642	}
50643  
50644	Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
50645  
50646		set: function ( value ) {
50647  
50648			if ( value === true ) this.version ++;
50649  
50650		}
50651  
50652	} );
50653  
50654	Object.assign( InterleavedBuffer.prototype, {
50655  
50656		isInterleavedBuffer: true,
50657  
50658		onUploadCallback: function () {},
50659  
50660		setArray: function ( array ) {
50661  
50662			if ( Array.isArray( array ) ) {
50663  
50664				throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
50665  
50666			}
50667  
50668			this.count = array !== undefined ? array.length / this.stride : 0;
50669			this.array = array;
50670  
50671			return this;
50672  
50673		},
50674  
50675		setDynamic: function ( value ) {
50676  
50677			this.dynamic = value;
50678  
50679			return this;
50680  
50681		},
50682  
50683		copy: function ( source ) {
50684  
50685			this.array = new source.array.constructor( source.array );
50686			this.count = source.count;
50687			this.stride = source.stride;
50688			this.dynamic = source.dynamic;
50689  
50690			return this;
50691  
50692		},
50693  
50694		copyAt: function ( index1, attribute, index2 ) {
50695  
50696			index1 *= this.stride;
50697			index2 *= attribute.stride;
50698  
50699			for ( var i = 0, l = this.stride; i < l; i ++ ) {
50700  
50701				this.array[ index1 + i ] = attribute.array[ index2 + i ];
50702  
50703			}
50704  
50705			return this;
50706  
50707		},
50708  
50709		set: function ( value, offset ) {
50710  
50711			if ( offset === undefined ) offset = 0;
50712  
50713			this.array.set( value, offset );
50714  
50715			return this;
50716  
50717		},
50718  
50719		clone: function () {
50720  
50721			return new this.constructor().copy( this );
50722  
50723		},
50724  
50725		onUpload: function ( callback ) {
50726  
50727			this.onUploadCallback = callback;
50728  
50729			return this;
50730  
50731		}
50732  
50733	} );
50734  
50735	/**
50736	 * @author benaadams / https://twitter.com/ben_a_adams
50737	 */
50738  
50739	function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
50740  
50741		InterleavedBuffer.call( this, array, stride );
50742  
50743		this.meshPerAttribute = meshPerAttribute || 1;
50744  
50745	}
50746  
50747	InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
50748  
50749		constructor: InstancedInterleavedBuffer,
50750  
50751		isInstancedInterleavedBuffer: true,
50752  
50753		copy: function ( source ) {
50754  
50755			InterleavedBuffer.prototype.copy.call( this, source );
50756  
50757			this.meshPerAttribute = source.meshPerAttribute;
50758  
50759			return this;
50760  
50761		}
50762  
50763	} );
50764  
50765	/**
50766	 * @author benaadams / https://twitter.com/ben_a_adams
50767	 */
50768  
50769	function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) {
50770  
50771		BufferAttribute.call( this, array, itemSize );
50772  
50773		this.meshPerAttribute = meshPerAttribute || 1;
50774  
50775	}
50776  
50777	InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
50778  
50779		constructor: InstancedBufferAttribute,
50780  
50781		isInstancedBufferAttribute: true,
50782  
50783		copy: function ( source ) {
50784  
50785			BufferAttribute.prototype.copy.call( this, source );
50786  
50787			this.meshPerAttribute = source.meshPerAttribute;
50788  
50789			return this;
50790  
50791		}
50792  
50793	} );
50794  
50795	/**
50796	 * @author mrdoob / http://mrdoob.com/
50797	 * @author bhouston / http://clara.io/
50798	 * @author stephomi / http://stephaneginier.com/
50799	 */
50800  
50801	function Raycaster( origin, direction, near, far ) {
50802  
50803		this.ray = new Ray( origin, direction );
50804		// direction is assumed to be normalized (for accurate distance calculations)
50805  
50806		this.near = near || 0;
50807		this.far = far || Infinity;
50808  
50809		this.params = {
50810			Mesh: {},
50811			Line: {},
50812			LOD: {},
50813			Points: { threshold: 1 },
50814			Sprite: {}
50815		};
50816  
50817		Object.defineProperties( this.params, {
50818			PointCloud: {
50819				get: function () {
50820  
50821					console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
50822					return this.Points;
50823  
50824				}
50825			}
50826		} );
50827  
50828	}
50829  
50830	function ascSort( a, b ) {
50831  
50832		return a.distance - b.distance;
50833  
50834	}
50835  
50836	function intersectObject( object, raycaster, intersects, recursive ) {
50837  
50838		if ( object.visible === false ) return;
50839  
50840		object.raycast( raycaster, intersects );
50841  
50842		if ( recursive === true ) {
50843  
50844			var children = object.children;
50845  
50846			for ( var i = 0, l = children.length; i < l; i ++ ) {
50847  
50848				intersectObject( children[ i ], raycaster, intersects, true );
50849  
50850			}
50851  
50852		}
50853  
50854	}
50855  
50856	Object.assign( Raycaster.prototype, {
50857  
50858		linePrecision: 1,
50859  
50860		set: function ( origin, direction ) {
50861  
50862			// direction is assumed to be normalized (for accurate distance calculations)
50863  
50864			this.ray.set( origin, direction );
50865  
50866		},
50867  
50868		setFromCamera: function ( coords, camera ) {
50869  
50870			if ( ( camera && camera.isPerspectiveCamera ) ) {
50871  
50872				this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
50873				this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
50874  
50875			} else if ( ( camera && camera.isOrthographicCamera ) ) {
50876  
50877				this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
50878				this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
50879  
50880			} else {
50881  
50882				console.error( 'THREE.Raycaster: Unsupported camera type.' );
50883  
50884			}
50885  
50886		},
50887  
50888		intersectObject: function ( object, recursive, optionalTarget ) {
50889  
50890			var intersects = optionalTarget || [];
50891  
50892			intersectObject( object, this, intersects, recursive );
50893  
50894			intersects.sort( ascSort );
50895  
50896			return intersects;
50897  
50898		},
50899  
50900		intersectObjects: function ( objects, recursive, optionalTarget ) {
50901  
50902			var intersects = optionalTarget || [];
50903  
50904			if ( Array.isArray( objects ) === false ) {
50905  
50906				console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
50907				return intersects;
50908  
50909			}
50910  
50911			for ( var i = 0, l = objects.length; i < l; i ++ ) {
50912  
50913				intersectObject( objects[ i ], this, intersects, recursive );
50914  
50915			}
50916  
50917			intersects.sort( ascSort );
50918  
50919			return intersects;
50920  
50921		}
50922  
50923	} );
50924  
50925	/**
50926	 * @author alteredq / http://alteredqualia.com/
50927	 */
50928  
50929	function Clock( autoStart ) {
50930  
50931		this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
50932  
50933		this.startTime = 0;
50934		this.oldTime = 0;
50935		this.elapsedTime = 0;
50936  
50937		this.running = false;
50938  
50939	}
50940  
50941	Object.assign( Clock.prototype, {
50942  
50943		start: function () {
50944  
50945			this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
50946  
50947			this.oldTime = this.startTime;
50948			this.elapsedTime = 0;
50949			this.running = true;
50950  
50951		},
50952  
50953		stop: function () {
50954  
50955			this.getElapsedTime();
50956			this.running = false;
50957			this.autoStart = false;
50958  
50959		},
50960  
50961		getElapsedTime: function () {
50962  
50963			this.getDelta();
50964			return this.elapsedTime;
50965  
50966		},
50967  
50968		getDelta: function () {
50969  
50970			var diff = 0;
50971  
50972			if ( this.autoStart && ! this.running ) {
50973  
50974				this.start();
50975				return 0;
50976  
50977			}
50978  
50979			if ( this.running ) {
50980  
50981				var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
50982  
50983				diff = ( newTime - this.oldTime ) / 1000;
50984				this.oldTime = newTime;
50985  
50986				this.elapsedTime += diff;
50987  
50988			}
50989  
50990			return diff;
50991  
50992		}
50993  
50994	} );
50995  
50996	/**
50997	 * @author bhouston / http://clara.io
50998	 * @author WestLangley / http://github.com/WestLangley
50999	 *
51000	 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
51001	 *
51002	 * The poles (phi) are at the positive and negative y axis.
51003	 * The equator starts at positive z.
51004	 */
51005  
51006	function Spherical( radius, phi, theta ) {
51007  
51008		this.radius = ( radius !== undefined ) ? radius : 1.0;
51009		this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole
51010		this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere
51011  
51012		return this;
51013  
51014	}
51015  
51016	Object.assign( Spherical.prototype, {
51017  
vendor: 1,528 bytes, lines 51018-51094
51018		set: function ( radius, phi, theta ) {
51019  
51020			this.radius = radius;
51021			this.phi = phi;
51022			this.theta = theta;
51023  
51024			return this;
51025  
51026		},
51027  
51028		clone: function () {
51029  
51030			return new this.constructor().copy( this );
51031  
51032		},
51033  
51034		copy: function ( other ) {
51035  
51036			this.radius = other.radius;
51037			this.phi = other.phi;
51038			this.theta = other.theta;
51039  
51040			return this;
51041  
51042		},
51043  
51044		// restrict phi to be betwee EPS and PI-EPS
51045		makeSafe: function () {
51046  
51047			var EPS = 0.000001;
51048			this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
51049  
51050			return this;
51051  
51052		},
51053  
51054		setFromVector3: function ( vec3 ) {
51055  
51056			this.radius = vec3.length();
51057  
51058			if ( this.radius === 0 ) {
51059  
51060				this.theta = 0;
51061				this.phi = 0;
51062  
51063			} else {
51064  
51065				this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis
51066				this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle
51067  
51068			}
51069  
51070			return this;
51071  
51072		}
51073  
51074	} );
51075  
51076	/**
51077	 * @author Mugen87 / https://github.com/Mugen87
51078	 *
51079	 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
51080	 *
51081	 */
51082  
51083	function Cylindrical( radius, theta, y ) {
51084  
51085		this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
51086		this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
51087		this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
51088  
51089		return this;
51090  
51091	}
51092  
51093	Object.assign( Cylindrical.prototype, {
51094  
vendor: 4,357 bytes, lines 51095-51324
51095		set: function ( radius, theta, y ) {
51096  
51097			this.radius = radius;
51098			this.theta = theta;
51099			this.y = y;
51100  
51101			return this;
51102  
51103		},
51104  
51105		clone: function () {
51106  
51107			return new this.constructor().copy( this );
51108  
51109		},
51110  
51111		copy: function ( other ) {
51112  
51113			this.radius = other.radius;
51114			this.theta = other.theta;
51115			this.y = other.y;
51116  
51117			return this;
51118  
51119		},
51120  
51121		setFromVector3: function ( vec3 ) {
51122  
51123			this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z );
51124			this.theta = Math.atan2( vec3.x, vec3.z );
51125			this.y = vec3.y;
51126  
51127			return this;
51128  
51129		}
51130  
51131	} );
51132  
51133	/**
51134	 * @author bhouston / http://clara.io
51135	 */
51136  
51137	function Box2( min, max ) {
51138  
51139		this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
51140		this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
51141  
51142	}
51143  
51144	Object.assign( Box2.prototype, {
51145  
51146		set: function ( min, max ) {
51147  
51148			this.min.copy( min );
51149			this.max.copy( max );
51150  
51151			return this;
51152  
51153		},
51154  
51155		setFromPoints: function ( points ) {
51156  
51157			this.makeEmpty();
51158  
51159			for ( var i = 0, il = points.length; i < il; i ++ ) {
51160  
51161				this.expandByPoint( points[ i ] );
51162  
51163			}
51164  
51165			return this;
51166  
51167		},
51168  
51169		setFromCenterAndSize: function () {
51170  
51171			var v1 = new Vector2();
51172  
51173			return function setFromCenterAndSize( center, size ) {
51174  
51175				var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
51176				this.min.copy( center ).sub( halfSize );
51177				this.max.copy( center ).add( halfSize );
51178  
51179				return this;
51180  
51181			};
51182  
51183		}(),
51184  
51185		clone: function () {
51186  
51187			return new this.constructor().copy( this );
51188  
51189		},
51190  
51191		copy: function ( box ) {
51192  
51193			this.min.copy( box.min );
51194			this.max.copy( box.max );
51195  
51196			return this;
51197  
51198		},
51199  
51200		makeEmpty: function () {
51201  
51202			this.min.x = this.min.y = + Infinity;
51203			this.max.x = this.max.y = - Infinity;
51204  
51205			return this;
51206  
51207		},
51208  
51209		isEmpty: function () {
51210  
51211			// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
51212  
51213			return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
51214  
51215		},
51216  
51217		getCenter: function ( target ) {
51218  
51219			if ( target === undefined ) {
51220  
51221				console.warn( 'THREE.Box2: .getCenter() target is now required' );
51222				target = new Vector2();
51223  
51224			}
51225  
51226			return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
51227  
51228		},
51229  
51230		getSize: function ( target ) {
51231  
51232			if ( target === undefined ) {
51233  
51234				console.warn( 'THREE.Box2: .getSize() target is now required' );
51235				target = new Vector2();
51236  
51237			}
51238  
51239			return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
51240  
51241		},
51242  
51243		expandByPoint: function ( point ) {
51244  
51245			this.min.min( point );
51246			this.max.max( point );
51247  
51248			return this;
51249  
51250		},
51251  
51252		expandByVector: function ( vector ) {
51253  
51254			this.min.sub( vector );
51255			this.max.add( vector );
51256  
51257			return this;
51258  
51259		},
51260  
51261		expandByScalar: function ( scalar ) {
51262  
51263			this.min.addScalar( - scalar );
51264			this.max.addScalar( scalar );
51265  
51266			return this;
51267  
51268		},
51269  
51270		containsPoint: function ( point ) {
51271  
51272			return point.x < this.min.x || point.x > this.max.x ||
51273				point.y < this.min.y || point.y > this.max.y ? false : true;
51274  
51275		},
51276  
51277		containsBox: function ( box ) {
51278  
51279			return this.min.x <= box.min.x && box.max.x <= this.max.x &&
51280				this.min.y <= box.min.y && box.max.y <= this.max.y;
51281  
51282		},
51283  
51284		getParameter: function ( point, target ) {
51285  
51286			// This can potentially have a divide by zero if the box
51287			// has a size dimension of 0.
51288  
51289			if ( target === undefined ) {
51290  
51291				console.warn( 'THREE.Box2: .getParameter() target is now required' );
51292				target = new Vector2();
51293  
51294			}
51295  
51296			return target.set(
51297				( point.x - this.min.x ) / ( this.max.x - this.min.x ),
51298				( point.y - this.min.y ) / ( this.max.y - this.min.y )
51299			);
51300  
51301		},
51302  
51303		intersectsBox: function ( box ) {
51304  
51305			// using 4 splitting planes to rule out intersections
51306  
51307			return box.max.x < this.min.x || box.min.x > this.max.x ||
51308				box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
51309  
51310		},
51311  
51312		clampPoint: function ( point, target ) {
51313  
51314			if ( target === undefined ) {
51315  
51316				console.warn( 'THREE.Box2: .clampPoint() target is now required' );
51317				target = new Vector2();
51318  
51319			}
51320  
51321			return target.copy( point ).clamp( this.min, this.max );
51322  
51323		},
51324  
51325		distanceToPoint: function () {
51326  
51327			var v1 = new Vector2();
51328  
51329			return function distanceToPoint( point ) {
51330  
51331				var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
51332				return clampedPoint.sub( point ).length();
51333  
51334			};
51335  
51336		}(),
51337  
51338		intersect: function ( box ) {
51339  
51340			this.min.max( box.min );
51341			this.max.min( box.max );
51342  
51343			return this;
51344  
51345		},
51346  
51347		union: function ( box ) {
51348  
51349			this.min.min( box.min );
51350			this.max.max( box.max );
51351  
51352			return this;
51353  
51354		},
51355  
51356		translate: function ( offset ) {
51357  
51358			this.min.add( offset );
51359			this.max.add( offset );
51360  
51361			return this;
51362  
51363		},
51364  
51365		equals: function ( box ) {
51366  
51367			return box.min.equals( this.min ) && box.max.equals( this.max );
51368  
51369		}
51370  
51371	} );
51372  
51373	/**
51374	 * @author alteredq / http://alteredqualia.com/
51375	 */
51376  
51377	function ImmediateRenderObject( material ) {
51378  
51379		Object3D.call( this );
51380  
51381		this.material = material;
51382		this.render = function ( /* renderCallback */ ) {};
51383  
51384	}
51385  
51386	ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
51387	ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
51388  
51389	ImmediateRenderObject.prototype.isImmediateRenderObject = true;
51390  
51391	/**
51392	 * @author mrdoob / http://mrdoob.com/
51393	 * @author WestLangley / http://github.com/WestLangley
51394	 */
51395  
51396	function VertexNormalsHelper( object, size, hex, linewidth ) {
51397  
51398		this.object = object;
51399  
51400		this.size = ( size !== undefined ) ? size : 1;
51401  
51402		var color = ( hex !== undefined ) ? hex : 0xff0000;
51403  
51404		var width = ( linewidth !== undefined ) ? linewidth : 1;
51405  
51406		//
51407  
51408		var nNormals = 0;
51409  
51410		var objGeometry = this.object.geometry;
51411  
51412		if ( objGeometry && objGeometry.isGeometry ) {
51413  
51414			nNormals = objGeometry.faces.length * 3;
51415  
51416		} else if ( objGeometry && objGeometry.isBufferGeometry ) {
51417  
51418			nNormals = objGeometry.attributes.normal.count;
51419  
51420		}
51421  
51422		//
51423  
51424		var geometry = new BufferGeometry();
51425  
51426		var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
51427  
51428		geometry.addAttribute( 'position', positions );
51429  
51430		LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
51431  
51432		//
51433  
51434		this.matrixAutoUpdate = false;
51435  
51436		this.update();
51437  
51438	}
51439  
51440	VertexNormalsHelper.prototype = Object.create( LineSegments.prototype );
51441	VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
51442  
51443	VertexNormalsHelper.prototype.update = ( function () {
51444  
51445		var v1 = new Vector3();
51446		var v2 = new Vector3();
51447		var normalMatrix = new Matrix3();
51448  
51449		return function update() {
51450  
51451			var keys = [ 'a', 'b', 'c' ];
51452  
51453			this.object.updateMatrixWorld( true );
51454  
51455			normalMatrix.getNormalMatrix( this.object.matrixWorld );
51456  
51457			var matrixWorld = this.object.matrixWorld;
51458  
51459			var position = this.geometry.attributes.position;
51460  
51461			//
51462  
51463			var objGeometry = this.object.geometry;
51464  
51465			if ( objGeometry && objGeometry.isGeometry ) {
51466  
51467				var vertices = objGeometry.vertices;
51468  
51469				var faces = objGeometry.faces;
51470  
51471				var idx = 0;
51472  
51473				for ( var i = 0, l = faces.length; i < l; i ++ ) {
51474  
51475					var face = faces[ i ];
51476  
51477					for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
51478  
51479						var vertex = vertices[ face[ keys[ j ] ] ];
51480  
51481						var normal = face.vertexNormals[ j ];
51482  
51483						v1.copy( vertex ).applyMatrix4( matrixWorld );
51484  
51485						v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
51486  
51487						position.setXYZ( idx, v1.x, v1.y, v1.z );
51488  
51489						idx = idx + 1;
51490  
51491						position.setXYZ( idx, v2.x, v2.y, v2.z );
51492  
51493						idx = idx + 1;
51494  
51495					}
51496  
51497				}
51498  
51499			} else if ( objGeometry && objGeometry.isBufferGeometry ) {
51500  
51501				var objPos = objGeometry.attributes.position;
51502  
51503				var objNorm = objGeometry.attributes.normal;
51504  
51505				var idx = 0;
51506  
51507				// for simplicity, ignore index and drawcalls, and render every normal
51508  
51509				for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
51510  
51511					v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
51512  
51513					v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
51514  
51515					v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
51516  
51517					position.setXYZ( idx, v1.x, v1.y, v1.z );
51518  
51519					idx = idx + 1;
51520  
51521					position.setXYZ( idx, v2.x, v2.y, v2.z );
51522  
51523					idx = idx + 1;
51524  
51525				}
51526  
51527			}
51528  
51529			position.needsUpdate = true;
51530  
51531		};
51532  
51533	}() );
51534  
51535	/**
51536	 * @author alteredq / http://alteredqualia.com/
51537	 * @author mrdoob / http://mrdoob.com/
51538	 * @author WestLangley / http://github.com/WestLangley
51539	 */
51540  
51541	function SpotLightHelper( light, color ) {
51542  
51543		Object3D.call( this );
51544  
51545		this.light = light;
51546		this.light.updateMatrixWorld();
51547  
51548		this.matrix = light.matrixWorld;
51549		this.matrixAutoUpdate = false;
vendor: 5,008 bytes, lines 51550-51764
51550  
51551		this.color = color;
51552  
51553		var geometry = new BufferGeometry();
51554  
51555		var positions = [
51556			0, 0, 0, 	0, 0, 1,
51557			0, 0, 0, 	1, 0, 1,
51558			0, 0, 0,	- 1, 0, 1,
51559			0, 0, 0, 	0, 1, 1,
51560			0, 0, 0, 	0, - 1, 1
51561		];
51562  
51563		for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
51564  
51565			var p1 = ( i / l ) * Math.PI * 2;
51566			var p2 = ( j / l ) * Math.PI * 2;
51567  
51568			positions.push(
51569				Math.cos( p1 ), Math.sin( p1 ), 1,
51570				Math.cos( p2 ), Math.sin( p2 ), 1
51571			);
51572  
51573		}
51574  
51575		geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
51576  
51577		var material = new LineBasicMaterial( { fog: false } );
51578  
51579		this.cone = new LineSegments( geometry, material );
51580		this.add( this.cone );
51581  
51582		this.update();
51583  
51584	}
51585  
51586	SpotLightHelper.prototype = Object.create( Object3D.prototype );
51587	SpotLightHelper.prototype.constructor = SpotLightHelper;
51588  
51589	SpotLightHelper.prototype.dispose = function () {
51590  
51591		this.cone.geometry.dispose();
51592		this.cone.material.dispose();
51593  
51594	};
51595  
51596	SpotLightHelper.prototype.update = function () {
51597  
51598		var vector = new Vector3();
51599		var vector2 = new Vector3();
51600  
51601		return function update() {
51602  
51603			this.light.updateMatrixWorld();
51604  
51605			var coneLength = this.light.distance ? this.light.distance : 1000;
51606			var coneWidth = coneLength * Math.tan( this.light.angle );
51607  
51608			this.cone.scale.set( coneWidth, coneWidth, coneLength );
51609  
51610			vector.setFromMatrixPosition( this.light.matrixWorld );
51611			vector2.setFromMatrixPosition( this.light.target.matrixWorld );
51612  
51613			this.cone.lookAt( vector2.sub( vector ) );
51614  
51615			if ( this.color !== undefined ) {
51616  
51617				this.cone.material.color.set( this.color );
51618  
51619			} else {
51620  
51621				this.cone.material.color.copy( this.light.color );
51622  
51623			}
51624  
51625		};
51626  
51627	}();
51628  
51629	/**
51630	 * @author Sean Griffin / http://twitter.com/sgrif
51631	 * @author Michael Guerrero / http://realitymeltdown.com
51632	 * @author mrdoob / http://mrdoob.com/
51633	 * @author ikerr / http://verold.com
51634	 * @author Mugen87 / https://github.com/Mugen87
51635	 */
51636  
51637	function getBoneList( object ) {
51638  
51639		var boneList = [];
51640  
51641		if ( object && object.isBone ) {
51642  
51643			boneList.push( object );
51644  
51645		}
51646  
51647		for ( var i = 0; i < object.children.length; i ++ ) {
51648  
51649			boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
51650  
51651		}
51652  
51653		return boneList;
51654  
51655	}
51656  
51657	function SkeletonHelper( object ) {
51658  
51659		var bones = getBoneList( object );
51660  
51661		var geometry = new BufferGeometry();
51662  
51663		var vertices = [];
51664		var colors = [];
51665  
51666		var color1 = new Color( 0, 0, 1 );
51667		var color2 = new Color( 0, 1, 0 );
51668  
51669		for ( var i = 0; i < bones.length; i ++ ) {
51670  
51671			var bone = bones[ i ];
51672  
51673			if ( bone.parent && bone.parent.isBone ) {
51674  
51675				vertices.push( 0, 0, 0 );
51676				vertices.push( 0, 0, 0 );
51677				colors.push( color1.r, color1.g, color1.b );
51678				colors.push( color2.r, color2.g, color2.b );
51679  
51680			}
51681  
51682		}
51683  
51684		geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51685		geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51686  
51687		var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );
51688  
51689		LineSegments.call( this, geometry, material );
51690  
51691		this.root = object;
51692		this.bones = bones;
51693  
51694		this.matrix = object.matrixWorld;
51695		this.matrixAutoUpdate = false;
51696  
51697	}
51698  
51699	SkeletonHelper.prototype = Object.create( LineSegments.prototype );
51700	SkeletonHelper.prototype.constructor = SkeletonHelper;
51701  
51702	SkeletonHelper.prototype.updateMatrixWorld = function () {
51703  
51704		var vector = new Vector3();
51705  
51706		var boneMatrix = new Matrix4();
51707		var matrixWorldInv = new Matrix4();
51708  
51709		return function updateMatrixWorld( force ) {
51710  
51711			var bones = this.bones;
51712  
51713			var geometry = this.geometry;
51714			var position = geometry.getAttribute( 'position' );
51715  
51716			matrixWorldInv.getInverse( this.root.matrixWorld );
51717  
51718			for ( var i = 0, j = 0; i < bones.length; i ++ ) {
51719  
51720				var bone = bones[ i ];
51721  
51722				if ( bone.parent && bone.parent.isBone ) {
51723  
51724					boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
51725					vector.setFromMatrixPosition( boneMatrix );
51726					position.setXYZ( j, vector.x, vector.y, vector.z );
51727  
51728					boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
51729					vector.setFromMatrixPosition( boneMatrix );
51730					position.setXYZ( j + 1, vector.x, vector.y, vector.z );
51731  
51732					j += 2;
51733  
51734				}
51735  
51736			}
51737  
51738			geometry.getAttribute( 'position' ).needsUpdate = true;
51739  
51740			Object3D.prototype.updateMatrixWorld.call( this, force );
51741  
51742		};
51743  
51744	}();
51745  
51746	/**
51747	 * @author alteredq / http://alteredqualia.com/
51748	 * @author mrdoob / http://mrdoob.com/
51749	 */
51750  
51751	function PointLightHelper( light, sphereSize, color ) {
51752  
51753		this.light = light;
51754		this.light.updateMatrixWorld();
51755  
51756		this.color = color;
51757  
51758		var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
51759		var material = new MeshBasicMaterial( { wireframe: true, fog: false } );
51760  
51761		Mesh.call( this, geometry, material );
51762  
51763		this.matrix = this.light.matrixWorld;
51764		this.matrixAutoUpdate = false;
51765  
51766		this.update();
51767  
51768  
51769		/*
51770		var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
51771		var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
51772  
51773		this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
51774		this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
51775  
51776		var d = light.distance;
51777  
51778		if ( d === 0.0 ) {
51779  
51780			this.lightDistance.visible = false;
51781  
51782		} else {
51783  
51784			this.lightDistance.scale.set( d, d, d );
51785  
51786		}
51787  
51788		this.add( this.lightDistance );
51789		*/
51790  
51791	}
51792  
51793	PointLightHelper.prototype = Object.create( Mesh.prototype );
51794	PointLightHelper.prototype.constructor = PointLightHelper;
51795  
51796	PointLightHelper.prototype.dispose = function () {
51797  
51798		this.geometry.dispose();
51799		this.material.dispose();
51800  
51801	};
51802  
51803	PointLightHelper.prototype.update = function () {
51804  
51805		if ( this.color !== undefined ) {
51806  
51807			this.material.color.set( this.color );
51808  
51809		} else {
51810  
51811			this.material.color.copy( this.light.color );
51812  
51813		}
51814  
51815		/*
51816		var d = this.light.distance;
51817  
51818		if ( d === 0.0 ) {
51819  
51820			this.lightDistance.visible = false;
51821  
51822		} else {
51823  
51824			this.lightDistance.visible = true;
51825			this.lightDistance.scale.set( d, d, d );
51826  
51827		}
51828		*/
51829  
51830	};
51831  
51832	/**
51833	 * @author abelnation / http://github.com/abelnation
51834	 * @author Mugen87 / http://github.com/Mugen87
51835	 * @author WestLangley / http://github.com/WestLangley
51836	 */
51837  
51838	function RectAreaLightHelper( light, color ) {
51839  
51840		Object3D.call( this );
51841  
51842		this.light = light;
51843		this.light.updateMatrixWorld();
51844  
51845		this.matrix = light.matrixWorld;
51846		this.matrixAutoUpdate = false;
51847  
51848		this.color = color;
51849  
51850		var material = new LineBasicMaterial( { fog: false } );
51851  
51852		var geometry = new BufferGeometry();
51853  
51854		geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) );
51855  
51856		this.line = new Line( geometry, material );
51857		this.add( this.line );
51858  
51859  
51860		this.update();
51861  
51862	}
51863  
51864	RectAreaLightHelper.prototype = Object.create( Object3D.prototype );
51865	RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
51866  
51867	RectAreaLightHelper.prototype.dispose = function () {
51868  
51869		this.children[ 0 ].geometry.dispose();
51870		this.children[ 0 ].material.dispose();
51871  
51872	};
51873  
51874	RectAreaLightHelper.prototype.update = function () {
51875  
51876		// calculate new dimensions of the helper
51877  
51878		var hx = this.light.width * 0.5;
51879		var hy = this.light.height * 0.5;
51880  
51881		var position = this.line.geometry.attributes.position;
51882		var array = position.array;
51883  
51884		// update vertices
51885  
51886		array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0;
51887		array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0;
51888		array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0;
51889		array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0;
51890		array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0;
51891  
51892		position.needsUpdate = true;
51893  
51894		if ( this.color !== undefined ) {
51895  
51896			this.line.material.color.set( this.color );
51897  
51898		} else {
51899  
51900			this.line.material.color.copy( this.light.color );
51901  
51902		}
51903  
51904	};
51905  
51906	/**
51907	 * @author alteredq / http://alteredqualia.com/
51908	 * @author mrdoob / http://mrdoob.com/
51909	 * @author Mugen87 / https://github.com/Mugen87
51910	 */
51911  
51912	function HemisphereLightHelper( light, size, color ) {
51913  
51914		Object3D.call( this );
51915  
51916		this.light = light;
51917		this.light.updateMatrixWorld();
51918  
51919		this.matrix = light.matrixWorld;
51920		this.matrixAutoUpdate = false;
51921  
51922		this.color = color;
51923  
51924		var geometry = new OctahedronBufferGeometry( size );
51925		geometry.rotateY( Math.PI * 0.5 );
51926  
51927		this.material = new MeshBasicMaterial( { wireframe: true, fog: false } );
51928		if ( this.color === undefined ) this.material.vertexColors = VertexColors;
51929  
51930		var position = geometry.getAttribute( 'position' );
51931		var colors = new Float32Array( position.count * 3 );
51932  
51933		geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
51934  
51935		this.add( new Mesh( geometry, this.material ) );
51936  
51937		this.update();
51938  
51939	}
51940  
51941	HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
51942	HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
51943  
51944	HemisphereLightHelper.prototype.dispose = function () {
51945  
51946		this.children[ 0 ].geometry.dispose();
51947		this.children[ 0 ].material.dispose();
51948  
51949	};
51950  
51951	HemisphereLightHelper.prototype.update = function () {
51952  
51953		var vector = new Vector3();
51954  
51955		var color1 = new Color();
51956		var color2 = new Color();
51957  
vendor: 4,151 bytes, lines 51958-52128
51958		return function update() {
51959  
51960			var mesh = this.children[ 0 ];
51961  
51962			if ( this.color !== undefined ) {
51963  
51964				this.material.color.set( this.color );
51965  
51966			} else {
51967  
51968				var colors = mesh.geometry.getAttribute( 'color' );
51969  
51970				color1.copy( this.light.color );
51971				color2.copy( this.light.groundColor );
51972  
51973				for ( var i = 0, l = colors.count; i < l; i ++ ) {
51974  
51975					var color = ( i < ( l / 2 ) ) ? color1 : color2;
51976  
51977					colors.setXYZ( i, color.r, color.g, color.b );
51978  
51979				}
51980  
51981				colors.needsUpdate = true;
51982  
51983			}
51984  
51985			mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
51986  
51987		};
51988  
51989	}();
51990  
51991	/**
51992	 * @author mrdoob / http://mrdoob.com/
51993	 */
51994  
51995	function GridHelper( size, divisions, color1, color2 ) {
51996  
51997		size = size || 10;
51998		divisions = divisions || 10;
51999		color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
52000		color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
52001  
52002		var center = divisions / 2;
52003		var step = size / divisions;
52004		var halfSize = size / 2;
52005  
52006		var vertices = [], colors = [];
52007  
52008		for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
52009  
52010			vertices.push( - halfSize, 0, k, halfSize, 0, k );
52011			vertices.push( k, 0, - halfSize, k, 0, halfSize );
52012  
52013			var color = i === center ? color1 : color2;
52014  
52015			color.toArray( colors, j ); j += 3;
52016			color.toArray( colors, j ); j += 3;
52017			color.toArray( colors, j ); j += 3;
52018			color.toArray( colors, j ); j += 3;
52019  
52020		}
52021  
52022		var geometry = new BufferGeometry();
52023		geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52024		geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52025  
52026		var material = new LineBasicMaterial( { vertexColors: VertexColors } );
52027  
52028		LineSegments.call( this, geometry, material );
52029  
52030	}
52031  
52032	GridHelper.prototype = Object.create( LineSegments.prototype );
52033	GridHelper.prototype.constructor = GridHelper;
52034  
52035	/**
52036	 * @author mrdoob / http://mrdoob.com/
52037	 * @author Mugen87 / http://github.com/Mugen87
52038	 * @author Hectate / http://www.github.com/Hectate
52039	 */
52040  
52041	function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
52042  
52043		radius = radius || 10;
52044		radials = radials || 16;
52045		circles = circles || 8;
52046		divisions = divisions || 64;
52047		color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
52048		color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
52049  
52050		var vertices = [];
52051		var colors = [];
52052  
52053		var x, z;
52054		var v, i, j, r, color;
52055  
52056		// create the radials
52057  
52058		for ( i = 0; i <= radials; i ++ ) {
52059  
52060			v = ( i / radials ) * ( Math.PI * 2 );
52061  
52062			x = Math.sin( v ) * radius;
52063			z = Math.cos( v ) * radius;
52064  
52065			vertices.push( 0, 0, 0 );
52066			vertices.push( x, 0, z );
52067  
52068			color = ( i & 1 ) ? color1 : color2;
52069  
52070			colors.push( color.r, color.g, color.b );
52071			colors.push( color.r, color.g, color.b );
52072  
52073		}
52074  
52075		// create the circles
52076  
52077		for ( i = 0; i <= circles; i ++ ) {
52078  
52079			color = ( i & 1 ) ? color1 : color2;
52080  
52081			r = radius - ( radius / circles * i );
52082  
52083			for ( j = 0; j < divisions; j ++ ) {
52084  
52085				// first vertex
52086  
52087				v = ( j / divisions ) * ( Math.PI * 2 );
52088  
52089				x = Math.sin( v ) * r;
52090				z = Math.cos( v ) * r;
52091  
52092				vertices.push( x, 0, z );
52093				colors.push( color.r, color.g, color.b );
52094  
52095				// second vertex
52096  
52097				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
52098  
52099				x = Math.sin( v ) * r;
52100				z = Math.cos( v ) * r;
52101  
52102				vertices.push( x, 0, z );
52103				colors.push( color.r, color.g, color.b );
52104  
52105			}
52106  
52107		}
52108  
52109		var geometry = new BufferGeometry();
52110		geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52111		geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52112  
52113		var material = new LineBasicMaterial( { vertexColors: VertexColors } );
52114  
52115		LineSegments.call( this, geometry, material );
52116  
52117	}
52118  
52119	PolarGridHelper.prototype = Object.create( LineSegments.prototype );
52120	PolarGridHelper.prototype.constructor = PolarGridHelper;
52121  
52122	/**
52123	 * @author mrdoob / http://mrdoob.com/
52124	 * @author WestLangley / http://github.com/WestLangley
52125	 */
52126  
52127	function FaceNormalsHelper( object, size, hex, linewidth ) {
52128  
52129		// FaceNormalsHelper only supports THREE.Geometry
52130  
52131		this.object = object;
52132  
52133		this.size = ( size !== undefined ) ? size : 1;
52134  
52135		var color = ( hex !== undefined ) ? hex : 0xffff00;
52136  
52137		var width = ( linewidth !== undefined ) ? linewidth : 1;
52138  
52139		//
52140  
52141		var nNormals = 0;
52142  
52143		var objGeometry = this.object.geometry;
52144  
52145		if ( objGeometry && objGeometry.isGeometry ) {
52146  
52147			nNormals = objGeometry.faces.length;
52148  
52149		} else {
52150  
52151			console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
52152  
52153		}
52154  
52155		//
52156  
52157		var geometry = new BufferGeometry();
52158  
52159		var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
52160  
52161		geometry.addAttribute( 'position', positions );
52162  
52163		LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
52164  
52165		//
52166  
52167		this.matrixAutoUpdate = false;
52168		this.update();
52169  
52170	}
52171  
52172	FaceNormalsHelper.prototype = Object.create( LineSegments.prototype );
52173	FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
52174  
52175	FaceNormalsHelper.prototype.update = ( function () {
52176  
52177		var v1 = new Vector3();
52178		var v2 = new Vector3();
52179		var normalMatrix = new Matrix3();
52180  
52181		return function update() {
52182  
52183			this.object.updateMatrixWorld( true );
52184  
52185			normalMatrix.getNormalMatrix( this.object.matrixWorld );
52186  
52187			var matrixWorld = this.object.matrixWorld;
52188  
52189			var position = this.geometry.attributes.position;
52190  
52191			//
52192  
52193			var objGeometry = this.object.geometry;
52194  
52195			var vertices = objGeometry.vertices;
52196  
52197			var faces = objGeometry.faces;
52198  
52199			var idx = 0;
52200  
52201			for ( var i = 0, l = faces.length; i < l; i ++ ) {
52202  
52203				var face = faces[ i ];
52204  
52205				var normal = face.normal;
52206  
52207				v1.copy( vertices[ face.a ] )
52208					.add( vertices[ face.b ] )
52209					.add( vertices[ face.c ] )
52210					.divideScalar( 3 )
52211					.applyMatrix4( matrixWorld );
52212  
52213				v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
52214  
52215				position.setXYZ( idx, v1.x, v1.y, v1.z );
52216  
52217				idx = idx + 1;
52218  
52219				position.setXYZ( idx, v2.x, v2.y, v2.z );
52220  
52221				idx = idx + 1;
52222  
52223			}
52224  
52225			position.needsUpdate = true;
52226  
52227		};
52228  
52229	}() );
52230  
52231	/**
52232	 * @author alteredq / http://alteredqualia.com/
52233	 * @author mrdoob / http://mrdoob.com/
52234	 * @author WestLangley / http://github.com/WestLangley
52235	 */
52236  
52237	function DirectionalLightHelper( light, size, color ) {
52238  
52239		Object3D.call( this );
52240  
52241		this.light = light;
52242		this.light.updateMatrixWorld();
52243  
52244		this.matrix = light.matrixWorld;
52245		this.matrixAutoUpdate = false;
52246  
52247		this.color = color;
52248  
52249		if ( size === undefined ) size = 1;
52250  
52251		var geometry = new BufferGeometry();
52252		geometry.addAttribute( 'position', new Float32BufferAttribute( [
52253			- size, size, 0,
52254			size, size, 0,
52255			size, - size, 0,
52256			- size, - size, 0,
52257			- size, size, 0
52258		], 3 ) );
52259  
52260		var material = new LineBasicMaterial( { fog: false } );
52261  
52262		this.lightPlane = new Line( geometry, material );
52263		this.add( this.lightPlane );
52264  
52265		geometry = new BufferGeometry();
52266		geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
52267  
52268		this.targetLine = new Line( geometry, material );
52269		this.add( this.targetLine );
52270  
52271		this.update();
52272  
52273	}
52274  
52275	DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
52276	DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
52277  
52278	DirectionalLightHelper.prototype.dispose = function () {
52279  
52280		this.lightPlane.geometry.dispose();
52281		this.lightPlane.material.dispose();
52282		this.targetLine.geometry.dispose();
52283		this.targetLine.material.dispose();
52284  
52285	};
52286  
52287	DirectionalLightHelper.prototype.update = function () {
52288  
52289		var v1 = new Vector3();
52290		var v2 = new Vector3();
52291		var v3 = new Vector3();
52292  
52293		return function update() {
52294  
52295			v1.setFromMatrixPosition( this.light.matrixWorld );
52296			v2.setFromMatrixPosition( this.light.target.matrixWorld );
52297			v3.subVectors( v2, v1 );
52298  
52299			this.lightPlane.lookAt( v3 );
52300  
52301			if ( this.color !== undefined ) {
52302  
52303				this.lightPlane.material.color.set( this.color );
52304				this.targetLine.material.color.set( this.color );
52305  
52306			} else {
52307  
52308				this.lightPlane.material.color.copy( this.light.color );
52309				this.targetLine.material.color.copy( this.light.color );
52310  
52311			}
52312  
52313			this.targetLine.lookAt( v3 );
52314			this.targetLine.scale.z = v3.length();
52315  
52316		};
52317  
52318	}();
52319  
52320	/**
52321	 * @author alteredq / http://alteredqualia.com/
52322	 * @author Mugen87 / https://github.com/Mugen87
52323	 *
52324	 *	- shows frustum, line of sight and up of the camera
52325	 *	- suitable for fast updates
52326	 * 	- based on frustum visualization in lightgl.js shadowmap example
52327	 *		http://evanw.github.com/lightgl.js/tests/shadowmap.html
52328	 */
52329  
52330	function CameraHelper( camera ) {
52331  
52332		var geometry = new BufferGeometry();
52333		var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );
52334  
52335		var vertices = [];
52336		var colors = [];
52337  
52338		var pointMap = {};
52339  
52340		// colors
52341  
52342		var colorFrustum = new Color( 0xffaa00 );
52343		var colorCone = new Color( 0xff0000 );
52344		var colorUp = new Color( 0x00aaff );
52345		var colorTarget = new Color( 0xffffff );
52346		var colorCross = new Color( 0x333333 );
52347  
52348		// near
52349  
52350		addLine( 'n1', 'n2', colorFrustum );
52351		addLine( 'n2', 'n4', colorFrustum );
52352		addLine( 'n4', 'n3', colorFrustum );
52353		addLine( 'n3', 'n1', colorFrustum );
52354  
52355		// far
52356  
52357		addLine( 'f1', 'f2', colorFrustum );
52358		addLine( 'f2', 'f4', colorFrustum );
52359		addLine( 'f4', 'f3', colorFrustum );
52360		addLine( 'f3', 'f1', colorFrustum );
52361  
52362		// sides
52363  
52364		addLine( 'n1', 'f1', colorFrustum );
52365		addLine( 'n2', 'f2', colorFrustum );
52366		addLine( 'n3', 'f3', colorFrustum );
52367		addLine( 'n4', 'f4', colorFrustum );
52368  
52369		// cone
52370  
52371		addLine( 'p', 'n1', colorCone );
52372		addLine( 'p', 'n2', colorCone );
52373		addLine( 'p', 'n3', colorCone );
52374		addLine( 'p', 'n4', colorCone );
52375  
52376		// up
52377  
52378		addLine( 'u1', 'u2', colorUp );
52379		addLine( 'u2', 'u3', colorUp );
52380		addLine( 'u3', 'u1', colorUp );
52381  
52382		// target
52383  
52384		addLine( 'c', 't', colorTarget );
52385		addLine( 'p', 'c', colorCross );
52386  
52387		// cross
52388  
52389		addLine( 'cn1', 'cn2', colorCross );
52390		addLine( 'cn3', 'cn4', colorCross );
52391  
52392		addLine( 'cf1', 'cf2', colorCross );
52393		addLine( 'cf3', 'cf4', colorCross );
52394  
52395		function addLine( a, b, color ) {
52396  
52397			addPoint( a, color );
52398			addPoint( b, color );
52399  
52400		}
52401  
52402		function addPoint( id, color ) {
52403  
52404			vertices.push( 0, 0, 0 );
52405			colors.push( color.r, color.g, color.b );
52406  
52407			if ( pointMap[ id ] === undefined ) {
52408  
52409				pointMap[ id ] = [];
52410  
52411			}
52412  
52413			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
52414  
52415		}
52416  
52417		geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52418		geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52419  
52420		LineSegments.call( this, geometry, material );
52421  
52422		this.camera = camera;
52423		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
52424  
52425		this.matrix = camera.matrixWorld;
52426		this.matrixAutoUpdate = false;
52427  
52428		this.pointMap = pointMap;
52429  
52430		this.update();
52431  
52432	}
52433  
52434	CameraHelper.prototype = Object.create( LineSegments.prototype );
52435	CameraHelper.prototype.constructor = CameraHelper;
52436  
52437	CameraHelper.prototype.update = function () {
52438  
52439		var geometry, pointMap;
52440  
52441		var vector = new Vector3();
52442		var camera = new Camera();
52443  
52444		function setPoint( point, x, y, z ) {
52445  
52446			vector.set( x, y, z ).unproject( camera );
52447  
52448			var points = pointMap[ point ];
52449  
52450			if ( points !== undefined ) {
52451  
52452				var position = geometry.getAttribute( 'position' );
52453  
52454				for ( var i = 0, l = points.length; i < l; i ++ ) {
52455  
52456					position.setXYZ( points[ i ], vector.x, vector.y, vector.z );
52457  
52458				}
52459  
52460			}
52461  
52462		}
52463  
52464		return function update() {
52465  
52466			geometry = this.geometry;
52467			pointMap = this.pointMap;
52468  
52469			var w = 1, h = 1;
52470  
52471			// we need just camera projection matrix
52472			// world matrix must be identity
52473  
52474			camera.projectionMatrix.copy( this.camera.projectionMatrix );
52475  
52476			// center / target
52477  
52478			setPoint( 'c', 0, 0, - 1 );
52479			setPoint( 't', 0, 0, 1 );
52480  
52481			// near
52482  
52483			setPoint( 'n1', - w, - h, - 1 );
52484			setPoint( 'n2', w, - h, - 1 );
52485			setPoint( 'n3', - w, h, - 1 );
52486			setPoint( 'n4', w, h, - 1 );
52487  
52488			// far
52489  
52490			setPoint( 'f1', - w, - h, 1 );
52491			setPoint( 'f2', w, - h, 1 );
52492			setPoint( 'f3', - w, h, 1 );
52493			setPoint( 'f4', w, h, 1 );
52494  
52495			// up
52496  
52497			setPoint( 'u1', w * 0.7, h * 1.1, - 1 );
52498			setPoint( 'u2', - w * 0.7, h * 1.1, - 1 );
52499			setPoint( 'u3', 0, h * 2, - 1 );
52500  
52501			// cross
52502  
52503			setPoint( 'cf1', - w, 0, 1 );
52504			setPoint( 'cf2', w, 0, 1 );
52505			setPoint( 'cf3', 0, - h, 1 );
52506			setPoint( 'cf4', 0, h, 1 );
52507  
52508			setPoint( 'cn1', - w, 0, - 1 );
52509			setPoint( 'cn2', w, 0, - 1 );
52510			setPoint( 'cn3', 0, - h, - 1 );
52511			setPoint( 'cn4', 0, h, - 1 );
52512  
52513			geometry.getAttribute( 'position' ).needsUpdate = true;
52514  
52515		};
52516  
52517	}();
52518  
52519	/**
52520	 * @author mrdoob / http://mrdoob.com/
52521	 * @author Mugen87 / http://github.com/Mugen87
52522	 */
52523  
52524	function BoxHelper( object, color ) {
52525  
52526		this.object = object;
52527  
52528		if ( color === undefined ) color = 0xffff00;
52529  
52530		var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
52531		var positions = new Float32Array( 8 * 3 );
52532  
52533		var geometry = new BufferGeometry();
52534		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52535		geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
52536  
52537		LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
52538  
52539		this.matrixAutoUpdate = false;
vendor: 5,749 bytes, lines 52540-52758
52540  
52541		this.update();
52542  
52543	}
52544  
52545	BoxHelper.prototype = Object.create( LineSegments.prototype );
52546	BoxHelper.prototype.constructor = BoxHelper;
52547  
52548	BoxHelper.prototype.update = ( function () {
52549  
52550		var box = new Box3();
52551  
52552		return function update( object ) {
52553  
52554			if ( object !== undefined ) {
52555  
52556				console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
52557  
52558			}
52559  
52560			if ( this.object !== undefined ) {
52561  
52562				box.setFromObject( this.object );
52563  
52564			}
52565  
52566			if ( box.isEmpty() ) return;
52567  
52568			var min = box.min;
52569			var max = box.max;
52570  
52571			/*
52572			  5____4
52573			1/___0/|
52574			| 6__|_7
52575			2/___3/
52576  
52577			0: max.x, max.y, max.z
52578			1: min.x, max.y, max.z
52579			2: min.x, min.y, max.z
52580			3: max.x, min.y, max.z
52581			4: max.x, max.y, min.z
52582			5: min.x, max.y, min.z
52583			6: min.x, min.y, min.z
52584			7: max.x, min.y, min.z
52585			*/
52586  
52587			var position = this.geometry.attributes.position;
52588			var array = position.array;
52589  
52590			array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
52591			array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
52592			array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
52593			array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
52594			array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
52595			array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
52596			array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
52597			array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
52598  
52599			position.needsUpdate = true;
52600  
52601			this.geometry.computeBoundingSphere();
52602  
52603		};
52604  
52605	} )();
52606  
52607	BoxHelper.prototype.setFromObject = function ( object ) {
52608  
52609		this.object = object;
52610		this.update();
52611  
52612		return this;
52613  
52614	};
52615  
52616	/**
52617	 * @author WestLangley / http://github.com/WestLangley
52618	 */
52619  
52620	function Box3Helper( box, hex ) {
52621  
52622		this.type = 'Box3Helper';
52623  
52624		this.box = box;
52625  
52626		var color = ( hex !== undefined ) ? hex : 0xffff00;
52627  
52628		var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
52629  
52630		var positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
52631  
52632		var geometry = new BufferGeometry();
52633  
52634		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52635  
52636		geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52637  
52638		LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
52639  
52640		this.geometry.computeBoundingSphere();
52641  
52642	}
52643  
52644	Box3Helper.prototype = Object.create( LineSegments.prototype );
52645	Box3Helper.prototype.constructor = Box3Helper;
52646  
52647	Box3Helper.prototype.updateMatrixWorld = function ( force ) {
52648  
52649		var box = this.box;
52650  
52651		if ( box.isEmpty() ) return;
52652  
52653		box.getCenter( this.position );
52654  
52655		box.getSize( this.scale );
52656  
52657		this.scale.multiplyScalar( 0.5 );
52658  
52659		Object3D.prototype.updateMatrixWorld.call( this, force );
52660  
52661	};
52662  
52663	/**
52664	 * @author WestLangley / http://github.com/WestLangley
52665	 */
52666  
52667	function PlaneHelper( plane, size, hex ) {
52668  
52669		this.type = 'PlaneHelper';
52670  
52671		this.plane = plane;
52672  
52673		this.size = ( size === undefined ) ? 1 : size;
52674  
52675		var color = ( hex !== undefined ) ? hex : 0xffff00;
52676  
52677		var positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ];
52678  
52679		var geometry = new BufferGeometry();
52680		geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52681		geometry.computeBoundingSphere();
52682  
52683		Line.call( this, geometry, new LineBasicMaterial( { color: color } ) );
52684  
52685		//
52686  
52687		var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
52688  
52689		var geometry2 = new BufferGeometry();
52690		geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
52691		geometry2.computeBoundingSphere();
52692  
52693		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );
52694  
52695	}
52696  
52697	PlaneHelper.prototype = Object.create( Line.prototype );
52698	PlaneHelper.prototype.constructor = PlaneHelper;
52699  
52700	PlaneHelper.prototype.updateMatrixWorld = function ( force ) {
52701  
52702		var scale = - this.plane.constant;
52703  
52704		if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
52705  
52706		this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
52707  
52708		this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
52709  
52710		this.lookAt( this.plane.normal );
52711  
52712		Object3D.prototype.updateMatrixWorld.call( this, force );
52713  
52714	};
52715  
52716	/**
52717	 * @author WestLangley / http://github.com/WestLangley
52718	 * @author zz85 / http://github.com/zz85
52719	 * @author bhouston / http://clara.io
52720	 *
52721	 * Creates an arrow for visualizing directions
52722	 *
52723	 * Parameters:
52724	 *  dir - Vector3
52725	 *  origin - Vector3
52726	 *  length - Number
52727	 *  color - color in hex value
52728	 *  headLength - Number
52729	 *  headWidth - Number
52730	 */
52731  
52732	var lineGeometry, coneGeometry;
52733  
52734	function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
52735  
52736		// dir is assumed to be normalized
52737  
52738		Object3D.call( this );
52739  
52740		if ( color === undefined ) color = 0xffff00;
52741		if ( length === undefined ) length = 1;
52742		if ( headLength === undefined ) headLength = 0.2 * length;
52743		if ( headWidth === undefined ) headWidth = 0.2 * headLength;
52744  
52745		if ( lineGeometry === undefined ) {
52746  
52747			lineGeometry = new BufferGeometry();
52748			lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
52749  
52750			coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
52751			coneGeometry.translate( 0, - 0.5, 0 );
52752  
52753		}
52754  
52755		this.position.copy( origin );
52756  
52757		this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );
52758		this.line.matrixAutoUpdate = false;
52759		this.add( this.line );
52760  
52761		this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );
52762		this.cone.matrixAutoUpdate = false;
52763		this.add( this.cone );
52764  
52765		this.setDirection( dir );
52766		this.setLength( length, headLength, headWidth );
52767  
52768	}
52769  
52770	ArrowHelper.prototype = Object.create( Object3D.prototype );
52771	ArrowHelper.prototype.constructor = ArrowHelper;
52772  
52773	ArrowHelper.prototype.setDirection = ( function () {
52774  
52775		var axis = new Vector3();
52776		var radians;
52777  
52778		return function setDirection( dir ) {
52779  
52780			// dir is assumed to be normalized
52781  
52782			if ( dir.y > 0.99999 ) {
52783  
52784				this.quaternion.set( 0, 0, 0, 1 );
52785  
52786			} else if ( dir.y < - 0.99999 ) {
52787  
52788				this.quaternion.set( 1, 0, 0, 0 );
52789  
52790			} else {
52791  
52792				axis.set( dir.z, 0, - dir.x ).normalize();
52793  
52794				radians = Math.acos( dir.y );
52795  
52796				this.quaternion.setFromAxisAngle( axis, radians );
52797  
52798			}
52799  
52800		};
52801  
52802	}() );
52803  
52804	ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
52805  
52806		if ( headLength === undefined ) headLength = 0.2 * length;
52807		if ( headWidth === undefined ) headWidth = 0.2 * headLength;
52808  
52809		this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
52810		this.line.updateMatrix();
52811  
52812		this.cone.scale.set( headWidth, headLength, headWidth );
52813		this.cone.position.y = length;
52814		this.cone.updateMatrix();
52815  
52816	};
52817  
52818	ArrowHelper.prototype.setColor = function ( color ) {
52819  
52820		this.line.material.color.copy( color );
52821		this.cone.material.color.copy( color );
52822  
52823	};
52824  
52825	/**
52826	 * @author sroucheray / http://sroucheray.org/
52827	 * @author mrdoob / http://mrdoob.com/
52828	 */
52829  
52830	function AxesHelper( size ) {
52831  
52832		size = size || 1;
52833  
52834		var vertices = [
52835			0, 0, 0,	size, 0, 0,
52836			0, 0, 0,	0, size, 0,
52837			0, 0, 0,	0, 0, size
52838		];
52839  
52840		var colors = [
52841			1, 0, 0,	1, 0.6, 0,
52842			0, 1, 0,	0.6, 1, 0,
52843			0, 0, 1,	0, 0.6, 1
52844		];
52845  
52846		var geometry = new BufferGeometry();
52847		geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52848		geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52849  
52850		var material = new LineBasicMaterial( { vertexColors: VertexColors } );
52851  
52852		LineSegments.call( this, geometry, material );
52853  
52854	}
52855  
52856	AxesHelper.prototype = Object.create( LineSegments.prototype );
52857	AxesHelper.prototype.constructor = AxesHelper;
52858  
52859	//
52860  
52861	Curve.create = function ( construct, getPoint ) {
52862  
52863		console.log( 'THREE.Curve.create() has been deprecated' );
52864  
52865		construct.prototype = Object.create( Curve.prototype );
52866		construct.prototype.constructor = construct;
52867		construct.prototype.getPoint = getPoint;
52868  
52869		return construct;
52870  
52871	};
52872  
52873	//
52874  
52875	Object.assign( CurvePath.prototype, {
52876  
52877		createPointsGeometry: function ( divisions ) {
52878  
52879			console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
52880  
52881			// generate geometry from path points (for Line or Points objects)
52882  
52883			var pts = this.getPoints( divisions );
52884			return this.createGeometry( pts );
52885  
52886		},
52887  
52888		createSpacedPointsGeometry: function ( divisions ) {
52889  
52890			console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
52891  
52892			// generate geometry from equidistant sampling along the path
52893  
52894			var pts = this.getSpacedPoints( divisions );
52895			return this.createGeometry( pts );
52896  
52897		},
52898  
52899		createGeometry: function ( points ) {
52900  
52901			console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
52902  
52903			var geometry = new Geometry();
52904  
52905			for ( var i = 0, l = points.length; i < l; i ++ ) {
52906  
52907				var point = points[ i ];
52908				geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
52909  
52910			}
52911  
52912			return geometry;
52913  
52914		}
52915  
52916	} );
52917  
52918	//
52919  
52920	Object.assign( Path.prototype, {
52921  
52922		fromPoints: function ( points ) {
52923  
52924			console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
52925			this.setFromPoints( points );
52926  
52927		}
52928  
52929	} );
52930  
52931	//
52932  
52933	function Spline( points ) {
52934  
52935		console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
52936  
52937		CatmullRomCurve3.call( this, points );
52938		this.type = 'catmullrom';
52939  
52940	}
52941  
52942	Spline.prototype = Object.create( CatmullRomCurve3.prototype );
52943  
52944	Object.assign( Spline.prototype, {
52945  
52946		initFromArray: function ( /* a */ ) {
52947  
52948			console.error( 'THREE.Spline: .initFromArray() has been removed.' );
52949  
52950		},
52951		getControlPointsArray: function ( /* optionalTarget */ ) {
52952  
52953			console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
52954  
52955		},
52956		reparametrizeByArcLength: function ( /* samplingCoef */ ) {
52957  
52958			console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
52959  
52960		}
52961  
52962	} );
52963  
52964	GridHelper.prototype.setColors = function () {
52965  
52966		console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
52967  
52968	};
52969  
52970	SkeletonHelper.prototype.update = function () {
52971  
52972		console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
52973  
52974	};
52975  
52976	//
52977  
52978	Object.assign( Loader.prototype, {
52979  
52980		extractUrlBase: function ( url ) {
52981  
52982			console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
52983			return LoaderUtils.extractUrlBase( url );
52984  
52985		}
52986  
52987	} );
52988  
52989	//
52990  
52991	Object.assign( Box2.prototype, {
52992  
52993		center: function ( optionalTarget ) {
52994  
52995			console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
52996			return this.getCenter( optionalTarget );
52997  
52998		},
52999		empty: function () {
53000  
53001			console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
53002			return this.isEmpty();
53003  
53004		},
53005		isIntersectionBox: function ( box ) {
53006  
53007			console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
53008			return this.intersectsBox( box );
53009  
53010		},
53011		size: function ( optionalTarget ) {
53012  
53013			console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
53014			return this.getSize( optionalTarget );
53015  
53016		}
53017	} );
53018  
53019	Object.assign( Box3.prototype, {
53020  
53021		center: function ( optionalTarget ) {
53022  
53023			console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
53024			return this.getCenter( optionalTarget );
53025  
53026		},
53027		empty: function () {
53028  
53029			console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
53030			return this.isEmpty();
53031  
53032		},
53033		isIntersectionBox: function ( box ) {
53034  
53035			console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
53036			return this.intersectsBox( box );
53037  
53038		},
53039		isIntersectionSphere: function ( sphere ) {
53040  
53041			console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
53042			return this.intersectsSphere( sphere );
53043  
53044		},
53045		size: function ( optionalTarget ) {
53046  
53047			console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
53048			return this.getSize( optionalTarget );
53049  
53050		}
53051	} );
53052  
53053	Line3.prototype.center = function ( optionalTarget ) {
53054  
53055		console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
53056		return this.getCenter( optionalTarget );
53057  
53058	};
53059  
53060	Object.assign( _Math, {
53061  
53062		random16: function () {
53063  
53064			console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
53065			return Math.random();
53066  
53067		},
53068  
53069		nearestPowerOfTwo: function ( value ) {
53070  
53071			console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
53072			return _Math.floorPowerOfTwo( value );
53073  
53074		},
53075  
53076		nextPowerOfTwo: function ( value ) {
53077  
53078			console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
53079			return _Math.ceilPowerOfTwo( value );
53080  
53081		}
53082  
53083	} );
53084  
53085	Object.assign( Matrix3.prototype, {
53086  
53087		flattenToArrayOffset: function ( array, offset ) {
53088  
53089			console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
53090			return this.toArray( array, offset );
53091  
53092		},
53093		multiplyVector3: function ( vector ) {
53094  
53095			console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
53096			return vector.applyMatrix3( this );
53097  
53098		},
53099		multiplyVector3Array: function ( /* a */ ) {
53100  
53101			console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
53102  
53103		},
53104		applyToBuffer: function ( buffer /*, offset, length */ ) {
53105  
53106			console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
53107			return this.applyToBufferAttribute( buffer );
53108  
53109		},
53110		applyToVector3Array: function ( /* array, offset, length */ ) {
53111  
53112			console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
53113  
53114		}
53115  
53116	} );
53117  
53118	Object.assign( Matrix4.prototype, {
53119  
53120		extractPosition: function ( m ) {
53121  
53122			console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
53123			return this.copyPosition( m );
53124  
53125		},
53126		flattenToArrayOffset: function ( array, offset ) {
53127  
53128			console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
53129			return this.toArray( array, offset );
53130  
53131		},
53132		getPosition: function () {
53133  
53134			var v1;
53135  
53136			return function getPosition() {
53137  
53138				if ( v1 === undefined ) v1 = new Vector3();
53139				console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
53140				return v1.setFromMatrixColumn( this, 3 );
53141  
53142			};
53143  
53144		}(),
53145		setRotationFromQuaternion: function ( q ) {
53146  
53147			console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
53148			return this.makeRotationFromQuaternion( q );
53149  
53150		},
53151		multiplyToArray: function () {
53152  
53153			console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
53154  
53155		},
53156		multiplyVector3: function ( vector ) {
53157  
53158			console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
53159			return vector.applyMatrix4( this );
53160  
53161		},
53162		multiplyVector4: function ( vector ) {
53163  
53164			console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
53165			return vector.applyMatrix4( this );
53166  
53167		},
53168		multiplyVector3Array: function ( /* a */ ) {
53169  
53170			console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
53171  
53172		},
53173		rotateAxis: function ( v ) {
53174  
53175			console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
53176			v.transformDirection( this );
53177  
53178		},
53179		crossVector: function ( vector ) {
53180  
53181			console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
53182			return vector.applyMatrix4( this );
53183  
53184		},
53185		translate: function () {
53186  
53187			console.error( 'THREE.Matrix4: .translate() has been removed.' );
53188  
53189		},
53190		rotateX: function () {
53191  
53192			console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
53193  
53194		},
53195		rotateY: function () {
53196  
53197			console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
53198  
53199		},
53200		rotateZ: function () {
53201  
53202			console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
53203  
53204		},
53205		rotateByAxis: function () {
53206  
53207			console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
53208  
53209		},
53210		applyToBuffer: function ( buffer /*, offset, length */ ) {
53211  
53212			console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
53213			return this.applyToBufferAttribute( buffer );
53214  
53215		},
53216		applyToVector3Array: function ( /* array, offset, length */ ) {
53217  
53218			console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
53219  
53220		},
53221		makeFrustum: function ( left, right, bottom, top, near, far ) {
53222  
53223			console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
53224			return this.makePerspective( left, right, top, bottom, near, far );
53225  
53226		}
53227  
53228	} );
53229  
53230	Plane.prototype.isIntersectionLine = function ( line ) {
53231  
53232		console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
53233		return this.intersectsLine( line );
53234  
53235	};
53236  
53237	Quaternion.prototype.multiplyVector3 = function ( vector ) {
53238  
53239		console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
53240		return vector.applyQuaternion( this );
53241  
53242	};
53243  
53244	Object.assign( Ray.prototype, {
53245  
53246		isIntersectionBox: function ( box ) {
53247  
53248			console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
53249			return this.intersectsBox( box );
53250  
53251		},
53252		isIntersectionPlane: function ( plane ) {
53253  
53254			console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
53255			return this.intersectsPlane( plane );
53256  
53257		},
53258		isIntersectionSphere: function ( sphere ) {
53259  
53260			console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
53261			return this.intersectsSphere( sphere );
53262  
53263		}
53264  
53265	} );
53266  
53267	Object.assign( Triangle.prototype, {
53268  
53269		area: function () {
53270  
53271			console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
53272			return this.getArea();
53273  
53274		},
53275		barycoordFromPoint: function ( point, target ) {
53276  
53277			console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
53278			return this.getBarycoord( point, target );
53279  
53280		},
53281		midpoint: function ( target ) {
53282  
53283			console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
53284			return this.getMidpoint( target );
53285  
53286		},
53287		normal: function ( target ) {
53288  
53289			console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
53290			return this.getNormal( target );
53291  
53292		},
53293		plane: function ( target ) {
53294  
53295			console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
53296			return this.getPlane( target );
53297  
53298		}
53299  
53300	} );
53301  
53302	Object.assign( Triangle, {
53303  
53304		barycoordFromPoint: function ( point, a, b, c, target ) {
53305  
53306			console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
53307			return Triangle.getBarycoord( point, a, b, c, target );
53308  
53309		},
53310		normal: function ( a, b, c, target ) {
53311  
53312			console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
53313			return Triangle.getNormal( a, b, c, target );
53314  
53315		}
53316  
53317	} );
53318  
53319	Object.assign( Shape.prototype, {
53320  
53321		extractAllPoints: function ( divisions ) {
53322  
53323			console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
53324			return this.extractPoints( divisions );
53325  
53326		},
53327		extrude: function ( options ) {
53328  
53329			console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
53330			return new ExtrudeGeometry( this, options );
53331  
53332		},
53333		makeGeometry: function ( options ) {
53334  
53335			console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
53336			return new ShapeGeometry( this, options );
53337  
53338		}
53339  
53340	} );
53341  
53342	Object.assign( Vector2.prototype, {
53343  
53344		fromAttribute: function ( attribute, index, offset ) {
53345  
53346			console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
53347			return this.fromBufferAttribute( attribute, index, offset );
53348  
53349		},
53350		distanceToManhattan: function ( v ) {
53351  
53352			console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
53353			return this.manhattanDistanceTo( v );
53354  
53355		},
53356		lengthManhattan: function () {
53357  
53358			console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
53359			return this.manhattanLength();
53360  
53361		}
53362  
53363	} );
53364  
53365	Object.assign( Vector3.prototype, {
53366  
53367		setEulerFromRotationMatrix: function () {
53368  
53369			console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
53370  
53371		},
53372		setEulerFromQuaternion: function () {
53373  
53374			console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
53375  
53376		},
53377		getPositionFromMatrix: function ( m ) {
53378  
53379			console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
53380			return this.setFromMatrixPosition( m );
53381  
53382		},
53383		getScaleFromMatrix: function ( m ) {
53384  
53385			console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
53386			return this.setFromMatrixScale( m );
53387  
53388		},
53389		getColumnFromMatrix: function ( index, matrix ) {
53390  
53391			console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
53392			return this.setFromMatrixColumn( matrix, index );
53393  
53394		},
53395		applyProjection: function ( m ) {
53396  
53397			console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
53398			return this.applyMatrix4( m );
53399  
53400		},
53401		fromAttribute: function ( attribute, index, offset ) {
53402  
53403			console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
53404			return this.fromBufferAttribute( attribute, index, offset );
53405  
53406		},
53407		distanceToManhattan: function ( v ) {
53408  
53409			console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
53410			return this.manhattanDistanceTo( v );
53411  
53412		},
53413		lengthManhattan: function () {
53414  
53415			console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
53416			return this.manhattanLength();
53417  
53418		}
53419  
53420	} );
53421  
53422	Object.assign( Vector4.prototype, {
53423  
53424		fromAttribute: function ( attribute, index, offset ) {
53425  
53426			console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
53427			return this.fromBufferAttribute( attribute, index, offset );
53428  
53429		},
53430		lengthManhattan: function () {
53431  
53432			console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
53433			return this.manhattanLength();
53434  
53435		}
53436  
53437	} );
53438  
53439	//
53440  
53441	Object.assign( Geometry.prototype, {
53442  
53443		computeTangents: function () {
53444  
53445			console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
53446  
53447		},
53448		computeLineDistances: function () {
53449  
53450			console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
53451  
53452		}
53453  
53454	} );
53455  
53456	Object.assign( Object3D.prototype, {
53457  
53458		getChildByName: function ( name ) {
53459  
53460			console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
53461			return this.getObjectByName( name );
53462  
53463		},
53464		renderDepth: function () {
53465  
53466			console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
53467  
53468		},
53469		translate: function ( distance, axis ) {
53470  
53471			console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
53472			return this.translateOnAxis( axis, distance );
53473  
53474		},
53475		getWorldRotation: function () {
53476  
53477			console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
53478  
53479		}
53480  
53481	} );
53482  
53483	Object.defineProperties( Object3D.prototype, {
53484  
vendor: 4,278 bytes, lines 53485-53680
53485		eulerOrder: {
53486			get: function () {
53487  
53488				console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
53489				return this.rotation.order;
53490  
53491			},
53492			set: function ( value ) {
53493  
53494				console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
53495				this.rotation.order = value;
53496  
53497			}
53498		},
53499		useQuaternion: {
53500			get: function () {
53501  
53502				console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
53503  
53504			},
53505			set: function () {
53506  
53507				console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
53508  
53509			}
53510		}
53511  
53512	} );
53513  
53514	Object.defineProperties( LOD.prototype, {
53515  
53516		objects: {
53517			get: function () {
53518  
53519				console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
53520				return this.levels;
53521  
53522			}
53523		}
53524  
53525	} );
53526  
53527	Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
53528  
53529		get: function () {
53530  
53531			console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
53532  
53533		},
53534		set: function () {
53535  
53536			console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
53537  
53538		}
53539  
53540	} );
53541  
53542	Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
53543  
53544		get: function () {
53545  
53546			console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
53547			return this.arcLengthDivisions;
53548  
53549		},
53550		set: function ( value ) {
53551  
53552			console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
53553			this.arcLengthDivisions = value;
53554  
53555		}
53556  
53557	} );
53558  
53559	//
53560  
53561	PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
53562  
53563		console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
53564				"Use .setFocalLength and .filmGauge for a photographic setup." );
53565  
53566		if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
53567		this.setFocalLength( focalLength );
53568  
53569	};
53570  
53571	//
53572  
53573	Object.defineProperties( Light.prototype, {
53574		onlyShadow: {
53575			set: function () {
53576  
53577				console.warn( 'THREE.Light: .onlyShadow has been removed.' );
53578  
53579			}
53580		},
53581		shadowCameraFov: {
53582			set: function ( value ) {
53583  
53584				console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
53585				this.shadow.camera.fov = value;
53586  
53587			}
53588		},
53589		shadowCameraLeft: {
53590			set: function ( value ) {
53591  
53592				console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
53593				this.shadow.camera.left = value;
53594  
53595			}
53596		},
53597		shadowCameraRight: {
53598			set: function ( value ) {
53599  
53600				console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
53601				this.shadow.camera.right = value;
53602  
53603			}
53604		},
53605		shadowCameraTop: {
53606			set: function ( value ) {
53607  
53608				console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
53609				this.shadow.camera.top = value;
53610  
53611			}
53612		},
53613		shadowCameraBottom: {
53614			set: function ( value ) {
53615  
53616				console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
53617				this.shadow.camera.bottom = value;
53618  
53619			}
53620		},
53621		shadowCameraNear: {
53622			set: function ( value ) {
53623  
53624				console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
53625				this.shadow.camera.near = value;
53626  
53627			}
53628		},
53629		shadowCameraFar: {
53630			set: function ( value ) {
53631  
53632				console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
53633				this.shadow.camera.far = value;
53634  
53635			}
53636		},
53637		shadowCameraVisible: {
53638			set: function () {
53639  
53640				console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
53641  
53642			}
53643		},
53644		shadowBias: {
53645			set: function ( value ) {
53646  
53647				console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
53648				this.shadow.bias = value;
53649  
53650			}
53651		},
53652		shadowDarkness: {
53653			set: function () {
53654  
53655				console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
53656  
53657			}
53658		},
53659		shadowMapWidth: {
53660			set: function ( value ) {
53661  
53662				console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
53663				this.shadow.mapSize.width = value;
53664  
53665			}
53666		},
53667		shadowMapHeight: {
53668			set: function ( value ) {
53669  
53670				console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
53671				this.shadow.mapSize.height = value;
53672  
53673			}
53674		}
53675	} );
53676  
53677	//
53678  
53679	Object.defineProperties( BufferAttribute.prototype, {
53680  
vendor: 1,325 bytes, lines 53681-53736
53681		length: {
53682			get: function () {
53683  
53684				console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
53685				return this.array.length;
53686  
53687			}
53688		},
53689		copyIndicesArray: function ( /* indices */ ) {
53690  
53691			console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
53692  
53693		}
53694  
53695	} );
53696  
53697	Object.assign( BufferGeometry.prototype, {
53698  
53699		addIndex: function ( index ) {
53700  
53701			console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
53702			this.setIndex( index );
53703  
53704		},
53705		addDrawCall: function ( start, count, indexOffset ) {
53706  
53707			if ( indexOffset !== undefined ) {
53708  
53709				console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
53710  
53711			}
53712			console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
53713			this.addGroup( start, count );
53714  
53715		},
53716		clearDrawCalls: function () {
53717  
53718			console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
53719			this.clearGroups();
53720  
53721		},
53722		computeTangents: function () {
53723  
53724			console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
53725  
53726		},
53727		computeOffsets: function () {
53728  
53729			console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
53730  
53731		}
53732  
53733	} );
53734  
53735	Object.defineProperties( BufferGeometry.prototype, {
53736  
vendor: 1,232 bytes, lines 53737-53805
53737		drawcalls: {
53738			get: function () {
53739  
53740				console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
53741				return this.groups;
53742  
53743			}
53744		},
53745		offsets: {
53746			get: function () {
53747  
53748				console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
53749				return this.groups;
53750  
53751			}
53752		}
53753  
53754	} );
53755  
53756	//
53757  
53758	Object.assign( ExtrudeBufferGeometry.prototype, {
53759  
53760		getArrays: function () {
53761  
53762			console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
53763  
53764		},
53765  
53766		addShapeList: function () {
53767  
53768			console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
53769  
53770		},
53771  
53772		addShape: function () {
53773  
53774			console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
53775  
53776		}
53777  
53778	} );
53779  
53780	//
53781  
53782	Object.defineProperties( Uniform.prototype, {
53783  
53784		dynamic: {
53785			set: function () {
53786  
53787				console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
53788  
53789			}
53790		},
53791		onUpdate: {
53792			value: function () {
53793  
53794				console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
53795				return this;
53796  
53797			}
53798		}
53799  
53800	} );
53801  
53802	//
53803  
53804	Object.defineProperties( Material.prototype, {
53805  
vendor: 1,204 bytes, lines 53806-53862
53806		wrapAround: {
53807			get: function () {
53808  
53809				console.warn( 'THREE.Material: .wrapAround has been removed.' );
53810  
53811			},
53812			set: function () {
53813  
53814				console.warn( 'THREE.Material: .wrapAround has been removed.' );
53815  
53816			}
53817		},
53818		wrapRGB: {
53819			get: function () {
53820  
53821				console.warn( 'THREE.Material: .wrapRGB has been removed.' );
53822				return new Color();
53823  
53824			}
53825		},
53826  
53827		shading: {
53828			get: function () {
53829  
53830				console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
53831  
53832			},
53833			set: function ( value ) {
53834  
53835				console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
53836				this.flatShading = ( value === FlatShading );
53837  
53838			}
53839		}
53840  
53841	} );
53842  
53843	Object.defineProperties( MeshPhongMaterial.prototype, {
53844  
53845		metal: {
53846			get: function () {
53847  
53848				console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
53849				return false;
53850  
53851			},
53852			set: function () {
53853  
53854				console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
53855  
53856			}
53857		}
53858  
53859	} );
53860  
53861	Object.defineProperties( ShaderMaterial.prototype, {
53862  
vendor: 4,060 bytes, lines 53863-54002
53863		derivatives: {
53864			get: function () {
53865  
53866				console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
53867				return this.extensions.derivatives;
53868  
53869			},
53870			set: function ( value ) {
53871  
53872				console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
53873				this.extensions.derivatives = value;
53874  
53875			}
53876		}
53877  
53878	} );
53879  
53880	//
53881  
53882	Object.assign( WebGLRenderer.prototype, {
53883  
53884		animate: function ( callback ) {
53885  
53886			console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
53887			this.setAnimationLoop( callback );
53888  
53889		},
53890  
53891		getCurrentRenderTarget: function () {
53892  
53893			console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
53894			return this.getRenderTarget();
53895  
53896		},
53897  
53898		getMaxAnisotropy: function () {
53899  
53900			console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
53901			return this.capabilities.getMaxAnisotropy();
53902  
53903		},
53904  
53905		getPrecision: function () {
53906  
53907			console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
53908			return this.capabilities.precision;
53909  
53910		},
53911  
53912		resetGLState: function () {
53913  
53914			console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
53915			return this.state.reset();
53916  
53917		},
53918  
53919		supportsFloatTextures: function () {
53920  
53921			console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
53922			return this.extensions.get( 'OES_texture_float' );
53923  
53924		},
53925		supportsHalfFloatTextures: function () {
53926  
53927			console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
53928			return this.extensions.get( 'OES_texture_half_float' );
53929  
53930		},
53931		supportsStandardDerivatives: function () {
53932  
53933			console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
53934			return this.extensions.get( 'OES_standard_derivatives' );
53935  
53936		},
53937		supportsCompressedTextureS3TC: function () {
53938  
53939			console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
53940			return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
53941  
53942		},
53943		supportsCompressedTexturePVRTC: function () {
53944  
53945			console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
53946			return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
53947  
53948		},
53949		supportsBlendMinMax: function () {
53950  
53951			console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
53952			return this.extensions.get( 'EXT_blend_minmax' );
53953  
53954		},
53955		supportsVertexTextures: function () {
53956  
53957			console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
53958			return this.capabilities.vertexTextures;
53959  
53960		},
53961		supportsInstancedArrays: function () {
53962  
53963			console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
53964			return this.extensions.get( 'ANGLE_instanced_arrays' );
53965  
53966		},
53967		enableScissorTest: function ( boolean ) {
53968  
53969			console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
53970			this.setScissorTest( boolean );
53971  
53972		},
53973		initMaterial: function () {
53974  
53975			console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
53976  
53977		},
53978		addPrePlugin: function () {
53979  
53980			console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
53981  
53982		},
53983		addPostPlugin: function () {
53984  
53985			console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
53986  
53987		},
53988		updateShadowMap: function () {
53989  
53990			console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
53991  
53992		},
53993		setFaceCulling: function () {
53994  
53995			console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
53996  
53997		}
53998  
53999	} );
54000  
54001	Object.defineProperties( WebGLRenderer.prototype, {
54002  
54003		shadowMapEnabled: {
54004			get: function () {
54005  
54006				return this.shadowMap.enabled;
54007  
54008			},
54009			set: function ( value ) {
54010  
54011				console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
54012				this.shadowMap.enabled = value;
54013  
54014			}
54015		},
54016		shadowMapType: {
54017			get: function () {
54018  
54019				return this.shadowMap.type;
54020  
54021			},
54022			set: function ( value ) {
54023  
54024				console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
54025				this.shadowMap.type = value;
54026  
54027			}
54028		},
54029		shadowMapCullFace: {
54030			get: function () {
54031  
54032				console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
54033				return undefined;
54034  
54035			},
54036			set: function ( /* value */ ) {
54037  
54038				console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
54039  
54040			}
54041		}
54042	} );
54043  
54044	Object.defineProperties( WebGLShadowMap.prototype, {
54045  
54046		cullFace: {
54047			get: function () {
54048  
54049				console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
54050				return undefined;
54051  
54052			},
54053			set: function ( /* cullFace */ ) {
54054  
54055				console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
54056  
54057			}
54058		},
54059		renderReverseSided: {
54060			get: function () {
54061  
54062				console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
54063				return undefined;
54064  
54065			},
54066			set: function () {
54067  
54068				console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
54069  
54070			}
54071		},
54072		renderSingleSided: {
54073			get: function () {
54074  
54075				console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
54076				return undefined;
54077  
54078			},
54079			set: function () {
54080  
54081				console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
54082  
54083			}
54084		}
54085  
54086	} );
54087  
54088	//
54089  
54090	Object.defineProperties( WebGLRenderTarget.prototype, {
54091  
54092		wrapS: {
54093			get: function () {
54094  
54095				console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
54096				return this.texture.wrapS;
54097  
54098			},
54099			set: function ( value ) {
54100  
54101				console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
54102				this.texture.wrapS = value;
54103  
54104			}
54105		},
54106		wrapT: {
54107			get: function () {
54108  
54109				console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
54110				return this.texture.wrapT;
54111  
54112			},
54113			set: function ( value ) {
54114  
54115				console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
54116				this.texture.wrapT = value;
54117  
54118			}
54119		},
54120		magFilter: {
54121			get: function () {
54122  
54123				console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
54124				return this.texture.magFilter;
54125  
54126			},
54127			set: function ( value ) {
54128  
54129				console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
54130				this.texture.magFilter = value;
54131  
54132			}
54133		},
54134		minFilter: {
54135			get: function () {
54136  
54137				console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
54138				return this.texture.minFilter;
54139  
54140			},
54141			set: function ( value ) {
54142  
54143				console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
54144				this.texture.minFilter = value;
54145  
54146			}
54147		},
54148		anisotropy: {
54149			get: function () {
54150  
54151				console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
54152				return this.texture.anisotropy;
54153  
54154			},
54155			set: function ( value ) {
54156  
54157				console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
54158				this.texture.anisotropy = value;
54159  
54160			}
54161		},
54162		offset: {
54163			get: function () {
54164  
54165				console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
54166				return this.texture.offset;
54167  
54168			},
54169			set: function ( value ) {
54170  
54171				console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
54172				this.texture.offset = value;
54173  
54174			}
54175		},
54176		repeat: {
54177			get: function () {
54178  
54179				console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
54180				return this.texture.repeat;
54181  
54182			},
54183			set: function ( value ) {
54184  
54185				console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
54186				this.texture.repeat = value;
54187  
54188			}
54189		},
54190		format: {
54191			get: function () {
54192  
54193				console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
54194				return this.texture.format;
54195  
54196			},
54197			set: function ( value ) {
54198  
54199				console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
54200				this.texture.format = value;
54201  
54202			}
54203		},
54204		type: {
54205			get: function () {
54206  
54207				console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
54208				return this.texture.type;
54209  
54210			},
54211			set: function ( value ) {
54212  
54213				console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
54214				this.texture.type = value;
54215  
54216			}
54217		},
54218		generateMipmaps: {
54219			get: function () {
54220  
54221				console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
54222				return this.texture.generateMipmaps;
54223  
54224			},
54225			set: function ( value ) {
54226  
54227				console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
54228				this.texture.generateMipmaps = value;
54229  
54230			}
54231		}
54232  
54233	} );
54234  
54235	//
54236  
54237	Object.defineProperties( WebVRManager.prototype, {
54238  
vendor: 4,336 bytes, lines 54239-54466
54239		standing: {
54240			set: function ( /* value */ ) {
54241  
54242				console.warn( 'THREE.WebVRManager: .standing has been removed.' );
54243  
54244			}
54245		}
54246  
54247	} );
54248  
54249	//
54250  
54251	Audio.prototype.load = function ( file ) {
54252  
54253		console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
54254		var scope = this;
54255		var audioLoader = new AudioLoader();
54256		audioLoader.load( file, function ( buffer ) {
54257  
54258			scope.setBuffer( buffer );
54259  
54260		} );
54261		return this;
54262  
54263	};
54264  
54265	AudioAnalyser.prototype.getData = function () {
54266  
54267		console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
54268		return this.getFrequencyData();
54269  
54270	};
54271  
54272	//
54273  
54274	CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
54275  
54276		console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
54277		return this.update( renderer, scene );
54278  
54279	};
54280  
54281	/**
54282	 * @author dmarcos / https://github.com/dmarcos
54283	 * @author mrdoob / http://mrdoob.com
54284	 */
54285	var VRControls = function ( object, onError ) {
54286  
54287		var scope = this;
54288  
54289		var vrDisplay, vrDisplays;
54290  
54291		var standingMatrix = new Matrix4();
54292  
54293		var frameData = null;
54294  
54295		if ( 'VRFrameData' in window ) {
54296  
54297			frameData = new VRFrameData();
54298  
54299		}
54300  
54301		function gotVRDisplays( displays ) {
54302  
54303			vrDisplays = displays;
54304  
54305			if ( displays.length > 0 ) {
54306  
54307				vrDisplay = displays[ 0 ];
54308  
54309			} else {
54310  
54311				if ( onError ) onError( 'VR input not available.' );
54312  
54313			}
54314  
54315		}
54316  
54317		if ( navigator.getVRDisplays ) {
54318  
54319			navigator.getVRDisplays().then( gotVRDisplays ).catch( function () {
54320  
54321				console.warn( 'VRControls: Unable to get VR Displays' );
54322  
54323			} );
54324  
54325		}
54326  
54327		// the Rift SDK returns the position in meters
54328		// this scale factor allows the user to define how meters
54329		// are converted to scene units.
54330  
54331		this.scale = 1;
54332  
54333		// If true will use "standing space" coordinate system where y=0 is the
54334		// floor and x=0, z=0 is the center of the room.
54335		this.standing = false;
54336  
54337		// Distance from the users eyes to the floor in meters. Used when
54338		// standing=true but the VRDisplay doesn't provide stageParameters.
54339		this.userHeight = 1.6;
54340  
54341		this.getVRDisplay = function () {
54342  
54343			return vrDisplay;
54344  
54345		};
54346  
54347		this.setVRDisplay = function ( value ) {
54348  
54349			vrDisplay = value;
54350  
54351		};
54352  
54353		this.getVRDisplays = function () {
54354  
54355			console.warn( 'VRControls: getVRDisplays() is being deprecated.' );
54356			return vrDisplays;
54357  
54358		};
54359  
54360		this.getStandingMatrix = function () {
54361  
54362			return standingMatrix;
54363  
54364		};
54365  
54366		this.update = function () {
54367  
54368			if ( vrDisplay ) {
54369  
54370				var pose;
54371  
54372				if ( vrDisplay.getFrameData ) {
54373  
54374					vrDisplay.getFrameData( frameData );
54375					pose = frameData.pose;
54376  
54377				} else if ( vrDisplay.getPose ) {
54378  
54379					pose = vrDisplay.getPose();
54380  
54381				}
54382  
54383				if ( pose.orientation !== null ) {
54384  
54385					object.quaternion.fromArray( pose.orientation );
54386  
54387				}
54388  
54389				if ( pose.position !== null ) {
54390  
54391					object.position.fromArray( pose.position );
54392  
54393				} else {
54394  
54395					object.position.set( 0, 0, 0 );
54396  
54397				}
54398  
54399				if ( this.standing ) {
54400  
54401					if ( vrDisplay.stageParameters ) {
54402  
54403						object.updateMatrix();
54404  
54405						standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform );
54406						object.applyMatrix( standingMatrix );
54407  
54408					} else {
54409  
54410						object.position.setY( object.position.y + this.userHeight );
54411  
54412					}
54413  
54414				}
54415  
54416				object.position.multiplyScalar( scope.scale );
54417  
54418			}
54419  
54420		};
54421  
54422		this.dispose = function () {
54423  
54424			vrDisplay = null;
54425  
54426		};
54427  
54428	};
54429  
54430	/**
54431	 * @author dmarcos / https://github.com/dmarcos
54432	 * @author mrdoob / http://mrdoob.com
54433	 *
54434	 * WebVR Spec: http://mozvr.github.io/webvr-spec/webvr.html
54435	 *
54436	 * Firefox: http://mozvr.com/downloads/
54437	 * Chromium: https://webvr.info/get-chrome
54438	 */
54439	var VREffect = function ( renderer, onError ) {
54440  
54441		var vrDisplay, vrDisplays;
54442		var eyeTranslationL = new Vector3();
54443		var eyeTranslationR = new Vector3();
54444		var renderRectL, renderRectR;
54445		var headMatrix = new Matrix4();
54446		var eyeMatrixL = new Matrix4();
54447		var eyeMatrixR = new Matrix4();
54448  
54449		var frameData = null;
54450  
54451		if ( 'VRFrameData' in window ) {
54452  
54453			frameData = new window.VRFrameData();
54454  
54455		}
54456  
54457		function gotVRDisplays( displays ) {
54458  
54459			vrDisplays = displays;
54460  
54461			if ( displays.length > 0 ) {
54462  
54463				vrDisplay = displays[ 0 ];
54464  
54465			} else {
54466  
vendor: 22,864 bytes, lines 54467-55330
54467				if ( onError ) onError( 'HMD not available' );
54468  
54469			}
54470  
54471		}
54472  
54473		if ( navigator.getVRDisplays ) {
54474  
54475			navigator.getVRDisplays().then( gotVRDisplays ).catch( function () {
54476  
54477				console.warn( 'VREffect: Unable to get VR Displays' );
54478  
54479			} );
54480  
54481		}
54482  
54483		//
54484  
54485		this.isPresenting = false;
54486  
54487		var scope = this;
54488  
54489		var rendererSize = renderer.getSize();
54490		var rendererUpdateStyle = false;
54491		var rendererPixelRatio = renderer.getPixelRatio();
54492  
54493		this.getVRDisplay = function () {
54494  
54495			return vrDisplay;
54496  
54497		};
54498  
54499		this.setVRDisplay = function ( value ) {
54500  
54501			vrDisplay = value;
54502  
54503		};
54504  
54505		this.getVRDisplays = function () {
54506  
54507			console.warn( 'VREffect: getVRDisplays() is being deprecated.' );
54508			return vrDisplays;
54509  
54510		};
54511  
54512		this.setSize = function ( width, height, updateStyle ) {
54513  
54514			rendererSize = { width: width, height: height };
54515			rendererUpdateStyle = updateStyle;
54516  
54517			if ( scope.isPresenting ) {
54518  
54519				var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
54520				renderer.setPixelRatio( 1 );
54521				renderer.setSize( eyeParamsL.renderWidth * 2, eyeParamsL.renderHeight, false );
54522  
54523			} else {
54524  
54525				renderer.setPixelRatio( rendererPixelRatio );
54526				renderer.setSize( width, height, updateStyle );
54527  
54528			}
54529  
54530		};
54531  
54532		// VR presentation
54533  
54534		var canvas = renderer.domElement;
54535		var defaultLeftBounds = [ 0.0, 0.0, 0.5, 1.0 ];
54536		var defaultRightBounds = [ 0.5, 0.0, 0.5, 1.0 ];
54537  
54538		function onVRDisplayPresentChange() {
54539  
54540			var wasPresenting = scope.isPresenting;
54541			scope.isPresenting = vrDisplay !== undefined && vrDisplay.isPresenting;
54542  
54543			if ( scope.isPresenting ) {
54544  
54545				var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
54546				var eyeWidth = eyeParamsL.renderWidth;
54547				var eyeHeight = eyeParamsL.renderHeight;
54548  
54549				if ( ! wasPresenting ) {
54550  
54551					rendererPixelRatio = renderer.getPixelRatio();
54552					rendererSize = renderer.getSize();
54553  
54554					renderer.setPixelRatio( 1 );
54555					renderer.setSize( eyeWidth * 2, eyeHeight, false );
54556  
54557				}
54558  
54559			} else if ( wasPresenting ) {
54560  
54561				renderer.setPixelRatio( rendererPixelRatio );
54562				renderer.setSize( rendererSize.width, rendererSize.height, rendererUpdateStyle );
54563  
54564			}
54565  
54566		}
54567  
54568		window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
54569  
54570		this.setFullScreen = function ( boolean ) {
54571  
54572			return new Promise( function ( resolve, reject ) {
54573  
54574				if ( vrDisplay === undefined ) {
54575  
54576					reject( new Error( 'No VR hardware found.' ) );
54577					return;
54578  
54579				}
54580  
54581				if ( scope.isPresenting === boolean ) {
54582  
54583					resolve();
54584					return;
54585  
54586				}
54587  
54588				if ( boolean ) {
54589  
54590					resolve( vrDisplay.requestPresent( [ { source: canvas } ] ) );
54591  
54592				} else {
54593  
54594					resolve( vrDisplay.exitPresent() );
54595  
54596				}
54597  
54598			} );
54599  
54600		};
54601  
54602		this.requestPresent = function () {
54603  
54604			return this.setFullScreen( true );
54605  
54606		};
54607  
54608		this.exitPresent = function () {
54609  
54610			return this.setFullScreen( false );
54611  
54612		};
54613  
54614		this.requestAnimationFrame = function ( f ) {
54615  
54616			if ( vrDisplay !== undefined ) {
54617  
54618				return vrDisplay.requestAnimationFrame( f );
54619  
54620			} else {
54621  
54622				return window.requestAnimationFrame( f );
54623  
54624			}
54625  
54626		};
54627  
54628		this.cancelAnimationFrame = function ( h ) {
54629  
54630			if ( vrDisplay !== undefined ) {
54631  
54632				vrDisplay.cancelAnimationFrame( h );
54633  
54634			} else {
54635  
54636				window.cancelAnimationFrame( h );
54637  
54638			}
54639  
54640		};
54641  
54642		this.submitFrame = function () {
54643  
54644			if ( vrDisplay !== undefined && scope.isPresenting ) {
54645  
54646				vrDisplay.submitFrame();
54647  
54648			}
54649  
54650		};
54651  
54652		this.autoSubmitFrame = true;
54653  
54654		// render
54655  
54656		var cameraL = new PerspectiveCamera();
54657		cameraL.layers.enable( 1 );
54658  
54659		var cameraR = new PerspectiveCamera();
54660		cameraR.layers.enable( 2 );
54661  
54662		this.render = function ( scene, camera, renderTarget, forceClear ) {
54663  
54664			if ( vrDisplay && scope.isPresenting ) {
54665  
54666				var autoUpdate = scene.autoUpdate;
54667  
54668				if ( autoUpdate ) {
54669  
54670					scene.updateMatrixWorld();
54671					scene.autoUpdate = false;
54672  
54673				}
54674  
54675				if ( Array.isArray( scene ) ) {
54676  
54677					console.warn( 'VREffect.render() no longer supports arrays. Use object.layers instead.' );
54678					scene = scene[ 0 ];
54679  
54680				}
54681  
54682				// When rendering we don't care what the recommended size is, only what the actual size
54683				// of the backbuffer is.
54684				var size = renderer.getSize();
54685				var layers = vrDisplay.getLayers();
54686				var leftBounds;
54687				var rightBounds;
54688  
54689				if ( layers.length ) {
54690  
54691					var layer = layers[ 0 ];
54692  
54693					leftBounds = layer.leftBounds !== null && layer.leftBounds.length === 4 ? layer.leftBounds : defaultLeftBounds;
54694					rightBounds = layer.rightBounds !== null && layer.rightBounds.length === 4 ? layer.rightBounds : defaultRightBounds;
54695  
54696				} else {
54697  
54698					leftBounds = defaultLeftBounds;
54699					rightBounds = defaultRightBounds;
54700  
54701				}
54702  
54703				renderRectL = {
54704					x: Math.round( size.width * leftBounds[ 0 ] ),
54705					y: Math.round( size.height * leftBounds[ 1 ] ),
54706					width: Math.round( size.width * leftBounds[ 2 ] ),
54707					height: Math.round( size.height * leftBounds[ 3 ] )
54708				};
54709				renderRectR = {
54710					x: Math.round( size.width * rightBounds[ 0 ] ),
54711					y: Math.round( size.height * rightBounds[ 1 ] ),
54712					width: Math.round( size.width * rightBounds[ 2 ] ),
54713					height: Math.round( size.height * rightBounds[ 3 ] )
54714				};
54715  
54716				if ( renderTarget ) {
54717  
54718					renderer.setRenderTarget( renderTarget );
54719					renderTarget.scissorTest = true;
54720  
54721				} else {
54722  
54723					renderer.setRenderTarget( null );
54724					renderer.setScissorTest( true );
54725  
54726				}
54727  
54728				if ( renderer.autoClear || forceClear ) renderer.clear();
54729  
54730				if ( camera.parent === null ) camera.updateMatrixWorld();
54731  
54732				camera.matrixWorld.decompose( cameraL.position, cameraL.quaternion, cameraL.scale );
54733  
54734				cameraR.position.copy( cameraL.position );
54735				cameraR.quaternion.copy( cameraL.quaternion );
54736				cameraR.scale.copy( cameraL.scale );
54737  
54738				if ( vrDisplay.getFrameData ) {
54739  
54740					vrDisplay.depthNear = camera.near;
54741					vrDisplay.depthFar = camera.far;
54742  
54743					vrDisplay.getFrameData( frameData );
54744  
54745					cameraL.projectionMatrix.elements = frameData.leftProjectionMatrix;
54746					cameraR.projectionMatrix.elements = frameData.rightProjectionMatrix;
54747  
54748					getEyeMatrices( frameData );
54749  
54750					cameraL.updateMatrix();
54751					cameraL.matrix.multiply( eyeMatrixL );
54752					cameraL.matrix.decompose( cameraL.position, cameraL.quaternion, cameraL.scale );
54753  
54754					cameraR.updateMatrix();
54755					cameraR.matrix.multiply( eyeMatrixR );
54756					cameraR.matrix.decompose( cameraR.position, cameraR.quaternion, cameraR.scale );
54757  
54758				} else {
54759  
54760					var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
54761					var eyeParamsR = vrDisplay.getEyeParameters( 'right' );
54762  
54763					cameraL.projectionMatrix = fovToProjection( eyeParamsL.fieldOfView, true, camera.near, camera.far );
54764					cameraR.projectionMatrix = fovToProjection( eyeParamsR.fieldOfView, true, camera.near, camera.far );
54765  
54766					eyeTranslationL.fromArray( eyeParamsL.offset );
54767					eyeTranslationR.fromArray( eyeParamsR.offset );
54768  
54769					cameraL.translateOnAxis( eyeTranslationL, cameraL.scale.x );
54770					cameraR.translateOnAxis( eyeTranslationR, cameraR.scale.x );
54771  
54772				}
54773  
54774				// render left eye
54775				if ( renderTarget ) {
54776  
54777					renderTarget.viewport.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
54778					renderTarget.scissor.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
54779  
54780				} else {
54781  
54782					renderer.setViewport( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
54783					renderer.setScissor( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
54784  
54785				}
54786				renderer.render( scene, cameraL, renderTarget, forceClear );
54787  
54788				// render right eye
54789				if ( renderTarget ) {
54790  
54791					renderTarget.viewport.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
54792					renderTarget.scissor.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
54793  
54794				} else {
54795  
54796					renderer.setViewport( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
54797					renderer.setScissor( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
54798  
54799				}
54800				renderer.render( scene, cameraR, renderTarget, forceClear );
54801  
54802				if ( renderTarget ) {
54803  
54804					renderTarget.viewport.set( 0, 0, size.width, size.height );
54805					renderTarget.scissor.set( 0, 0, size.width, size.height );
54806					renderTarget.scissorTest = false;
54807					renderer.setRenderTarget( null );
54808  
54809				} else {
54810  
54811					renderer.setViewport( 0, 0, size.width, size.height );
54812					renderer.setScissorTest( false );
54813  
54814				}
54815  
54816				if ( autoUpdate ) {
54817  
54818					scene.autoUpdate = true;
54819  
54820				}
54821  
54822				if ( scope.autoSubmitFrame ) {
54823  
54824					scope.submitFrame();
54825  
54826				}
54827  
54828				return;
54829  
54830			}
54831  
54832			// Regular render mode if not HMD
54833  
54834			renderer.render( scene, camera, renderTarget, forceClear );
54835  
54836		};
54837  
54838		this.dispose = function () {
54839  
54840			window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
54841  
54842		};
54843  
54844		//
54845  
54846		var poseOrientation = new Quaternion();
54847		var posePosition = new Vector3();
54848  
54849		// Compute model matrices of the eyes with respect to the head.
54850		function getEyeMatrices( frameData ) {
54851  
54852			// Compute the matrix for the position of the head based on the pose
54853			if ( frameData.pose.orientation ) {
54854  
54855				poseOrientation.fromArray( frameData.pose.orientation );
54856				headMatrix.makeRotationFromQuaternion( poseOrientation );
54857  
54858			}	else {
54859  
54860				headMatrix.identity();
54861  
54862			}
54863  
54864			if ( frameData.pose.position ) {
54865  
54866				posePosition.fromArray( frameData.pose.position );
54867				headMatrix.setPosition( posePosition );
54868  
54869			}
54870  
54871			// The view matrix transforms vertices from sitting space to eye space. As such, the view matrix can be thought of as a product of two matrices:
54872			// headToEyeMatrix * sittingToHeadMatrix
54873  
54874			// The headMatrix that we've calculated above is the model matrix of the head in sitting space, which is the inverse of sittingToHeadMatrix.
54875			// So when we multiply the view matrix with headMatrix, we're left with headToEyeMatrix:
54876			// viewMatrix * headMatrix = headToEyeMatrix * sittingToHeadMatrix * headMatrix = headToEyeMatrix
54877  
54878			eyeMatrixL.fromArray( frameData.leftViewMatrix );
54879			eyeMatrixL.multiply( headMatrix );
54880			eyeMatrixR.fromArray( frameData.rightViewMatrix );
54881			eyeMatrixR.multiply( headMatrix );
54882  
54883			// The eye's model matrix in head space is the inverse of headToEyeMatrix we calculated above.
54884  
54885			eyeMatrixL.getInverse( eyeMatrixL );
54886			eyeMatrixR.getInverse( eyeMatrixR );
54887  
54888		}
54889  
54890		function fovToNDCScaleOffset( fov ) {
54891  
54892			var pxscale = 2.0 / ( fov.leftTan + fov.rightTan );
54893			var pxoffset = ( fov.leftTan - fov.rightTan ) * pxscale * 0.5;
54894			var pyscale = 2.0 / ( fov.upTan + fov.downTan );
54895			var pyoffset = ( fov.upTan - fov.downTan ) * pyscale * 0.5;
54896			return { scale: [ pxscale, pyscale ], offset: [ pxoffset, pyoffset ] };
54897  
54898		}
54899  
54900		function fovPortToProjection( fov, rightHanded, zNear, zFar ) {
54901  
54902			rightHanded = rightHanded === undefined ? true : rightHanded;
54903			zNear = zNear === undefined ? 0.01 : zNear;
54904			zFar = zFar === undefined ? 10000.0 : zFar;
54905  
54906			var handednessScale = rightHanded ? - 1.0 : 1.0;
54907  
54908			// start with an identity matrix
54909			var mobj = new Matrix4();
54910			var m = mobj.elements;
54911  
54912			// and with scale/offset info for normalized device coords
54913			var scaleAndOffset = fovToNDCScaleOffset( fov );
54914  
54915			// X result, map clip edges to [-w,+w]
54916			m[ 0 * 4 + 0 ] = scaleAndOffset.scale[ 0 ];
54917			m[ 0 * 4 + 1 ] = 0.0;
54918			m[ 0 * 4 + 2 ] = scaleAndOffset.offset[ 0 ] * handednessScale;
54919			m[ 0 * 4 + 3 ] = 0.0;
54920  
54921			// Y result, map clip edges to [-w,+w]
54922			// Y offset is negated because this proj matrix transforms from world coords with Y=up,
54923			// but the NDC scaling has Y=down (thanks D3D?)
54924			m[ 1 * 4 + 0 ] = 0.0;
54925			m[ 1 * 4 + 1 ] = scaleAndOffset.scale[ 1 ];
54926			m[ 1 * 4 + 2 ] = - scaleAndOffset.offset[ 1 ] * handednessScale;
54927			m[ 1 * 4 + 3 ] = 0.0;
54928  
54929			// Z result (up to the app)
54930			m[ 2 * 4 + 0 ] = 0.0;
54931			m[ 2 * 4 + 1 ] = 0.0;
54932			m[ 2 * 4 + 2 ] = zFar / ( zNear - zFar ) * - handednessScale;
54933			m[ 2 * 4 + 3 ] = ( zFar * zNear ) / ( zNear - zFar );
54934  
54935			// W result (= Z in)
54936			m[ 3 * 4 + 0 ] = 0.0;
54937			m[ 3 * 4 + 1 ] = 0.0;
54938			m[ 3 * 4 + 2 ] = handednessScale;
54939			m[ 3 * 4 + 3 ] = 0.0;
54940  
54941			mobj.transpose();
54942			return mobj;
54943  
54944		}
54945  
54946		function fovToProjection( fov, rightHanded, zNear, zFar ) {
54947  
54948			var DEG2RAD = Math.PI / 180.0;
54949  
54950			var fovPort = {
54951				upTan: Math.tan( fov.upDegrees * DEG2RAD ),
54952				downTan: Math.tan( fov.downDegrees * DEG2RAD ),
54953				leftTan: Math.tan( fov.leftDegrees * DEG2RAD ),
54954				rightTan: Math.tan( fov.rightDegrees * DEG2RAD )
54955			};
54956  
54957			return fovPortToProjection( fovPort, rightHanded, zNear, zFar );
54958  
54959		}
54960  
54961	};
54962  
54963	/**
54964	 * @author qiao / https://github.com/qiao
54965	 * @author mrdoob / http://mrdoob.com
54966	 * @author alteredq / http://alteredqualia.com/
54967	 * @author WestLangley / http://github.com/WestLangley
54968	 * @author erich666 / http://erichaines.com
54969	 */
54970	var OrbitControls = function ( object, domElement ) {
54971  
54972		this.object = object;
54973  
54974		this.domElement = ( domElement !== undefined ) ? domElement : document;
54975  
54976		// Set to false to disable this control
54977		this.enabled = true;
54978  
54979		// "target" sets the location of focus, where the object orbits around
54980		this.target = new Vector3();
54981  
54982		// How far you can dolly in and out ( PerspectiveCamera only )
54983		this.minDistance = 0;
54984		this.maxDistance = Infinity;
54985  
54986		// How far you can zoom in and out ( OrthographicCamera only )
54987		this.minZoom = 0;
54988		this.maxZoom = Infinity;
54989  
54990		// How far you can orbit vertically, upper and lower limits.
54991		// Range is 0 to Math.PI radians.
54992		this.minPolarAngle = 0; // radians
54993		this.maxPolarAngle = Math.PI; // radians
54994  
54995		// How far you can orbit horizontally, upper and lower limits.
54996		// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
54997		this.minAzimuthAngle = - Infinity; // radians
54998		this.maxAzimuthAngle = Infinity; // radians
54999  
55000		// Set to true to enable damping (inertia)
55001		// If damping is enabled, you must call controls.update() in your animation loop
55002		this.enableDamping = false;
55003		this.dampingFactor = 0.25;
55004  
55005		// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
55006		// Set to false to disable zooming
55007		this.enableZoom = true;
55008		this.zoomSpeed = 1.0;
55009  
55010		// Set to false to disable rotating
55011		this.enableRotate = true;
55012		this.rotateSpeed = 1.0;
55013  
55014		// Set to false to disable panning
55015		this.enablePan = true;
55016		this.panSpeed = 1.0;
55017		this.screenSpacePanning = false; // if true, pan in screen-space
55018		this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
55019  
55020		// Set to true to automatically rotate around the target
55021		// If auto-rotate is enabled, you must call controls.update() in your animation loop
55022		this.autoRotate = false;
55023		this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
55024  
55025		// Set to false to disable use of the keys
55026		this.enableKeys = true;
55027  
55028		// The four arrow keys
55029		this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
55030  
55031		// Mouse buttons
55032		this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT };
55033  
55034		// for reset
55035		this.target0 = this.target.clone();
55036		this.position0 = this.object.position.clone();
55037		this.zoom0 = this.object.zoom;
55038  
55039		//
55040		// public methods
55041		//
55042  
55043		this.getPolarAngle = function () {
55044  
55045			return spherical.phi;
55046  
55047		};
55048  
55049		this.getAzimuthalAngle = function () {
55050  
55051			return spherical.theta;
55052  
55053		};
55054  
55055		this.saveState = function () {
55056  
55057			scope.target0.copy( scope.target );
55058			scope.position0.copy( scope.object.position );
55059			scope.zoom0 = scope.object.zoom;
55060  
55061		};
55062  
55063		this.reset = function () {
55064  
55065			scope.target.copy( scope.target0 );
55066			scope.object.position.copy( scope.position0 );
55067			scope.object.zoom = scope.zoom0;
55068  
55069			scope.object.updateProjectionMatrix();
55070			scope.dispatchEvent( changeEvent );
55071  
55072			scope.update();
55073  
55074			state = STATE.NONE;
55075  
55076		};
55077  
55078		// this method is exposed, but perhaps it would be better if we can make it private...
55079		this.update = function () {
55080  
55081			var offset = new Vector3();
55082  
55083			// so camera.up is the orbit axis
55084			var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );
55085			var quatInverse = quat.clone().inverse();
55086  
55087			var lastPosition = new Vector3();
55088			var lastQuaternion = new Quaternion();
55089  
55090			return function update() {
55091  
55092				var position = scope.object.position;
55093  
55094				offset.copy( position ).sub( scope.target );
55095  
55096				// rotate offset to "y-axis-is-up" space
55097				offset.applyQuaternion( quat );
55098  
55099				// angle from z-axis around y-axis
55100				spherical.setFromVector3( offset );
55101  
55102				if ( scope.autoRotate && state === STATE.NONE ) {
55103  
55104					scope.rotateLeft( getAutoRotationAngle() );
55105  
55106				}
55107  
55108				spherical.theta += sphericalDelta.theta;
55109				spherical.phi += sphericalDelta.phi;
55110  
55111				// restrict theta to be between desired limits
55112				spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
55113  
55114				// restrict phi to be between desired limits
55115				spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
55116  
55117				spherical.makeSafe();
55118  
55119  
55120				spherical.radius *= scale;
55121  
55122				// restrict radius to be between desired limits
55123				spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
55124  
55125				// move target to panned location
55126				scope.target.add( panOffset );
55127  
55128				offset.setFromSpherical( spherical );
55129  
55130				// rotate offset back to "camera-up-vector-is-up" space
55131				offset.applyQuaternion( quatInverse );
55132  
55133				position.copy( scope.target ).add( offset );
55134  
55135				scope.object.lookAt( scope.target );
55136  
55137				if ( scope.enableDamping === true ) {
55138  
55139					sphericalDelta.theta *= ( 1 - scope.dampingFactor );
55140					sphericalDelta.phi *= ( 1 - scope.dampingFactor );
55141  
55142					panOffset.multiplyScalar( 1 - scope.dampingFactor );
55143  
55144				} else {
55145  
55146					sphericalDelta.set( 0, 0, 0 );
55147  
55148					panOffset.set( 0, 0, 0 );
55149  
55150				}
55151  
55152				scale = 1;
55153  
55154				// update condition is:
55155				// min(camera displacement, camera rotation in radians)^2 > EPS
55156				// using small-angle approximation cos(x/2) = 1 - x^2 / 8
55157  
55158				if ( zoomChanged ||
55159					lastPosition.distanceToSquared( scope.object.position ) > EPS ||
55160					8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
55161  
55162					scope.dispatchEvent( changeEvent );
55163  
55164					lastPosition.copy( scope.object.position );
55165					lastQuaternion.copy( scope.object.quaternion );
55166					zoomChanged = false;
55167  
55168					return true;
55169  
55170				}
55171  
55172				return false;
55173  
55174			};
55175  
55176		}();
55177  
55178		this.dispose = function () {
55179  
55180			scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );
55181			scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );
55182			scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );
55183  
55184			scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );
55185			scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );
55186			scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );
55187  
55188			document.removeEventListener( 'mousemove', onMouseMove, false );
55189			document.removeEventListener( 'mouseup', onMouseUp, false );
55190  
55191			window.removeEventListener( 'keydown', onKeyDown, false );
55192  
55193			//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
55194  
55195		};
55196  
55197		//
55198		// internals
55199		//
55200  
55201		var scope = this;
55202  
55203		var changeEvent = { type: 'change' };
55204		var startEvent = { type: 'start' };
55205		var endEvent = { type: 'end' };
55206  
55207		var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 };
55208  
55209		var state = STATE.NONE;
55210  
55211		var EPS = 0.000001;
55212  
55213		// current position in spherical coordinates
55214		var spherical = new Spherical();
55215		var sphericalDelta = new Spherical();
55216  
55217		var scale = 1;
55218		var panOffset = new Vector3();
55219		var zoomChanged = false;
55220  
55221		var rotateStart = new Vector2();
55222		var rotateEnd = new Vector2();
55223		var rotateDelta = new Vector2();
55224  
55225		var panStart = new Vector2();
55226		var panEnd = new Vector2();
55227		var panDelta = new Vector2();
55228  
55229		var dollyStart = new Vector2();
55230		var dollyEnd = new Vector2();
55231		var dollyDelta = new Vector2();
55232  
55233		function getAutoRotationAngle() {
55234  
55235			return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
55236  
55237		}
55238  
55239		function getZoomScale() {
55240  
55241			return Math.pow( 0.95, scope.zoomSpeed );
55242  
55243		}
55244  
55245		scope.rotateLeft = function( angle ) {
55246  
55247			sphericalDelta.theta -= angle;
55248  
55249		};
55250  
55251		scope.rotateUp = function( angle ) {
55252  
55253			sphericalDelta.phi -= angle;
55254  
55255		};
55256  
55257		var panLeft = function () {
55258  
55259			var v = new Vector3();
55260  
55261			return function panLeft( distance, objectMatrix ) {
55262  
55263				v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
55264				v.multiplyScalar( - distance );
55265  
55266				panOffset.add( v );
55267  
55268			};
55269  
55270		}();
55271  
55272		var panUp = function () {
55273  
55274			var v = new Vector3();
55275  
55276			return function panUp( distance, objectMatrix ) {
55277  
55278				if ( scope.screenSpacePanning === true ) {
55279  
55280					v.setFromMatrixColumn( objectMatrix, 1 );
55281  
55282				} else {
55283  
55284					v.setFromMatrixColumn( objectMatrix, 0 );
55285					v.crossVectors( scope.object.up, v );
55286  
55287				}
55288  
55289				v.multiplyScalar( distance );
55290  
55291				panOffset.add( v );
55292  
55293			};
55294  
55295		}();
55296  
55297		// deltaX and deltaY are in pixels; right and down are positive
55298		var pan = function () {
55299  
55300			var offset = new Vector3();
55301  
55302			return function pan( deltaX, deltaY ) {
55303  
55304				var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
55305  
55306				if ( scope.object.isPerspectiveCamera ) {
55307  
55308					// perspective
55309					var position = scope.object.position;
55310					offset.copy( position ).sub( scope.target );
55311					var targetDistance = offset.length();
55312  
55313					// half of the fov is center to top of screen
55314					targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
55315  
55316					// we use only clientHeight here so aspect ratio does not distort speed
55317					panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
55318					panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
55319  
55320				} else if ( scope.object.isOrthographicCamera ) {
55321  
55322					// orthographic
55323					panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
55324					panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
55325  
55326				} else {
55327  
55328					// camera neither orthographic nor perspective
55329					console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
55330					scope.enablePan = false;
55331  
55332				}
55333  
55334			};
55335  
55336		}();
55337  
55338		function dollyIn( dollyScale ) {
55339  
55340			if ( scope.object.isPerspectiveCamera ) {
55341  
55342				scale /= dollyScale;
55343  
55344			} else if ( scope.object.isOrthographicCamera ) {
55345  
55346				scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
55347				scope.object.updateProjectionMatrix();
55348				zoomChanged = true;
55349  
55350			} else {
55351  
55352				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
55353				scope.enableZoom = false;
55354  
55355			}
55356  
55357		}
55358  
55359		function dollyOut( dollyScale ) {
55360  
55361			if ( scope.object.isPerspectiveCamera ) {
55362  
55363				scale *= dollyScale;
55364  
55365			} else if ( scope.object.isOrthographicCamera ) {
55366  
55367				scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
55368				scope.object.updateProjectionMatrix();
55369				zoomChanged = true;
55370  
55371			} else {
55372  
55373				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
55374				scope.enableZoom = false;
vendor: 14,089 bytes, lines 55375-56053
55375  
55376			}
55377  
55378		}
55379  
55380		//
55381		// event callbacks - update the object state
55382		//
55383  
55384		function handleMouseDownRotate( event ) {
55385  
55386			//console.log( 'handleMouseDownRotate' );
55387  
55388			rotateStart.set( event.clientX, event.clientY );
55389  
55390		}
55391  
55392		function handleMouseDownDolly( event ) {
55393  
55394			//console.log( 'handleMouseDownDolly' );
55395  
55396			dollyStart.set( event.clientX, event.clientY );
55397  
55398		}
55399  
55400		function handleMouseDownPan( event ) {
55401  
55402			//console.log( 'handleMouseDownPan' );
55403  
55404			panStart.set( event.clientX, event.clientY );
55405  
55406		}
55407  
55408		function handleMouseMoveRotate( event ) {
55409  
55410			//console.log( 'handleMouseMoveRotate' );
55411  
55412			rotateEnd.set( event.clientX, event.clientY );
55413  
55414			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
55415  
55416			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
55417  
55418			scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
55419  
55420			scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
55421  
55422			rotateStart.copy( rotateEnd );
55423  
55424			scope.update();
55425  
55426		}
55427  
55428		function handleMouseMoveDolly( event ) {
55429  
55430			//console.log( 'handleMouseMoveDolly' );
55431  
55432			dollyEnd.set( event.clientX, event.clientY );
55433  
55434			dollyDelta.subVectors( dollyEnd, dollyStart );
55435  
55436			if ( dollyDelta.y > 0 ) {
55437  
55438				dollyIn( getZoomScale() );
55439  
55440			} else if ( dollyDelta.y < 0 ) {
55441  
55442				dollyOut( getZoomScale() );
55443  
55444			}
55445  
55446			dollyStart.copy( dollyEnd );
55447  
55448			scope.update();
55449  
55450		}
55451  
55452		function handleMouseMovePan( event ) {
55453  
55454			//console.log( 'handleMouseMovePan' );
55455  
55456			panEnd.set( event.clientX, event.clientY );
55457  
55458			panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
55459  
55460			pan( panDelta.x, panDelta.y );
55461  
55462			panStart.copy( panEnd );
55463  
55464			scope.update();
55465  
55466		}
55467  
55468		function handleMouseWheel( event ) {
55469  
55470			// console.log( 'handleMouseWheel' );
55471  
55472			if ( event.deltaY < 0 ) {
55473  
55474				dollyOut( getZoomScale() );
55475  
55476			} else if ( event.deltaY > 0 ) {
55477  
55478				dollyIn( getZoomScale() );
55479  
55480			}
55481  
55482			scope.update();
55483  
55484		}
55485  
55486		function handleKeyDown( event ) {
55487  
55488			//console.log( 'handleKeyDown' );
55489  
55490			switch ( event.keyCode ) {
55491  
55492				case scope.keys.UP:
55493					pan( 0, scope.keyPanSpeed );
55494					scope.update();
55495					break;
55496  
55497				case scope.keys.BOTTOM:
55498					pan( 0, - scope.keyPanSpeed );
55499					scope.update();
55500					break;
55501  
55502				case scope.keys.LEFT:
55503					pan( scope.keyPanSpeed, 0 );
55504					scope.update();
55505					break;
55506  
55507				case scope.keys.RIGHT:
55508					pan( - scope.keyPanSpeed, 0 );
55509					scope.update();
55510					break;
55511  
55512			}
55513  
55514		}
55515  
55516		function handleTouchStartRotate( event ) {
55517  
55518			//console.log( 'handleTouchStartRotate' );
55519  
55520			rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
55521  
55522		}
55523  
55524		function handleTouchStartDollyPan( event ) {
55525  
55526			//console.log( 'handleTouchStartDollyPan' );
55527  
55528			if ( scope.enableZoom ) {
55529  
55530				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
55531				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
55532  
55533				var distance = Math.sqrt( dx * dx + dy * dy );
55534  
55535				dollyStart.set( 0, distance );
55536  
55537			}
55538  
55539			if ( scope.enablePan ) {
55540  
55541				var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
55542				var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
55543  
55544				panStart.set( x, y );
55545  
55546			}
55547  
55548		}
55549  
55550		function handleTouchMoveRotate( event ) {
55551  
55552			//console.log( 'handleTouchMoveRotate' );
55553  
55554			rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
55555  
55556			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
55557  
55558			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
55559  
55560			scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
55561  
55562			scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
55563  
55564			rotateStart.copy( rotateEnd );
55565  
55566			scope.update();
55567  
55568		}
55569  
55570		function handleTouchMoveDollyPan( event ) {
55571  
55572			//console.log( 'handleTouchMoveDollyPan' );
55573  
55574			if ( scope.enableZoom ) {
55575  
55576				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
55577				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
55578  
55579				var distance = Math.sqrt( dx * dx + dy * dy );
55580  
55581				dollyEnd.set( 0, distance );
55582  
55583				dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
55584  
55585				dollyIn( dollyDelta.y );
55586  
55587				dollyStart.copy( dollyEnd );
55588  
55589			}
55590  
55591			if ( scope.enablePan ) {
55592  
55593				var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
55594				var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
55595  
55596				panEnd.set( x, y );
55597  
55598				panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
55599  
55600				pan( panDelta.x, panDelta.y );
55601  
55602				panStart.copy( panEnd );
55603  
55604			}
55605  
55606			scope.update();
55607  
55608		}
55609  
55610		//
55611		// event handlers - FSM: listen for events and reset state
55612		//
55613  
55614		function onMouseDown( event ) {
55615  
55616			if ( scope.enabled === false ) return;
55617  
55618			event.preventDefault();
55619  
55620			switch ( event.button ) {
55621  
55622				case scope.mouseButtons.ORBIT:
55623  
55624					if ( scope.enableRotate === false ) return;
55625  
55626					handleMouseDownRotate( event );
55627  
55628					state = STATE.ROTATE;
55629  
55630					break;
55631  
55632				case scope.mouseButtons.ZOOM:
55633  
55634					if ( scope.enableZoom === false ) return;
55635  
55636					handleMouseDownDolly( event );
55637  
55638					state = STATE.DOLLY;
55639  
55640					break;
55641  
55642				case scope.mouseButtons.PAN:
55643  
55644					if ( scope.enablePan === false ) return;
55645  
55646					handleMouseDownPan( event );
55647  
55648					state = STATE.PAN;
55649  
55650					break;
55651  
55652			}
55653  
55654			if ( state !== STATE.NONE ) {
55655  
55656				document.addEventListener( 'mousemove', onMouseMove, false );
55657				document.addEventListener( 'mouseup', onMouseUp, false );
55658  
55659				scope.dispatchEvent( startEvent );
55660  
55661			}
55662  
55663		}
55664  
55665		function onMouseMove( event ) {
55666  
55667			if ( scope.enabled === false ) return;
55668  
55669			event.preventDefault();
55670  
55671			switch ( state ) {
55672  
55673				case STATE.ROTATE:
55674  
55675					if ( scope.enableRotate === false ) return;
55676  
55677					handleMouseMoveRotate( event );
55678  
55679					break;
55680  
55681				case STATE.DOLLY:
55682  
55683					if ( scope.enableZoom === false ) return;
55684  
55685					handleMouseMoveDolly( event );
55686  
55687					break;
55688  
55689				case STATE.PAN:
55690  
55691					if ( scope.enablePan === false ) return;
55692  
55693					handleMouseMovePan( event );
55694  
55695					break;
55696  
55697			}
55698  
55699		}
55700  
55701		function onMouseUp( event ) {
55702  
55703			if ( scope.enabled === false ) return;
55704  
55705			document.removeEventListener( 'mousemove', onMouseMove, false );
55706			document.removeEventListener( 'mouseup', onMouseUp, false );
55707  
55708			scope.dispatchEvent( endEvent );
55709  
55710			state = STATE.NONE;
55711  
55712		}
55713  
55714		function onMouseWheel( event ) {
55715  
55716			if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;
55717  
55718			event.preventDefault();
55719			event.stopPropagation();
55720  
55721			scope.dispatchEvent( startEvent );
55722  
55723			handleMouseWheel( event );
55724  
55725			scope.dispatchEvent( endEvent );
55726  
55727		}
55728  
55729		function onKeyDown( event ) {
55730  
55731			if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;
55732  
55733			handleKeyDown( event );
55734  
55735		}
55736  
55737		function onTouchStart( event ) {
55738  
55739			if ( scope.enabled === false ) return;
55740  
55741			event.preventDefault();
55742  
55743			switch ( event.touches.length ) {
55744  
55745				case 1:	// one-fingered touch: rotate
55746  
55747					if ( scope.enableRotate === false ) return;
55748  
55749					handleTouchStartRotate( event );
55750  
55751					state = STATE.TOUCH_ROTATE;
55752  
55753					break;
55754  
55755				case 2:	// two-fingered touch: dolly-pan
55756  
55757					if ( scope.enableZoom === false && scope.enablePan === false ) return;
55758  
55759					handleTouchStartDollyPan( event );
55760  
55761					state = STATE.TOUCH_DOLLY_PAN;
55762  
55763					break;
55764  
55765				default:
55766  
55767					state = STATE.NONE;
55768  
55769			}
55770  
55771			if ( state !== STATE.NONE ) {
55772  
55773				scope.dispatchEvent( startEvent );
55774  
55775			}
55776  
55777		}
55778  
55779		function onTouchMove( event ) {
55780  
55781			if ( scope.enabled === false ) return;
55782  
55783			event.preventDefault();
55784			event.stopPropagation();
55785  
55786			switch ( event.touches.length ) {
55787  
55788				case 1: // one-fingered touch: rotate
55789  
55790					if ( scope.enableRotate === false ) return;
55791					if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?
55792  
55793					handleTouchMoveRotate( event );
55794  
55795					break;
55796  
55797				case 2: // two-fingered touch: dolly-pan
55798  
55799					if ( scope.enableZoom === false && scope.enablePan === false ) return;
55800					if ( state !== STATE.TOUCH_DOLLY_PAN ) return; // is this needed?
55801  
55802					handleTouchMoveDollyPan( event );
55803  
55804					break;
55805  
55806				default:
55807  
55808					state = STATE.NONE;
55809  
55810			}
55811  
55812		}
55813  
55814		function onTouchEnd( event ) {
55815  
55816			if ( scope.enabled === false ) return;
55817  
55818			scope.dispatchEvent( endEvent );
55819  
55820			state = STATE.NONE;
55821  
55822		}
55823  
55824		function onContextMenu( event ) {
55825  
55826			if ( scope.enabled === false ) return;
55827  
55828			event.preventDefault();
55829  
55830		}
55831  
55832		//
55833  
55834		//scope.domElement.addEventListener\( 'contextmenu', onContextMenu, false );
55835  
55836		scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
55837		scope.domElement.addEventListener( 'wheel', onMouseWheel, false );
55838  
55839		scope.domElement.addEventListener( 'touchstart', onTouchStart, false );
55840		scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
55841		scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
55842  
55843		window.addEventListener( 'keydown', onKeyDown, false );
55844  
55845		// force an update at start
55846  
55847		this.update();
55848  
55849	};
55850  
55851	OrbitControls.prototype = Object.create( EventDispatcher.prototype );
55852	OrbitControls.prototype.constructor = OrbitControls;
55853  
55854	Object.defineProperties( OrbitControls.prototype, {
55855  
55856		center: {
55857  
55858			get: function () {
55859  
55860				console.warn( 'OrbitControls: .center has been renamed to .target' );
55861				return this.target;
55862  
55863			}
55864  
55865		},
55866  
55867		// backward compatibility
55868  
55869		noZoom: {
55870  
55871			get: function () {
55872  
55873				console.warn( 'OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
55874				return ! this.enableZoom;
55875  
55876			},
55877  
55878			set: function ( value ) {
55879  
55880				console.warn( 'OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
55881				this.enableZoom = ! value;
55882  
55883			}
55884  
55885		},
55886  
55887		noRotate: {
55888  
55889			get: function () {
55890  
55891				console.warn( 'OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
55892				return ! this.enableRotate;
55893  
55894			},
55895  
55896			set: function ( value ) {
55897  
55898				console.warn( 'OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
55899				this.enableRotate = ! value;
55900  
55901			}
55902  
55903		},
55904  
55905		noPan: {
55906  
55907			get: function () {
55908  
55909				console.warn( 'OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
55910				return ! this.enablePan;
55911  
55912			},
55913  
55914			set: function ( value ) {
55915  
55916				console.warn( 'OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
55917				this.enablePan = ! value;
55918  
55919			}
55920  
55921		},
55922  
55923		noKeys: {
55924  
55925			get: function () {
55926  
55927				console.warn( 'OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
55928				return ! this.enableKeys;
55929  
55930			},
55931  
55932			set: function ( value ) {
55933  
55934				console.warn( 'OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
55935				this.enableKeys = ! value;
55936  
55937			}
55938  
55939		},
55940  
55941		staticMoving: {
55942  
55943			get: function () {
55944  
55945				console.warn( 'OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
55946				return ! this.enableDamping;
55947  
55948			},
55949  
55950			set: function ( value ) {
55951  
55952				console.warn( 'OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
55953				this.enableDamping = ! value;
55954  
55955			}
55956  
55957		},
55958  
55959		dynamicDampingFactor: {
55960  
55961			get: function () {
55962  
55963				console.warn( 'OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
55964				return this.dampingFactor;
55965  
55966			},
55967  
55968			set: function ( value ) {
55969  
55970				console.warn( 'OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
55971				this.dampingFactor = value;
55972  
55973			}
55974  
55975		}
55976  
55977	} );
55978  
55979	/**
55980	 * @author richt / http://richt.me
55981	 * @author WestLangley / http://github.com/WestLangley
55982	 *
55983	 * W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
55984	 */
55985	var DeviceOrientationControls = function ( object ) {
55986  
55987		var scope = this;
55988  
55989		this.object = object;
55990		this.object.rotation.reorder( 'YXZ' );
55991  
55992		this.enabled = true;
55993  
55994		this.deviceOrientation = {};
55995		this.screenOrientation = 0;
55996  
55997		this.alphaOffset = 0; // radians
55998  
55999		var onDeviceOrientationChangeEvent = function ( event ) {
56000  
56001			scope.deviceOrientation = event;
56002  
56003		};
56004  
56005		var onScreenOrientationChangeEvent = function () {
56006  
56007			scope.screenOrientation = window.orientation || 0;
56008  
56009		};
56010  
56011		// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
56012  
56013		var setObjectQuaternion = function () {
56014  
56015			var zee = new Vector3( 0, 0, 1 );
56016  
56017			var euler = new Euler();
56018  
56019			var q0 = new Quaternion();
56020  
56021			var q1 = new Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
56022  
56023			return function ( quaternion, alpha, beta, gamma, orient ) {
56024  
56025				euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us
56026  
56027				quaternion.setFromEuler( euler ); // orient the device
56028  
56029				quaternion.multiply( q1 ); // camera looks out the back of the device, not the top
56030  
56031				quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation
56032  
56033			};
56034  
56035		}();
56036  
56037		this.connect = function () {
56038  
56039			onScreenOrientationChangeEvent(); // run once on load
56040  
56041			window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
56042			window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
56043  
56044			scope.enabled = true;
56045  
56046		};
56047  
56048		this.disconnect = function () {
56049  
56050			window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
56051			window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
56052  
56053			scope.enabled = false;
vendor: 1,895 bytes, lines 56054-56137
56054  
56055		};
56056  
56057		this.update = function () {
56058  
56059			if ( scope.enabled === false ) return;
56060  
56061			var device = scope.deviceOrientation;
56062  
56063			if ( device ) {
56064  
56065				var alpha = device.alpha ? _Math.degToRad( device.alpha ) + scope.alphaOffset : 0; // Z
56066  
56067				var beta = device.beta ? _Math.degToRad( device.beta ) : 0; // X'
56068  
56069				var gamma = device.gamma ? _Math.degToRad( device.gamma ) : 0; // Y''
56070  
56071				var orient = scope.screenOrientation ? _Math.degToRad( scope.screenOrientation ) : 0; // O
56072  
56073				setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient );
56074  
56075			}
56076  
56077  
56078		};
56079  
56080		this.dispose = function () {
56081  
56082			scope.disconnect();
56083  
56084		};
56085  
56086		this.connect();
56087  
56088	};
56089  
56090	/**
56091	 * Convert a quaternion to an angle
56092	 *
56093	 * Taken from https://stackoverflow.com/a/35448946
56094	 * Thanks P. Ellul
56095	 */
56096  
56097	function Quat2Angle(x, y, z, w) {
56098	  var test = x * y + z * w; // singularity at north pole
56099  
56100	  if (test > 0.499) {
56101		var _yaw = 2 * Math.atan2(x, w);
56102  
56103		var _pitch = Math.PI / 2;
56104  
56105		var _roll = 0;
56106		return new Vector3(_pitch, _roll, _yaw);
56107	  } // singularity at south pole
56108  
56109  
56110	  if (test < -0.499) {
56111		var _yaw2 = -2 * Math.atan2(x, w);
56112  
56113		var _pitch2 = -Math.PI / 2;
56114  
56115		var _roll2 = 0;
56116		return new Vector3(_pitch2, _roll2, _yaw2);
56117	  }
56118  
56119	  var sqx = x * x;
56120	  var sqy = y * y;
56121	  var sqz = z * z;
56122	  var yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
56123	  var pitch = Math.asin(2 * test);
56124	  var roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
56125	  return new Vector3(pitch, roll, yaw);
56126	}
56127  
56128	var OrbitOrientationControls =
56129	/*#__PURE__*/
56130	function () {
56131	  function OrbitOrientationControls(options) {
56132		this.object = options.camera;
56133		this.domElement = options.canvas;
56134		this.orbit = new OrbitControls(this.object, this.domElement);
56135		this.speed = 0.5;
56136		this.orbit.target.set(0, 0, -1);
56137		this.orbit.enableZoom = false;
56138		this.orbit.enablePan = false;
56139		this.orbit.rotateSpeed = -this.speed; // if orientation is supported
56140  
56141		if (options.orientation) {
56142		  this.orientation = new DeviceOrientationControls(this.object);
56143		} // if projection is not full view
56144		// limit the rotation angle in order to not display back half view
56145  
56146  
56147		if (options.halfView) {
56148		  this.orbit.minAzimuthAngle = -Math.PI / 4;
56149		  this.orbit.maxAzimuthAngle = Math.PI / 4;
56150		}
56151	  }
56152  
56153	  var _proto = OrbitOrientationControls.prototype;
56154  
56155	  _proto.update = function update() {
56156		// orientation updates the camera using quaternions and
56157		// orbit updates the camera using angles. They are incompatible
56158		// and one update overrides the other. So before
56159		// orbit overrides orientation we convert our quaternion changes to
56160		// an angle change. Then save the angle into orbit so that
56161		// it will take those into account when it updates the camera and overrides
56162		// our changes
56163		if (this.orientation) {
56164		  this.orientation.update();
56165		  var quat = this.orientation.object.quaternion;
56166		  var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); // we also have to store the last angle since quaternions are b
56167  
56168		  if (typeof this.lastAngle_ === 'undefined') {
56169			this.lastAngle_ = currentAngle;
56170		  }
56171  
56172		  this.orbit.rotateLeft((this.lastAngle_.z - currentAngle.z) * (1 + this.speed));
56173		  this.orbit.rotateUp((this.lastAngle_.y - currentAngle.y) * (1 + this.speed));
56174		  this.lastAngle_ = currentAngle;
56175		}
56176  
56177		this.orbit.update();
56178	  };
56179  
56180	  _proto.dispose = function dispose() {
56181		this.orbit.dispose();
56182  
56183		if (this.orientation) {
56184		  this.orientation.dispose();
56185		}
56186	  };
56187  
56188	  return OrbitOrientationControls;
56189	}();
56190  
56191	var corsSupport = function () {
56192	  var video = document$1.createElement('video');
56193	  video.crossOrigin = 'anonymous';
56194	  return video.hasAttribute('crossorigin');
56195	}();
56196	var validProjections = ['360', '360_LR', '360_TB', '360_CUBE', 'EAC', 'EAC_LR', 'NONE', 'AUTO', 'Sphere', 'Cube', 'equirectangular', '180', '180_LR', '180_MONO'];
56197	var getInternalProjectionName = function getInternalProjectionName(projection) {
56198	  if (!projection) {
56199		return;
56200	  }
56201  
56202	  projection = projection.toString().trim();
56203  
56204	  if (/sphere/i.test(projection)) {
56205		return '360';
56206	  }
56207  
56208	  if (/cube/i.test(projection)) {
56209		return '360_CUBE';
56210	  }
56211  
56212	  if (/equirectangular/i.test(projection)) {
56213		return '360';
56214	  }
56215  
56216	  for (var i = 0; i < validProjections.length; i++) {
56217		if (new RegExp('^' + validProjections[i] + '$', 'i').test(projection)) {
56218		  return validProjections[i];
56219		}
56220	  }
56221	};
56222  
56223	/**
56224	 * This class reacts to interactions with the canvas and
56225	 * triggers appropriate functionality on the player. Right now
56226	 * it does two things:
56227	 *
56228	 * 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any
56229	 *    `touchmove` or `mousemove` toggles play/pause on the player
56230	 * 2. Only moving on/clicking the control bar or toggling play/pause should
56231	 *    show the control bar. Moving around the scene in the canvas should not.
56232	 */
56233  
56234	var CanvasPlayerControls =
56235	/*#__PURE__*/
56236	function (_videojs$EventTarget) {
56237	  inheritsLoose(CanvasPlayerControls, _videojs$EventTarget);
56238  
56239	  function CanvasPlayerControls(player, canvas) {
56240		var _this;
56241  
56242		_this = _videojs$EventTarget.call(this) || this;
56243		_this.player = player;
56244		_this.canvas = canvas;
56245		_this.onMoveEnd = videojs.bind(assertThisInitialized(_this), _this.onMoveEnd);
56246		_this.onMoveStart = videojs.bind(assertThisInitialized(_this), _this.onMoveStart);
56247		_this.onMove = videojs.bind(assertThisInitialized(_this), _this.onMove);
56248		_this.onControlBarMove = videojs.bind(assertThisInitialized(_this), _this.onControlBarMove);
56249  
56250		_this.player.controlBar.on(['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend'], _this.onControlBarMove); // we have to override these here because
56251		// video.js listens for user activity on the video element
56252		// and makes the user active when the mouse moves.
56253		// We don't want that for 3d videos
56254  
56255  
56256		_this.oldReportUserActivity = _this.player.reportUserActivity;
56257  
56258		_this.player.reportUserActivity = function () {}; // canvas movements
56259  
56260  
56261		_this.canvas.addEventListener('mousedown', _this.onMoveStart);
56262  
56263		_this.canvas.addEventListener('touchstart', _this.onMoveStart);
56264  
56265		_this.canvas.addEventListener('mousemove', _this.onMove);
56266  
56267		_this.canvas.addEventListener('touchmove', _this.onMove);
56268  
56269		_this.canvas.addEventListener('mouseup', _this.onMoveEnd);
56270  
56271		_this.canvas.addEventListener('touchend', _this.onMoveEnd);
56272  
56273		_this.shouldTogglePlay = false;
56274		return _this;
56275	  }
56276  
56277	  var _proto = CanvasPlayerControls.prototype;
56278  
56279	  _proto.togglePlay = function togglePlay() {
56280		if (this.player.paused()) {
56281		  this.player.play();
56282		} else {
56283		  this.player.pause();
56284		}
56285	  };
56286  
56287	  _proto.onMoveStart = function onMoveStart(e) {
56288		// if the player does not have a controlbar or
56289		// the move was a mouse click but not left click do not
56290		// toggle play.
56291		if (!this.player.controls() || e.type === 'mousedown' && !videojs.dom.isSingleLeftClick(e)) {
56292		  this.shouldTogglePlay = false;
56293		  return;
56294		}
56295  
56296		this.shouldTogglePlay = true;
56297		this.touchMoveCount_ = 0;
56298	  };
56299  
56300	  _proto.onMoveEnd = function onMoveEnd(e) {
56301		// We want to have the same behavior in VR360 Player and standard player.
56302		// in touchend we want to know if was a touch click, for a click we show the bar,
56303		// otherwise continue with the mouse logic.
56304		//
56305		// Maximum movement allowed during a touch event to still be considered a tap
56306		// Other popular libs use anywhere from 2 (hammer.js) to 15,
56307		// so 10 seems like a nice, round number.
56308		if (e.type === 'touchend' && this.touchMoveCount_ < 10) {
56309		  if (this.player.userActive() === false) {
56310			this.player.userActive(true);
56311			return;
56312		  }
56313  
56314		  this.player.userActive(false);
56315		  return;
56316		}
56317  
56318		if (!this.shouldTogglePlay) {
56319		  return;
56320		} // We want the same behavior in Desktop for VR360  and standard player
56321  
56322  
56323		if (e.type == 'mouseup') {
56324		  this.togglePlay();
56325		}
56326	  };
56327  
56328	  _proto.onMove = function onMove(e) {
56329		// Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normally
56330		this.touchMoveCount_++;
56331		this.shouldTogglePlay = false;
56332	  };
56333  
56334	  _proto.onControlBarMove = function onControlBarMove(e) {
56335		this.player.userActive(true);
56336	  };
56337  
56338	  _proto.dispose = function dispose() {
56339		this.canvas.removeEventListener('mousedown', this.onMoveStart);
56340		this.canvas.removeEventListener('touchstart', this.onMoveStart);
56341		this.canvas.removeEventListener('mousemove', this.onMove);
56342		this.canvas.removeEventListener('touchmove', this.onMove);
56343		this.canvas.removeEventListener('mouseup', this.onMoveEnd);
56344		this.canvas.removeEventListener('touchend', this.onMoveEnd);
56345		this.player.controlBar.off(['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend'], this.onControlBarMove);
56346		this.player.reportUserActivity = this.oldReportUserActivity;
56347	  };
56348  
56349	  return CanvasPlayerControls;
56350	}(videojs.EventTarget);
56351  
56352	/**
56353	 * This class manages ambisonic decoding and binaural rendering via Omnitone library.
56354	 */
56355  
56356	var OmnitoneController =
56357	/*#__PURE__*/
56358	function (_videojs$EventTarget) {
56359	  inheritsLoose(OmnitoneController, _videojs$EventTarget);
56360  
56361	  /**
56362	   * Omnitone controller class.
56363	   *
56364	   * @class
56365	   * @param {AudioContext} audioContext - associated AudioContext.
56366	   * @param {Omnitone library} omnitone - Omnitone library element.
56367	   * @param {HTMLVideoElement} video - vidoe tag element.
56368	   * @param {Object} options - omnitone options.
56369	   */
56370	  function OmnitoneController(audioContext, omnitone, video, options) {
56371		var _this;
56372  
56373		_this = _videojs$EventTarget.call(this) || this;
56374		var settings = videojs.mergeOptions({
56375		  // Safari uses the different AAC decoder than FFMPEG. The channel order is
56376		  // The default 4ch AAC channel layout for FFMPEG AAC channel ordering.
56377		  channelMap: videojs.browser.IS_SAFARI ? [2, 0, 1, 3] : [0, 1, 2, 3],
56378		  ambisonicOrder: 1
56379		}, options);
56380		_this.videoElementSource = audioContext.createMediaElementSource(video);
56381		_this.foaRenderer = omnitone.createFOARenderer(audioContext, settings);
56382  
56383		_this.foaRenderer.initialize().then(function () {
56384		  if (audioContext.state === 'suspended') {
56385			_this.trigger({
56386			  type: 'audiocontext-suspended'
56387			});
56388		  }
56389  
56390		  _this.videoElementSource.connect(_this.foaRenderer.input);
56391  
56392		  _this.foaRenderer.output.connect(audioContext.destination);
56393  
56394		  _this.initialized = true;
56395  
56396		  _this.trigger({
56397			type: 'omnitone-ready'
56398		  });
56399		}, function (error) {
56400		  videojs.log.warn("videojs-vr: Omnitone initializes failed with the following error: " + error + ")");
56401		});
56402  
56403		return _this;
56404	  }
56405	  /**
56406	   * Updates the rotation of the Omnitone decoder based on three.js camera matrix.
56407	   *
56408	   * @param {Camera} camera Three.js camera object
56409	   */
56410  
56411  
56412	  var _proto = OmnitoneController.prototype;
56413  
56414	  _proto.update = function update(camera) {
56415		if (!this.initialized) {
56416		  return;
56417		}
56418  
56419		this.foaRenderer.setRotationMatrixFromCamera(camera.matrix);
56420	  }
56421	  /**
56422	   * Destroys the controller and does any necessary cleanup.
56423	   */
56424	  ;
56425  
56426	  _proto.dispose = function dispose() {
56427		this.initialized = false;
56428		this.foaRenderer.setRenderingMode('bypass');
56429		this.foaRenderer = null;
56430	  };
56431  
56432	  return OmnitoneController;
56433	}(videojs.EventTarget);
56434  
56435	var Button = videojs.getComponent('Button');
56436  
56437	var CardboardButton =
56438	/*#__PURE__*/
56439	function (_Button) {
56440	  inheritsLoose(CardboardButton, _Button);
56441  
56442	  function CardboardButton(player, options) {
56443		var _this;
56444  
56445		_this = _Button.call(this, player, options) || this;
56446		_this.handleVrDisplayActivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayActivate_);
56447		_this.handleVrDisplayDeactivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayDeactivate_);
56448		_this.handleVrDisplayPresentChange_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayPresentChange_);
56449		_this.handleOrientationChange_ = videojs.bind(assertThisInitialized(_this), _this.handleOrientationChange_);
56450		window$1.addEventListener('orientationchange', _this.handleOrientationChange_);
56451		window$1.addEventListener('vrdisplayactivate', _this.handleVrDisplayActivate_);
56452		window$1.addEventListener('vrdisplaydeactivate', _this.handleVrDisplayDeactivate_); // vrdisplaypresentchange does not fire activate or deactivate
56453		// and happens when hitting the back button during cardboard mode
56454		// so we need to make sure we stay in the correct state by
56455		// listening to it and checking if we are presenting it or not
56456  
56457		window$1.addEventListener('vrdisplaypresentchange', _this.handleVrDisplayPresentChange_); // we cannot show the cardboard button in fullscreen on
56458		// android as it breaks the controls, and makes it impossible
56459		// to exit cardboard mode
56460  
56461		if (videojs.browser.IS_ANDROID) {
56462		  _this.on(player, 'fullscreenchange', function () {
56463			if (player.isFullscreen()) {
56464			  _this.hide();
56465			} else {
56466			  _this.show();
56467			}
56468		  });
56469		}
56470  
56471		return _this;
56472	  }
56473  
56474	  var _proto = CardboardButton.prototype;
56475  
56476	  _proto.buildCSSClass = function buildCSSClass() {
56477		return "vjs-button-vr " + _Button.prototype.buildCSSClass.call(this);
56478	  };
56479  
56480	  _proto.handleVrDisplayPresentChange_ = function handleVrDisplayPresentChange_() {
56481		if (!this.player_.vr().vrDisplay.isPresenting && this.active_) {
56482		  this.handleVrDisplayDeactivate_();
56483		}
56484  
56485		if (this.player_.vr().vrDisplay.isPresenting && !this.active_) {
56486		  this.handleVrDisplayActivate_();
56487		}
56488	  };
56489  
56490	  _proto.handleOrientationChange_ = function handleOrientationChange_() {
56491		if (this.active_ && videojs.browser.IS_IOS) {
56492		  this.changeSize_();
56493		}
56494	  };
56495  
56496	  _proto.changeSize_ = function changeSize_() {
56497		this.player_.width(window$1.innerWidth);
56498		this.player_.height(window$1.innerHeight);
56499		window$1.dispatchEvent(new window$1.Event('resize'));
56500	  };
56501  
56502	  _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() {
56503		// we mimic fullscreen on IOS
56504		if (videojs.browser.IS_IOS) {
56505		  this.oldWidth_ = this.player_.currentWidth();
56506		  this.oldHeight_ = this.player_.currentHeight();
56507		  this.player_.enterFullWindow();
56508		  this.changeSize_();
56509		}
56510  
56511		this.active_ = true;
56512	  };
56513  
56514	  _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() {
56515		// un-mimic fullscreen on iOS
56516		if (videojs.browser.IS_IOS) {
56517		  if (this.oldWidth_) {
56518			this.player_.width(this.oldWidth_);
56519		  }
56520  
56521		  if (this.oldHeight_) {
56522			this.player_.height(this.oldHeight_);
56523		  }
56524  
56525		  this.player_.exitFullWindow();
56526		}
56527  
56528		this.active_ = false;
56529	  };
56530  
56531	  _proto.handleClick = function handleClick(event) {
56532		// if cardboard mode display is not active, activate it
56533		// otherwise deactivate it
56534		if (!this.active_) {
56535		  // This starts playback mode when the cardboard button
56536		  // is clicked on Android. We need to do this as the controls
56537		  // disappear
56538		  if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) {
56539			this.player_.play();
56540		  }
56541  
56542		  window$1.dispatchEvent(new window$1.Event('vrdisplayactivate'));
56543		} else {
56544		  window$1.dispatchEvent(new window$1.Event('vrdisplaydeactivate'));
56545		}
56546	  };
56547  
56548	  _proto.dispose = function dispose() {
56549		_Button.prototype.dispose.call(this);
56550  
56551		window$1.removeEventListener('vrdisplayactivate', this.handleVrDisplayActivate_);
56552		window$1.removeEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_);
56553		window$1.removeEventListener('vrdisplaypresentchange', this.handleVrDisplayPresentChange_);
56554	  };
56555  
56556	  return CardboardButton;
56557	}(Button);
56558  
56559	videojs.registerComponent('CardboardButton', CardboardButton);
56560  
56561	var BigPlayButton = videojs.getComponent('BigPlayButton');
56562  
56563	var BigVrPlayButton =
56564	/*#__PURE__*/
56565	function (_BigPlayButton) {
56566	  inheritsLoose(BigVrPlayButton, _BigPlayButton);
56567  
56568	  function BigVrPlayButton() {
56569		return _BigPlayButton.apply(this, arguments) || this;
56570	  }
56571  
56572	  var _proto = BigVrPlayButton.prototype;
56573  
56574	  _proto.buildCSSClass = function buildCSSClass() {
56575		return "vjs-big-vr-play-button " + _BigPlayButton.prototype.buildCSSClass.call(this);
56576	  };
56577  
56578	  return BigVrPlayButton;
56579	}(BigPlayButton);
56580  
56581	videojs.registerComponent('BigVrPlayButton', BigVrPlayButton);
56582  
56583	var defaults = {
56584	  debug: false,
56585	  omnitone: false,
56586	  forceCardboard: false,
56587	  omnitoneOptions: {},
56588	  projection: 'AUTO',
56589	  sphereDetail: 32
56590	};
56591	var errors = {
56592	  'web-vr-out-of-date': {
56593		headline: '360 is out of date',
56594		type: '360_OUT_OF_DATE',
56595		message: "Your browser supports 360 but not the latest version. See <a href='http://webvr.info'>http://webvr.info</a> for more info."
56596	  },
56597	  'web-vr-not-supported': {
56598		headline: '360 not supported on this device',
56599		type: '360_NOT_SUPPORTED',
56600		message: "Your browser does not support 360. See <a href='http://webvr.info'>http://webvr.info</a> for assistance."
56601	  },
56602	  'web-vr-hls-cors-not-supported': {
56603		headline: '360 HLS video not supported on this device',
56604		type: '360_NOT_SUPPORTED',
56605		message: "Your browser/device does not support HLS 360 video. See <a href='http://webvr.info'>http://webvr.info</a> for assistance."
56606	  }
56607	};
56608	var Plugin = videojs.getPlugin('plugin');
56609	var Component = videojs.getComponent('Component');
56610  
56611	var VR =
56612	/*#__PURE__*/
56613	function (_Plugin) {
56614	  inheritsLoose(VR, _Plugin);
56615  
56616	  function VR(player, options) {
56617		var _this;
56618  
56619		var settings = videojs.mergeOptions(defaults, options);
56620		_this = _Plugin.call(this, player, settings) || this;
56621		_this.options_ = settings;
56622		_this.player_ = player;
56623		_this.bigPlayButtonIndex_ = player.children().indexOf(player.getChild('BigPlayButton')) || 0; // custom videojs-errors integration boolean
56624  
56625		_this.videojsErrorsSupport_ = !!videojs.errors;
56626  
56627		if (_this.videojsErrorsSupport_) {
56628		  player.errors({
56629			errors: errors
56630		  });
56631		} // IE 11 does not support enough webgl to be supported
56632		// older safari does not support cors, so it wont work
56633  
56634  
56635		if (videojs.browser.IE_VERSION || !corsSupport) {
56636		  // if a player triggers error before 'loadstart' is fired
56637		  // video.js will reset the error overlay
56638		  _this.player_.on('loadstart', function () {
56639			_this.triggerError_({
56640			  code: 'web-vr-not-supported',
56641			  dismiss: false
56642			});
56643		  });
56644  
56645		  return assertThisInitialized(_this);
56646		}
56647  
56648		_this.polyfill_ = new WebVRPolyfill({
56649		  // do not show rotate instructions
56650		  ROTATE_INSTRUCTIONS_DISABLED: true
56651		});
56652		_this.polyfill_ = new WebVRPolyfill();
56653		_this.handleVrDisplayActivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayActivate_);
56654		_this.handleVrDisplayDeactivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayDeactivate_);
56655		_this.handleResize_ = videojs.bind(assertThisInitialized(_this), _this.handleResize_);
56656		_this.animate_ = videojs.bind(assertThisInitialized(_this), _this.animate_);
56657  
56658		_this.setProjection(_this.options_.projection); // any time the video element is recycled for ads
56659		// we have to reset the vr state and re-init after ad
56660  
56661  
56662		_this.on(player, 'adstart', function () {
56663		  return player.setTimeout(function () {
56664			// if the video element was recycled for this ad
56665			if (!player.ads || !player.ads.videoElementRecycled()) {
56666			  _this.log('video element not recycled for this ad, no need to reset');
56667  
56668			  return;
56669			}
56670  
56671			_this.log('video element recycled for this ad, reseting');
56672  
56673			_this.reset();
56674  
56675			_this.one(player, 'playing', _this.init);
56676		  });
56677		}, 1);
56678  
56679		_this.on(player, 'loadedmetadata', _this.init);
56680  
56681		return _this;
56682	  }
56683  
56684	  var _proto = VR.prototype;
56685  
56686	  _proto.changeProjection_ = function changeProjection_(projection) {
56687		var _this2 = this;
56688  
56689		projection = getInternalProjectionName(projection); // don't change to an invalid projection
56690  
56691		if (!projection) {
56692		  projection = 'NONE';
56693		}
56694  
56695		var position = {
56696		  x: 0,
56697		  y: 0,
56698		  z: 0
56699		};
56700  
56701		if (this.scene) {
56702		  this.scene.remove(this.movieScreen);
56703		}
56704  
56705		if (projection === 'AUTO') {
56706		  // mediainfo cannot be set to auto or we would infinite loop here
56707		  // each source should know whatever they are 360 or not, if using AUTO
56708		  if (this.player_.mediainfo && this.player_.mediainfo.projection && this.player_.mediainfo.projection !== 'AUTO') {
56709			var autoProjection = getInternalProjectionName(this.player_.mediainfo.projection);
56710			return this.changeProjection_(autoProjection);
56711		  }
56712  
56713		  return this.changeProjection_('NONE');
56714		} else if (projection === '360') {
56715		  this.movieGeometry = new SphereBufferGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail);
56716		  this.movieMaterial = new MeshBasicMaterial({
56717			map: this.videoTexture,
56718			overdraw: true,
56719			side: BackSide
56720		  });
56721		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial);
56722		  this.movieScreen.position.set(position.x, position.y, position.z);
56723		  this.movieScreen.scale.x = -1;
56724		  this.movieScreen.quaternion.setFromAxisAngle({
56725			x: 0,
56726			y: 1,
56727			z: 0
56728		  }, -Math.PI / 2);
56729		  this.scene.add(this.movieScreen);
56730		} else if (projection === '360_LR' || projection === '360_TB') {
56731		  // Left eye view
56732		  var geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail);
56733		  var uvs = geometry.faceVertexUvs[0];
56734  
56735		  for (var i = 0; i < uvs.length; i++) {
56736			for (var j = 0; j < 3; j++) {
56737			  if (projection === '360_LR') {
56738				uvs[i][j].x *= 0.5;
56739			  } else {
56740				uvs[i][j].y *= 0.5;
56741				uvs[i][j].y += 0.5;
56742			  }
56743			}
56744		  }
56745  
56746		  this.movieGeometry = new BufferGeometry().fromGeometry(geometry);
56747		  this.movieMaterial = new MeshBasicMaterial({
56748			map: this.videoTexture,
56749			overdraw: true,
56750			side: BackSide
56751		  });
56752		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial);
56753		  this.movieScreen.scale.x = -1;
56754		  this.movieScreen.quaternion.setFromAxisAngle({
56755			x: 0,
56756			y: 1,
56757			z: 0
56758		  }, -Math.PI / 2); // display in left eye only
56759  
56760		  this.movieScreen.layers.set(1);
56761		  this.scene.add(this.movieScreen); // Right eye view
56762  
56763		  geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail);
56764		  uvs = geometry.faceVertexUvs[0];
56765  
56766		  for (var _i = 0; _i < uvs.length; _i++) {
56767			for (var _j = 0; _j < 3; _j++) {
56768			  if (projection === '360_LR') {
56769				uvs[_i][_j].x *= 0.5;
56770				uvs[_i][_j].x += 0.5;
56771			  } else {
56772				uvs[_i][_j].y *= 0.5;
56773			  }
56774			}
56775		  }
56776  
56777		  this.movieGeometry = new BufferGeometry().fromGeometry(geometry);
56778		  this.movieMaterial = new MeshBasicMaterial({
56779			map: this.videoTexture,
56780			overdraw: true,
56781			side: BackSide
56782		  });
56783		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial);
56784		  this.movieScreen.scale.x = -1;
56785		  this.movieScreen.quaternion.setFromAxisAngle({
56786			x: 0,
56787			y: 1,
56788			z: 0
56789		  }, -Math.PI / 2); // display in right eye only
56790  
56791		  this.movieScreen.layers.set(2);
56792		  this.scene.add(this.movieScreen);
56793		} else if (projection === '360_CUBE') {
56794		  this.movieGeometry = new BoxGeometry(256, 256, 256);
56795		  this.movieMaterial = new MeshBasicMaterial({
56796			map: this.videoTexture,
56797			overdraw: true,
56798			side: BackSide
56799		  });
56800		  var left = [new Vector2(0, 0.5), new Vector2(0.333, 0.5), new Vector2(0.333, 1), new Vector2(0, 1)];
56801		  var right = [new Vector2(0.333, 0.5), new Vector2(0.666, 0.5), new Vector2(0.666, 1), new Vector2(0.333, 1)];
56802		  var top = [new Vector2(0.666, 0.5), new Vector2(1, 0.5), new Vector2(1, 1), new Vector2(0.666, 1)];
56803		  var bottom = [new Vector2(0, 0), new Vector2(0.333, 0), new Vector2(0.333, 0.5), new Vector2(0, 0.5)];
56804		  var front = [new Vector2(0.333, 0), new Vector2(0.666, 0), new Vector2(0.666, 0.5), new Vector2(0.333, 0.5)];
56805		  var back = [new Vector2(0.666, 0), new Vector2(1, 0), new Vector2(1, 0.5), new Vector2(0.666, 0.5)];
56806		  this.movieGeometry.faceVertexUvs[0] = [];
56807		  this.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]];
56808		  this.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]];
56809		  this.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]];
56810		  this.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]];
56811		  this.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]];
56812		  this.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]];
56813		  this.movieGeometry.faceVertexUvs[0][6] = [bottom[2], bottom[1], bottom[3]];
56814		  this.movieGeometry.faceVertexUvs[0][7] = [bottom[1], bottom[0], bottom[3]];
56815		  this.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]];
56816		  this.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]];
56817		  this.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]];
56818		  this.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]];
56819		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial);
56820		  this.movieScreen.position.set(position.x, position.y, position.z);
56821		  this.movieScreen.rotation.y = -Math.PI;
56822		  this.scene.add(this.movieScreen);
56823		} else if (projection === '180' || projection === '180_LR' || projection === '180_MONO') {
56824		  var _geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail, Math.PI, Math.PI); // Left eye view
56825  
56826  
56827		  _geometry.scale(-1, 1, 1);
56828  
56829		  var _uvs = _geometry.faceVertexUvs[0];
56830  
56831		  if (projection !== '180_MONO') {
56832			for (var _i2 = 0; _i2 < _uvs.length; _i2++) {
56833			  for (var _j2 = 0; _j2 < 3; _j2++) {
56834				_uvs[_i2][_j2].x *= 0.5;
56835			  }
56836			}
56837		  }
56838  
56839		  this.movieGeometry = new BufferGeometry().fromGeometry(_geometry);
56840		  this.movieMaterial = new MeshBasicMaterial({
56841			map: this.videoTexture,
56842			overdraw: true
56843		  });
56844		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in left eye only
56845  
56846		  this.movieScreen.layers.set(1);
56847		  this.scene.add(this.movieScreen); // Right eye view
56848  
56849		  _geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail, Math.PI, Math.PI);
56850  
56851		  _geometry.scale(-1, 1, 1);
56852  
56853		  _uvs = _geometry.faceVertexUvs[0];
56854  
56855		  for (var _i3 = 0; _i3 < _uvs.length; _i3++) {
56856			for (var _j3 = 0; _j3 < 3; _j3++) {
56857			  _uvs[_i3][_j3].x *= 0.5;
56858			  _uvs[_i3][_j3].x += 0.5;
56859			}
56860		  }
56861  
56862		  this.movieGeometry = new BufferGeometry().fromGeometry(_geometry);
56863		  this.movieMaterial = new MeshBasicMaterial({
56864			map: this.videoTexture,
56865			overdraw: true
56866		  });
56867		  this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in right eye only
56868  
56869		  this.movieScreen.layers.set(2);
56870		  this.scene.add(this.movieScreen);
56871		} else if (projection === 'EAC' || projection === 'EAC_LR') {
56872		  var makeScreen = function makeScreen(mapMatrix, scaleMatrix) {
56873			// "Continuity correction?": because of discontinuous faces and aliasing,
56874			// we truncate the 2-pixel-wide strips on all discontinuous edges,
56875			var contCorrect = 2;
56876			_this2.movieGeometry = new BoxGeometry(256, 256, 256);
56877			_this2.movieMaterial = new ShaderMaterial({
56878			  overdraw: true,
56879			  side: BackSide,
56880			  uniforms: {
56881				mapped: {
56882				  value: _this2.videoTexture
56883				},
56884				mapMatrix: {
56885				  value: mapMatrix
56886				},
56887				contCorrect: {
56888				  value: contCorrect
56889				},
56890				faceWH: {
56891				  value: new Vector2(1 / 3, 1 / 2).applyMatrix3(scaleMatrix)
56892				},
56893				vidWH: {
56894				  value: new Vector2(_this2.videoTexture.image.videoWidth, _this2.videoTexture.image.videoHeight).applyMatrix3(scaleMatrix)
56895				}
56896			  },
56897			  vertexShader: "\nvarying vec2 vUv;\nuniform mat3 mapMatrix;\n\nvoid main() {\n  vUv = (mapMatrix * vec3(uv, 1.)).xy;\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n}",
56898			  fragmentShader: "\nvarying vec2 vUv;\nuniform sampler2D mapped;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\nuniform float contCorrect;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n  vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, c
56898ontCorrect / vidWH.y);\n\n  vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n\n  vec2 p = (vUv - corner) / faceWHadj - .5;\n  vec2 q = 2. / PI * atan(2. * p) + .5;\n\n  vec2 eUv = corner + q * faceWHadj;\n\n  gl_FragColor = texture2D(mapped, eUv);\n}"
56899			});
56900			var right = [new Vector2(0, 1 / 2), new Vector2(1 / 3, 1 / 2), new Vector2(1 / 3, 1), new Vector2(0, 1)];
56901			var front = [new Vector2(1 / 3, 1 / 2), new Vector2(2 / 3, 1 / 2), new Vector2(2 / 3, 1), new Vector2(1 / 3, 1)];
56902			var left = [new Vector2(2 / 3, 1 / 2), new Vector2(1, 1 / 2), new Vector2(1, 1), new Vector2(2 / 3, 1)];
56903			var bottom = [new Vector2(1 / 3, 0), new Vector2(1 / 3, 1 / 2), new Vector2(0, 1 / 2), new Vector2(0, 0)];
56904			var back = [new Vector2(1 / 3, 1 / 2), new Vector2(1 / 3, 0), new Vector2(2 / 3, 0), new Vector2(2 / 3, 1 / 2)];
56905			var top = [new Vector2(1, 0), new Vector2(1, 1 / 2), new Vector2(2 / 3, 1 / 2), new Vector2(2 / 3, 0)];
56906  
56907			for (var _i4 = 0, _arr = [right, front, left, bottom, back, top]; _i4 < _arr.length; _i4++) {
56908			  var face = _arr[_i4];
56909			  var height = _this2.videoTexture.image.videoHeight;
56910			  var lowY = 1;
56911			  var highY = 0;
56912  
56913			  for (var _iterator = face, _isArray = Array.isArray(_iterator), _i5 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
56914				var _ref;
56915  
56916				if (_isArray) {
56917				  if (_i5 >= _iterator.length) break;
56918				  _ref = _iterator[_i5++];
56919				} else {
56920				  _i5 = _iterator.next();
56921				  if (_i5.done) break;
56922				  _ref = _i5.value;
56923				}
56924  
56925				var vector = _ref;
56926  
56927				if (vector.y < lowY) {
56928				  lowY = vector.y;
56929				}
56930  
56931				if (vector.y > highY) {
56932				  highY = vector.y;
56933				}
56934			  }
56935  
56936			  for (var _iterator2 = face, _isArray2 = Array.isArray(_iterator2), _i6 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
56937				var _ref2;
56938  
56939				if (_isArray2) {
56940				  if (_i6 >= _iterator2.length) break;
56941				  _ref2 = _iterator2[_i6++];
56942				} else {
56943				  _i6 = _iterator2.next();
56944				  if (_i6.done) break;
56945				  _ref2 = _i6.value;
56946				}
56947  
56948				var _vector = _ref2;
56949  
56950				if (Math.abs(_vector.y - lowY) < Number.EPSILON) {
56951				  _vector.y += contCorrect / height;
56952				}
56953  
56954				if (Math.abs(_vector.y - highY) < Number.EPSILON) {
56955				  _vector.y -= contCorrect / height;
56956				}
56957  
56958				_vector.x = _vector.x / height * (height - contCorrect * 2) + contCorrect / height;
56959			  }
56960			}
56961  
56962			_this2.movieGeometry.faceVertexUvs[0] = [];
56963			_this2.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]];
56964			_this2.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]];
56965			_this2.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]];
56966			_this2.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]];
56967			_this2.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]];
56968			_this2.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]];
56969			_this2.movieGeometry.faceVertexUvs[0][6] = [bottom[2], bottom[1], bottom[3]];
56970			_this2.movieGeometry.faceVertexUvs[0][7] = [bottom[1], bottom[0], bottom[3]];
56971			_this2.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]];
56972			_this2.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]];
56973			_this2.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]];
56974			_this2.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]];
56975			_this2.movieScreen = new Mesh(_this2.movieGeometry, _this2.movieMaterial);
56976  
56977			_this2.movieScreen.position.set(position.x, position.y, position.z);
56978  
56979			_this2.movieScreen.rotation.y = -Math.PI;
56980			return _this2.movieScreen;
56981		  };
56982  
56983		  if (projection === 'EAC') {
56984			this.scene.add(makeScreen(new Matrix3(), new Matrix3()));
56985		  } else {
56986			var scaleMatrix = new Matrix3().set(0, 0.5, 0, 1, 0, 0, 0, 0, 1);
56987			makeScreen(new Matrix3().set(0, -0.5, 0.5, 1, 0, 0, 0, 0, 1), scaleMatrix); // display in left eye only
56988  
56989			this.movieScreen.layers.set(1);
56990			this.scene.add(this.movieScreen);
56991			makeScreen(new Matrix3().set(0, -0.5, 1, 1, 0, 0, 0, 0, 1), scaleMatrix); // display in right eye only
56992  
56993			this.movieScreen.layers.set(2);
56994			this.scene.add(this.movieScreen);
56995		  }
56996		}
56997  
56998		this.currentProjection_ = projection;
56999	  };
57000  
57001	  _proto.triggerError_ = function triggerError_(errorObj) {
57002		// if we have videojs-errors use it
57003		if (this.videojsErrorsSupport_) {
57004		  this.player_.error(errorObj); // if we don't have videojs-errors just use a normal player error
57005		} else {
57006		  // strip any html content from the error message
57007		  // as it is not supported outside of videojs-errors
57008		  var div = document$1.createElement('div');
57009		  div.innerHTML = errors[errorObj.code].message;
57010		  var message = div.textContent || div.innerText || '';
57011		  this.player_.error({
57012			code: errorObj.code,
57013			message: message
57014		  });
57015		}
57016	  };
57017  
57018	  _proto.log = function log() {
57019		if (!this.options_.debug) {
57020		  return;
57021		}
57022  
57023		for (var _len = arguments.length, msgs = new Array(_len), _key = 0; _key < _len; _key++) {
57024		  msgs[_key] = arguments[_key];
57025		}
57026  
57027		msgs.forEach(function (msg) {
57028		  videojs.log('VR: ', msg);
57029		});
57030	  };
57031  
57032	  _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() {
57033		var _this3 = this;
57034  
57035		if (!this.vrDisplay) {
57036		  return;
57037		}
57038  
57039		this.vrDisplay.requestPresent([{
57040		  source: this.renderedCanvas
57041		}]).then(function () {
57042		  if (!_this3.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) {
57043			return;
57044		  } // webvr-polyfill/cardboard ui only watches for click events
57045		  // to tell that the back arrow button is pressed during cardboard vr.
57046		  // but somewhere along the line these events are silenced with preventDefault
57047		  // but only on iOS, so we translate them ourselves here
57048  
57049  
57050		  var touches = [];
57051  
57052		  var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) {
57053			for (var i = 0; i < e.touches.length; i++) {
57054			  touches.push(e.touches[i]);
57055			}
57056		  };
57057  
57058		  var iosCardboardTouchEnd_ = function iosCardboardTouchEnd_(e) {
57059			if (!touches.length) {
57060			  return;
57061			}
57062  
57063			touches.forEach(function (t) {
57064			  var simulatedClick = new window$1.MouseEvent('click', {
57065				screenX: t.screenX,
57066				screenY: t.screenY,
57067				clientX: t.clientX,
57068				clientY: t.clientY
57069			  });
57070  
57071			  _this3.renderedCanvas.dispatchEvent(simulatedClick);
57072			});
57073			touches = [];
57074		  };
57075  
57076		  _this3.renderedCanvas.addEventListener('touchstart', iosCardboardTouchStart_);
57077  
57078		  _this3.renderedCanvas.addEventListener('touchend', iosCardboardTouchEnd_);
57079  
57080		  _this3.iosRevertTouchToClick_ = function () {
57081			_this3.renderedCanvas.removeEventListener('touchstart', iosCardboardTouchStart_);
57082  
57083			_this3.renderedCanvas.removeEventListener('touchend', iosCardboardTouchEnd_);
57084  
57085			_this3.iosRevertTouchToClick_ = null;
57086		  };
57087		});
57088	  };
57089  
57090	  _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() {
57091		if (!this.vrDisplay || !this.vrDisplay.isPresenting) {
57092		  return;
57093		}
57094  
57095		if (this.iosRevertTouchToClick_) {
57096		  this.iosRevertTouchToClick_();
57097		}
57098  
57099		this.vrDisplay.exitPresent();
57100	  };
57101  
57102	  _proto.requestAnimationFrame = function requestAnimationFrame(fn) {
57103		if (this.vrDisplay) {
57104		  return this.vrDisplay.requestAnimationFrame(fn);
57105		}
57106  
57107		return this.player_.requestAnimationFrame(fn);
57108	  };
57109  
57110	  _proto.cancelAnimationFrame = function cancelAnimationFrame(id) {
57111		if (this.vrDisplay) {
57112		  return this.vrDisplay.cancelAnimationFrame(id);
57113		}
57114  
57115		return this.player_.cancelAnimationFrame(id);
57116	  };
57117  
57118	  _proto.togglePlay_ = function togglePlay_() {
57119		if (this.player_.paused()) {
57120		  this.player_.play();
57121		} else {
57122		  this.player_.pause();
57123		}
57124	  };
57125  
57126	  _proto.animate_ = function animate_() {
57127		if (!this.initialized_) {
57128		  return;
57129		}
57130  
57131		if (this.getVideoEl_().readyState === this.getVideoEl_().HAVE_ENOUGH_DATA) {
57132		  if (this.videoTexture) {
57133			this.videoTexture.needsUpdate = true;
57134		  }
57135		}
57136  
57137		this.controls3d.update();
57138  
57139		if (this.omniController) {
57140		  this.omniController.update(this.camera);
57141		}
57142  
57143		this.effect.render(this.scene, this.camera);
57144  
57145		if (window$1.navigator.getGamepads) {
57146		  // Grab all gamepads
57147		  var gamepads = window$1.navigator.getGamepads();
57148  
57149		  for (var i = 0; i < gamepads.length; ++i) {
57150			var gamepad = gamepads[i]; // Make sure gamepad is defined
57151			// Only take input if state has changed since we checked last
57152  
57153			if (!gamepad || !gamepad.timestamp || gamepad.timestamp === this.prevTimestamps_[i]) {
57154			  continue;
57155			}
57156  
57157			for (var j = 0; j < gamepad.buttons.length; ++j) {
57158			  if (gamepad.buttons[j].pressed) {
57159				this.togglePlay_();
57160				this.prevTimestamps_[i] = gamepad.timestamp;
57161				break;
57162			  }
57163			}
57164		  }
57165		}
57166  
57167		this.camera.getWorldDirection(this.cameraVector);
57168		this.animationFrameId_ = this.requestAnimationFrame(this.animate_);
57169	  };
57170  
57171	  _proto.handleResize_ = function handleResize_() {
57172		var width = this.player_.currentWidth();
57173		var height = this.player_.currentHeight();
57174		this.effect.setSize(width, height, false);
57175		this.camera.aspect = width / height;
57176		this.camera.updateProjectionMatrix();
57177	  };
57178  
57179	  _proto.setProjection = function setProjection(projection) {
57180		if (!getInternalProjectionName(projection)) {
57181		  videojs.log.error('videojs-vr: please pass a valid projection ' + validProjections.join(', '));
57182		  return;
57183		}
57184  
57185		this.currentProjection_ = projection;
57186		this.defaultProjection_ = projection;
57187	  };
57188  
57189	  _proto.init = function init() {
57190		var _this4 = this;
57191  
57192		this.reset();
57193		this.camera = new PerspectiveCamera(75, this.player_.currentWidth() / this.player_.currentHeight(), 1, 1000); // Store vector representing the direction in which the camera is looking, in world space.
57194  
57195		this.cameraVector = new Vector3();
57196  
57197		if (this.currentProjection_ === '360_LR' || this.currentProjection_ === '360_TB' || this.currentProjection_ === '180' || this.currentProjection_ === '180_LR' || this.currentProjection_ === '180_MONO' || this.currentProjection_ === 'EAC_LR') {
57198		  // Render left eye when not in VR mode
57199		  this.camera.layers.enable(1);
57200		}
57201  
57202		this.scene = new Scene();
57203		this.videoTexture = new VideoTexture(this.getVideoEl_()); // shared regardless of wether VideoTexture is used or
57204		// an image canvas is used
57205  
57206		this.videoTexture.generateMipmaps = false;
57207		this.videoTexture.minFilter = LinearFilter;
57208		this.videoTexture.magFilter = LinearFilter;
57209		this.videoTexture.format = RGBFormat;
57210		this.changeProjection_(this.currentProjection_);
57211  
57212		if (this.currentProjection_ === 'NONE') {
57213		  this.log('Projection is NONE, dont init');
57214		  this.reset();
57215		  return;
57216		}
57217  
57218		this.player_.removeChild('BigPlayButton');
57219		this.player_.addChild('BigVrPlayButton', {}, this.bigPlayButtonIndex_);
57220		this.player_.bigPlayButton = this.player_.getChild('BigVrPlayButton'); // mobile devices, or cardboard forced to on
57221  
57222		if (this.options_.forceCardboard || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {
57223		  this.addCardboardButton_();
57224		} // if ios remove full screen toggle
57225  
57226  
57227		if (videojs.browser.IS_IOS && this.player_.controlBar && this.player_.controlBar.fullscreenToggle) {
57228		  this.player_.controlBar.fullscreenToggle.hide();
57229		}
57230  
57231		this.camera.position.set(0, 0, 0);
57232		this.renderer = new WebGLRenderer({
57233		  devicePixelRatio: window$1.devicePixelRatio,
57234		  alpha: false,
57235		  clearColor: 0xffffff,
57236		  antialias: true
57237		});
57238		var webglContext = this.renderer.getContext('webgl');
57239		var oldTexImage2D = webglContext.texImage2D;
57240		/* this is a workaround since threejs uses try catch */
57241  
57242		webglContext.texImage2D = function () {
57243		  try {
57244			for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
57245			  args[_key2] = arguments[_key2];
57246			}
57247  
57248			return oldTexImage2D.apply(webglContext, args);
57249		  } catch (e) {
57250			_this4.reset();
57251  
57252			_this4.player_.pause();
57253  
57254			_this4.triggerError_({
57255			  code: 'web-vr-hls-cors-not-supported',
57256			  dismiss: false
57257			});
57258  
57259			throw new Error(e);
57260		  }
57261		};
57262  
57263		this.renderer.setSize(this.player_.currentWidth(), this.player_.currentHeight(), false);
57264		this.effect = new VREffect(this.renderer);
57265		this.effect.setSize(this.player_.currentWidth(), this.player_.currentHeight(), false);
57266		this.vrDisplay = null; // Previous timestamps for gamepad updates
57267  
57268		this.prevTimestamps_ = [];
57269		this.renderedCanvas = this.renderer.domElement;
57270		this.renderedCanvas.setAttribute('style', 'width: 100%; height: 100%; position: absolute; top:0;');
57271		var videoElStyle = this.getVideoEl_().style;
57272		this.player_.el().insertBefore(this.renderedCanvas, this.player_.el().firstChild);
57273		videoElStyle.zIndex = '-1';
57274		videoElStyle.opacity = '0';
57275  
57276		if (window$1.navigator.getVRDisplays) {
57277		  this.log('is supported, getting vr displays');
57278		  window$1.navigator.getVRDisplays().then(function (displays) {
57279			if (displays.length > 0) {
57280			  _this4.log('Displays found', displays);
57281  
57282			  _this4.vrDisplay = displays[0]; // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive
57283			  // also need the cardboard button to enter fully immersive mode
57284			  // so, we want to add the button if we're not polyfilled.
57285  
57286			  if (!_this4.vrDisplay.isPolyfilled) {
57287				_this4.log('Real HMD found using VRControls', _this4.vrDisplay);
57288  
57289				_this4.addCardboardButton_(); // We use VRControls here since we are working with an HMD
57290				// and we only want orientation controls.
57291  
57292  
57293				_this4.controls3d = new VRControls(_this4.camera);
57294			  }
57295			}
57296  
57297			if (!_this4.controls3d) {
57298			  _this4.log('no HMD found Using Orbit & Orientation Controls');
57299  
57300			  var options = {
57301				camera: _this4.camera,
57302				canvas: _this4.renderedCanvas,
57303				// check if its a half sphere view projection
57304				halfView: _this4.currentProjection_.indexOf('180') === 0,
57305				orientation: videojs.browser.IS_IOS || videojs.browser.IS_ANDROID || false
57306			  };
57307  
57308			  if (_this4.options_.motionControls === false) {
57309				options.orientation = false;
57310			  }
57311  
57312			  _this4.controls3d = new OrbitOrientationControls(options);
57313			  _this4.canvasPlayerControls = new CanvasPlayerControls(_this4.player_, _this4.renderedCanvas);
57314			}
57315  
57316			_this4.animationFrameId_ = _this4.requestAnimationFrame(_this4.animate_);
57317		  });
57318		} else if (window$1.navigator.getVRDevices) {
57319		  this.triggerError_({
57320			code: 'web-vr-out-of-date',
57321			dismiss: false
57322		  });
57323		} else {
57324		  this.triggerError_({
57325			code: 'web-vr-not-supported',
57326			dismiss: false
57327		  });
57328		}
57329  
57330		if (this.options_.omnitone) {
57331		  var audiocontext = AudioContext.getContext();
57332		  this.omniController = new OmnitoneController(audiocontext, this.options_.omnitone, this.getVideoEl_(), this.options_.omnitoneOptions);
57333		  this.omniController.one('audiocontext-suspended', function () {
57334			_this4.player.pause();
57335  
57336			_this4.player.one('playing', function () {
57337			  audiocontext.resume();
57338			});
57339		  });
57340		}
57341  
57342		this.on(this.player_, 'fullscreenchange', this.handleResize_);
57343		window$1.addEventListener('vrdisplaypresentchange', this.handleResize_, true);
57344		window$1.addEventListener('resize', this.handleResize_, true);
57345		window$1.addEventListener('vrdisplayactivate', this.handleVrDisplayActivate_, true);
57346		window$1.addEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_, true);
57347		this.initialized_ = true;
57348		this.trigger('initialized');
57349	  };
57350  
57351	  _proto.addCardboardButton_ = function addCardboardButton_() {
57352		if (!this.player_.controlBar.getChild('CardboardButton')) {
57353		  this.player_.controlBar.addChild('CardboardButton', {});
57354		}
57355	  };
57356  
57357	  _proto.getVideoEl_ = function getVideoEl_() {
57358		return this.player_.el().getElementsByTagName('video')[0];
57359	  };
57360  
57361	  _proto.reset = function reset() {
57362		if (!this.initialized_) {
57363		  return;
57364		}
57365  
57366		if (this.omniController) {
57367		  this.omniController.off('audiocontext-suspended');
57368		  this.omniController.dispose();
57369		  this.omniController = undefined;
57370		}
57371  
57372		if (this.controls3d) {
57373		  this.controls3d.dispose();
57374		  this.controls3d = null;
57375		}
57376  
57377		if (this.canvasPlayerControls) {
57378		  this.canvasPlayerControls.dispose();
57379		  this.canvasPlayerControls = null;
57380		}
57381  
57382		if (this.effect) {
57383		  this.effect.dispose();
57384		  this.effect = null;
57385		}
57386  
57387		window$1.removeEventListener('resize', this.handleResize_, true);
57388		window$1.removeEventListener('vrdisplaypresentchange', this.handleResize_, true);
57389		window$1.removeEventListener('vrdisplayactivate', this.handleVrDisplayActivate_, true);
57390		window$1.removeEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_, true); // re-add the big play button to player
57391  
57392		if (!this.player_.getChild('BigPlayButton')) {
57393		  this.player_.addChild('BigPlayButton', {}, this.bigPlayButtonIndex_);
57394		}
57395  
57396		if (this.player_.getChild('BigVrPlayButton')) {
57397		  this.player_.removeChild('BigVrPlayButton');
57398		} // remove the cardboard button
57399  
57400  
57401		if (this.player_.getChild('CardboardButton')) {
57402		  this.player_.controlBar.removeChild('CardboardButton');
57403		} // show the fullscreen again
57404  
57405  
57406		if (videojs.browser.IS_IOS && this.player_.controlBar && this.player_.controlBar.fullscreenToggle) {
57407		  this.player_.controlBar.fullscreenToggle.show();
57408		} // reset the video element style so that it will be displayed
57409  
57410  
57411		var videoElStyle = this.getVideoEl_().style;
57412		videoElStyle.zIndex = '';
57413		videoElStyle.opacity = ''; // set the current projection to the default
57414  
57415		this.currentProjection_ = this.defaultProjection_; // reset the ios touch to click workaround
57416  
57417		if (this.iosRevertTouchToClick_) {
57418		  this.iosRevertTouchToClick_();
57419		} // remove the old canvas
57420  
57421  
57422		if (this.renderedCanvas) {
57423		  this.renderedCanvas.parentNode.removeChild(this.renderedCanvas);
57424		}
57425  
57426		if (this.animationFrameId_) {
57427		  this.cancelAnimationFrame(this.animationFrameId_);
57428		}
57429  
57430		this.initialized_ = false;
57431	  };
57432  
57433	  _proto.dispose = function dispose() {
57434		_Plugin.prototype.dispose.call(this);
57435  
57436		this.reset();
57437	  };
57438  
57439	  _proto.polyfillVersion = function polyfillVersion() {
57440		return WebVRPolyfill.version;
57441	  };
57442  
57443	  return VR;
57444	}(Plugin);
57445  
57446	VR.prototype.setTimeout = Component.prototype.setTimeout;
57447	VR.prototype.clearTimeout = Component.prototype.clearTimeout;
57448	VR.VERSION = version;
57449	videojs.registerPlugin('vr', VR);
57450  
57451	return VR;
57452  
57453  })));
57454// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/admin/lib/pannellum/src/js/videojs-pannellum-plugin.js?ver=1 
57455/*
57456 * Video.js plugin for Pannellum
57457 * Copyright (c) 2015-2018 Matthew Petroff
57458 * MIT License
57459 */
57460
57461(function(document, videojs, pannellum) {
57462'use strict';
57463
57464var registerPlugin = videojs.registerPlugin || videojs.plugin;  // Use registerPlugin for Video.js >= 6
57465registerPlugin('pannellum', function(config) {
57466    // Create Pannellum instance
57467    var player = this;
vendor: 1,462 bytes, lines 57468-57510
57468    var container = player.el();
57469    var vid = container.getElementsByTagName('video')[0],
57470        pnlmContainer = document.createElement('div');
57471    pnlmContainer.style.zIndex = '0';
57472    config = config || {};
57473    config.type = 'equirectangular';
57474    config.dynamic = true;
57475    config.showZoomCtrl = false;
57476    config.showFullscreenCtrl = false;
57477    config.autoLoad = true;
57478    config.panorama = vid;
57479    pnlmContainer.style.visibility = 'hidden';
57480    player.pnlmViewer = pannellum.viewer(pnlmContainer, config);
57481    container.insertBefore(pnlmContainer, container.firstChild);
57482    vid.style.display = 'none';
57483
57484    // Handle update settings
57485    player.on('play', function() {
57486        if (vid.readyState > 1)
57487            player.pnlmViewer.setUpdate(true);
57488    });
57489    player.on('canplay', function() {
57490        if (!player.paused())
57491            player.pnlmViewer.setUpdate(true);
57492    });
57493    player.on('pause', function() {
57494        player.pnlmViewer.setUpdate(false);
57495    });
57496    player.on('loadeddata', function() {
57497        pnlmContainer.style.visibility = 'visible';
57498    });
57499    player.on('seeking', function() {
57500        if (player.paused())
57501            player.pnlmViewer.setUpdate(true);
57502    });
57503    player.on('seeked', function() {
57504        if (player.paused())
57505            player.pnlmViewer.setUpdate(false);
57506    });
57507});
57508
57509})(document, videojs, pannellum);
57510// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/admin/js/owl.carousel.js?ver=6.8.2 
vendor: 39,702 bytes, lines 57511-59026
57511/**
57512 * Owl carousel
57513 * @version 2.3.4
57514 * @author Bartosz Wojciechowski
57515 * @author David Deutsch
57516 * @license The MIT License (MIT)
57517 * @todo Lazy Load Icon
57518 * @todo prevent animationend bubling
57519 * @todo itemsScaleUp
57520 * @todo Test Zepto
57521 * @todo stagePadding calculate wrong active classes
57522 */
57523;(function($, window, document, undefined) {
57524
57525	/**
57526	 * Creates a carousel.
57527	 * @class The Owl Carousel.
57528	 * @public
57529	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
57530	 * @param {Object} [options] - The options
57531	 */
57532	function Owl(element, options) {
57533
57534		/**
57535		 * Current settings for the carousel.
57536		 * @public
57537		 */
57538		this.settings = null;
57539
57540		/**
57541		 * Current options set by the caller including defaults.
57542		 * @public
57543		 */
57544		this.options = $.extend({}, Owl.Defaults, options);
57545
57546		/**
57547		 * Plugin element.
57548		 * @public
57549		 */
57550		this.$element = $(element);
57551
57552		/**
57553		 * Proxied event handlers.
57554		 * @protected
57555		 */
57556		this._handlers = {};
57557
57558		/**
57559		 * References to the running plugins of this carousel.
57560		 * @protected
57561		 */
57562		this._plugins = {};
57563
57564		/**
57565		 * Currently suppressed events to prevent them from being retriggered.
57566		 * @protected
57567		 */
57568		this._supress = {};
57569
57570		/**
57571		 * Absolute current position.
57572		 * @protected
57573		 */
57574		this._current = null;
57575
57576		/**
57577		 * Animation speed in milliseconds.
57578		 * @protected
57579		 */
57580		this._speed = null;
57581
57582		/**
57583		 * Coordinates of all items in pixel.
57584		 * @todo The name of this member is missleading.
57585		 * @protected
57586		 */
57587		this._coordinates = [];
57588
57589		/**
57590		 * Current breakpoint.
57591		 * @todo Real media queries would be nice.
57592		 * @protected
57593		 */
57594		this._breakpoint = null;
57595
57596		/**
57597		 * Current width of the plugin element.
57598		 */
57599		this._width = null;
57600
57601		/**
57602		 * All real items.
57603		 * @protected
57604		 */
57605		this._items = [];
57606
57607		/**
57608		 * All cloned items.
57609		 * @protected
57610		 */
57611		this._clones = [];
57612
57613		/**
57614		 * Merge values of all items.
57615		 * @todo Maybe this could be part of a plugin.
57616		 * @protected
57617		 */
57618		this._mergers = [];
57619
57620		/**
57621		 * Widths of all items.
57622		 */
57623		this._widths = [];
57624
57625		/**
57626		 * Invalidated parts within the update process.
57627		 * @protected
57628		 */
57629		this._invalidated = {};
57630
57631		/**
57632		 * Ordered list of workers for the update process.
57633		 * @protected
57634		 */
57635		this._pipe = [];
57636
57637		/**
57638		 * Current state information for the drag operation.
57639		 * @todo #261
57640		 * @protected
57641		 */
57642		this._drag = {
57643			time: null,
57644			target: null,
57645			pointer: null,
57646			stage: {
57647				start: null,
57648				current: null
57649			},
57650			direction: null
57651		};
57652
57653		/**
57654		 * Current state information and their tags.
57655		 * @type {Object}
57656		 * @protected
57657		 */
57658		this._states = {
57659			current: {},
57660			tags: {
57661				'initializing': [ 'busy' ],
57662				'animating': [ 'busy' ],
57663				'dragging': [ 'interacting' ]
57664			}
57665		};
57666
57667		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
57668			this._handlers[handler] = $.proxy(this[handler], this);
57669		}, this));
57670
57671		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
57672			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
57673				= new plugin(this);
57674		}, this));
57675
57676		$.each(Owl.Workers, $.proxy(function(priority, worker) {
57677			this._pipe.push({
57678				'filter': worker.filter,
57679				'run': $.proxy(worker.run, this)
57680			});
57681		}, this));
57682
57683		this.setup();
57684		this.initialize();
57685	}
57686
57687	/**
57688	 * Default options for the carousel.
57689	 * @public
57690	 */
57691	Owl.Defaults = {
57692		items: 3,
57693		loop: false,
57694		center: false,
57695		rewind: false,
57696		checkVisibility: true,
57697
57698		mouseDrag: true,
57699		touchDrag: true,
57700		pullDrag: true,
57701		freeDrag: false,
57702
57703		margin: 0,
57704		stagePadding: 0,
57705
57706		merge: false,
57707		mergeFit: true,
57708		autoWidth: false,
57709
57710		startPosition: 0,
57711		rtl: false,
57712
57713		smartSpeed: 250,
57714		fluidSpeed: false,
57715		dragEndSpeed: false,
57716
57717		responsive: {},
57718		responsiveRefreshRate: 200,
57719		responsiveBaseElement: window,
57720
57721		fallbackEasing: 'swing',
57722		slideTransition: '',
57723
57724		info: false,
57725
57726		nestedItemSelector: false,
57727		itemElement: 'div',
57728		stageElement: 'div',
57729
57730		refreshClass: 'owl-refresh',
57731		loadedClass: 'owl-loaded',
57732		loadingClass: 'owl-loading',
57733		rtlClass: 'owl-rtl',
57734		responsiveClass: 'owl-responsive',
57735		dragClass: 'owl-drag',
57736		itemClass: 'owl-item',
57737		stageClass: 'owl-stage',
57738		stageOuterClass: 'owl-stage-outer',
57739		grabClass: 'owl-grab'
57740	};
57741
57742	/**
57743	 * Enumeration for width.
57744	 * @public
57745	 * @readonly
57746	 * @enum {String}
57747	 */
57748	Owl.Width = {
57749		Default: 'default',
57750		Inner: 'inner',
57751		Outer: 'outer'
57752	};
57753
57754	/**
57755	 * Enumeration for types.
57756	 * @public
57757	 * @readonly
57758	 * @enum {String}
57759	 */
57760	Owl.Type = {
57761		Event: 'event',
57762		State: 'state'
57763	};
57764
57765	/**
57766	 * Contains all registered plugins.
57767	 * @public
57768	 */
57769	Owl.Plugins = {};
57770
57771	/**
57772	 * List of workers involved in the update process.
57773	 */
57774	Owl.Workers = [ {
57775		filter: [ 'width', 'settings' ],
57776		run: function() {
57777			this._width = this.$element.width();
57778		}
57779	}, {
57780		filter: [ 'width', 'items', 'settings' ],
57781		run: function(cache) {
57782			cache.current = this._items && this._items[this.relative(this._current)];
57783		}
57784	}, {
57785		filter: [ 'items', 'settings' ],
57786		run: function() {
57787			this.$stage.children('.cloned').remove();
57788		}
57789	}, {
57790		filter: [ 'width', 'items', 'settings' ],
57791		run: function(cache) {
57792			var margin = this.settings.margin || '',
57793				grid = !this.settings.autoWidth,
57794				rtl = this.settings.rtl,
57795				css = {
57796					'width': 'auto',
57797					'margin-left': rtl ? margin : '',
57798					'margin-right': rtl ? '' : margin
57799				};
57800
57801			!grid && this.$stage.children().css(css);
57802
57803			cache.css = css;
57804		}
57805	}, {
57806		filter: [ 'width', 'items', 'settings' ],
57807		run: function(cache) {
57808			var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
57809				merge = null,
57810				iterator = this._items.length,
57811				grid = !this.settings.autoWidth,
57812				widths = [];
57813
57814			cache.items = {
57815				merge: false,
57816				width: width
57817			};
57818
57819			while (iterator--) {
57820				merge = this._mergers[iterator];
57821				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
57822
57823				cache.items.merge = merge > 1 || cache.items.merge;
57824
57825				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
57826			}
57827
57828			this._widths = widths;
57829		}
57830	}, {
57831		filter: [ 'items', 'settings' ],
57832		run: function() {
57833			var clones = [],
57834				items = this._items,
57835				settings = this.settings,
57836				// TODO: Should be computed from number of min width items in stage
57837				view = Math.max(settings.items * 2, 4),
57838				size = Math.ceil(items.length / 2) * 2,
57839				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
57840				append = '',
57841				prepend = '';
57842
57843			repeat /= 2;
57844
57845			while (repeat > 0) {
57846				// Switch to only using appended clones
57847				clones.push(this.normalize(clones.length / 2, true));
57848				$(items[clones[clones.length - 1]][0]).clone(true).addClass('cloned').appendTo(this.$stage);
57849				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
57850				$(items[clones[clones.length - 1]][0]).clone(true).addClass('cloned').prependTo(this.$stage);
57851				repeat -= 1;
57852			}
57853			this._clones = clones;
57854		}
57855	}, {
57856		filter: [ 'width', 'items', 'settings' ],
57857		run: function() {
57858			var rtl = this.settings.rtl ? 1 : -1,
57859				size = this._clones.length + this._items.length,
57860				iterator = -1,
57861				previous = 0,
57862				current = 0,
57863				coordinates = [];
57864
57865			while (++iterator < size) {
57866				previous = coordinates[iterator - 1] || 0;
57867				current = this._widths[this.relative(iterator)] + this.settings.margin;
57868				coordinates.push(previous + current * rtl);
57869			}
57870
57871			this._coordinates = coordinates;
57872		}
57873	}, {
57874		filter: [ 'width', 'items', 'settings' ],
57875		run: function() {
57876			var padding = this.settings.stagePadding,
57877				coordinates = this._coordinates,
57878				css = {
57879					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
57880					'padding-left': padding || '',
57881					'padding-right': padding || ''
57882				};
57883
57884			this.$stage.css(css);
57885		}
57886	}, {
57887		filter: [ 'width', 'items', 'settings' ],
57888		run: function(cache) {
57889			var iterator = this._coordinates.length,
57890				grid = !this.settings.autoWidth,
57891				items = this.$stage.children();
57892
57893			if (grid && cache.items.merge) {
57894				while (iterator--) {
57895					cache.css.width = this._widths[this.relative(iterator)];
57896					items.eq(iterator).css(cache.css);
57897				}
57898			} else if (grid) {
57899				cache.css.width = cache.items.width;
57900				items.css(cache.css);
57901			}
57902		}
57903	}, {
57904		filter: [ 'items' ],
57905		run: function() {
57906			this._coordinates.length < 1 && this.$stage.removeAttr('style');
57907		}
57908	}, {
57909		filter: [ 'width', 'items', 'settings' ],
57910		run: function(cache) {
57911			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
57912			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
57913			this.reset(cache.current);
57914		}
57915	}, {
57916		filter: [ 'position' ],
57917		run: function() {
57918			this.animate(this.coordinates(this._current));
57919		}
57920	}, {
57921		filter: [ 'width', 'position', 'items', 'settings' ],
57922		run: function() {
57923			var rtl = this.settings.rtl ? 1 : -1,
57924				padding = this.settings.stagePadding * 2,
57925				begin = this.coordinates(this.current()) + padding,
57926				end = begin + this.width() * rtl,
57927				inner, outer, matches = [], i, n;
57928
57929			for (i = 0, n = this._coordinates.length; i < n; i++) {
57930				inner = this._coordinates[i - 1] || 0;
57931				outer = Math.abs(this._coordinates[i]) + padding * rtl;
57932
57933				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
57934					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
57935					matches.push(i);
57936				}
57937			}
57938
57939			this.$stage.children('.active').removeClass('active');
57940			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
57941
57942			this.$stage.children('.center').removeClass('center');
57943			if (this.settings.center) {
57944				this.$stage.children().eq(this.current()).addClass('center');
57945			}
57946		}
57947	} ];
57948
57949	/**
57950	 * Create the stage DOM element
57951	 */
57952	Owl.prototype.initializeStage = function() {
57953		this.$stage = this.$element.find('.' + this.settings.stageClass);
57954
57955		// if the stage is already in the DOM, grab it and skip stage initialization
57956		if (this.$stage.length) {
57957			return;
57958		}
57959
57960		this.$element.addClass(this.options.loadingClass);
57961
57962		// create stage
57963		this.$stage = $('<' + this.settings.stageElement + '>', {
57964			"class": this.settings.stageClass
57965		}).wrap( $( '<div/>', {
57966			"class": this.settings.stageOuterClass
57967		}));
57968
57969		// append stage
57970		this.$element.append(this.$stage.parent());
57971	};
57972
57973	/**
57974	 * Create item DOM elements
57975	 */
57976	Owl.prototype.initializeItems = function() {
57977		var $items = this.$element.find('.owl-item');
57978
57979		// if the items are already in the DOM, grab them and skip item initialization
57980		if ($items.length) {
57981			this._items = $items.get().map(function(item) {
57982				return $(item);
57983			});
57984
57985			this._mergers = this._items.map(function() {
57986				return 1;
57987			});
57988
57989			this.refresh();
57990
57991			return;
57992		}
57993
57994		// append content
57995		this.replace(this.$element.children().not(this.$stage.parent()));
57996
57997		// check visibility
57998		if (this.isVisible()) {
57999			// update view
58000			this.refresh();
58001		} else {
58002			// invalidate width
58003			this.invalidate('width');
58004		}
58005
58006		this.$element
58007			.removeClass(this.options.loadingClass)
58008			.addClass(this.options.loadedClass);
58009	};
58010
58011	/**
58012	 * Initializes the carousel.
58013	 * @protected
58014	 */
58015	Owl.prototype.initialize = function() {
58016		this.enter('initializing');
58017		this.trigger('initialize');
58018
58019		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
58020
58021		if (this.settings.autoWidth && !this.is('pre-loading')) {
58022			var imgs, nestedSelector, width;
58023			imgs = this.$element.find('img');
58024			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
58025			width = this.$element.children(nestedSelector).width();
58026
58027			if (imgs.length && width <= 0) {
58028				this.preloadAutoWidthImages(imgs);
58029			}
58030		}
58031
58032		this.initializeStage();
58033		this.initializeItems();
58034
58035		// register event handlers
58036		this.registerEventHandlers();
58037
58038		this.leave('initializing');
58039		this.trigger('initialized');
58040	};
58041
58042	/**
58043	 * @returns {Boolean} visibility of $element
58044	 *                    if you know the carousel will always be visible you can set `checkVisibility` to `false` to
58045	 *                    prevent the expensive browser layout forced reflow the $element.is(':visible') does
58046	 */
58047	Owl.prototype.isVisible = function() {
58048		return this.settings.checkVisibility
58049			? this.$element.is(':visible')
58050			: true;
58051	};
58052
58053	/**
58054	 * Setups the current settings.
58055	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
58056	 * @todo Support for media queries by using `matchMedia` would be nice.
58057	 * @public
58058	 */
58059	Owl.prototype.setup = function() {
58060		var viewport = this.viewport(),
58061			overwrites = this.options.responsive,
58062			match = -1,
58063			settings = null;
58064
58065		if (!overwrites) {
58066			settings = $.extend({}, this.options);
58067		} else {
58068			$.each(overwrites, function(breakpoint) {
58069				if (breakpoint <= viewport && breakpoint > match) {
58070					match = Number(breakpoint);
58071				}
58072			});
58073
58074			settings = $.extend({}, this.options, overwrites[match]);
58075			if (typeof settings.stagePadding === 'function') {
58076				settings.stagePadding = settings.stagePadding();
58077			}
58078			delete settings.responsive;
58079
58080			// responsive class
58081			if (settings.responsiveClass) {
58082				this.$element.attr('class',
58083					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
58084				);
58085			}
58086		}
58087
58088		this.trigger('change', { property: { name: 'settings', value: settings } });
58089		this._breakpoint = match;
58090		this.settings = settings;
58091		this.invalidate('settings');
58092		this.trigger('changed', { property: { name: 'settings', value: this.settings } });
58093	};
58094
58095	/**
58096	 * Updates option logic if necessery.
58097	 * @protected
58098	 */
58099	Owl.prototype.optionsLogic = function() {
58100		if (this.settings.autoWidth) {
58101			this.settings.stagePadding = false;
58102			this.settings.merge = false;
58103		}
58104	};
58105
58106	/**
58107	 * Prepares an item before add.
58108	 * @todo Rename event parameter `content` to `item`.
58109	 * @protected
58110	 * @returns {jQuery|HTMLElement} - The item container.
58111	 */
58112	Owl.prototype.prepare = function(item) {
58113		var event = this.trigger('prepare', { content: item });
58114
58115		if (!event.data) {
58116			event.data = $('<' + this.settings.itemElement + '/>')
58117				.addClass(this.options.itemClass).append(item)
58118		}
58119
58120		this.trigger('prepared', { content: event.data });
58121
58122		return event.data;
58123	};
58124
58125	/**
58126	 * Updates the view.
58127	 * @public
58128	 */
58129	Owl.prototype.update = function() {
58130		var i = 0,
58131			n = this._pipe.length,
58132			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
58133			cache = {};
58134
58135		while (i < n) {
58136			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
58137				this._pipe[i].run(cache);
58138			}
58139			i++;
58140		}
58141
58142		this._invalidated = {};
58143
58144		!this.is('valid') && this.enter('valid');
58145	};
58146
58147	/**
58148	 * Gets the width of the view.
58149	 * @public
58150	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
58151	 * @returns {Number} - The width of the view in pixel.
58152	 */
58153	Owl.prototype.width = function(dimension) {
58154		dimension = dimension || Owl.Width.Default;
58155		switch (dimension) {
58156			case Owl.Width.Inner:
58157			case Owl.Width.Outer:
58158				return this._width;
58159			default:
58160				return this._width - this.settings.stagePadding * 2 + this.settings.margin;
58161		}
58162	};
58163
58164	/**
58165	 * Refreshes the carousel primarily for adaptive purposes.
58166	 * @public
58167	 */
58168	Owl.prototype.refresh = function(resizing) {
58169		resizing = resizing || false;
58170
58171		this.enter('refreshing');
58172		this.trigger('refresh');
58173
58174		this.setup();
58175
58176		this.optionsLogic();
58177
58178		this.$element.addClass(this.options.refreshClass);
58179
58180		this.update();
58181
58182		if (!resizing) {
58183			this.onResize();
58184		}
58185
58186		this.$element.removeClass(this.options.refreshClass);
58187
58188		this.leave('refreshing');
58189		this.trigger('refreshed');
58190	};
58191
58192	/**
58193	 * Checks window `resize` event.
58194	 * @protected
58195	 */
58196	Owl.prototype.onThrottledResize = function() {
58197		window.clearTimeout(this.resizeTimer);
58198		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
58199	};
58200
58201	/**
58202	 * Checks window `resize` event.
58203	 * @protected
58204	 */
58205	Owl.prototype.onResize = function() {
58206		var resizing = true;
58207
58208		if (!this._items.length) {
58209			return false;
58210		}
58211
58212		if (this._width === this.$element.width()) {
58213			return false;
58214		}
58215
58216		if (!this.isVisible()) {
58217			return false;
58218		}
58219
58220		this.enter('resizing');
58221
58222		if (this.trigger('resize').isDefaultPrevented()) {
58223			this.leave('resizing');
58224			return false;
58225		}
58226
58227		this.invalidate('width');
58228
58229		this.refresh(resizing);
58230
58231		this.leave('resizing');
58232		this.trigger('resized');
58233	};
58234
58235	/**
58236	 * Registers event handlers.
58237	 * @todo Check `msPointerEnabled`
58238	 * @todo #261
58239	 * @protected
58240	 */
58241	Owl.prototype.registerEventHandlers = function() {
58242		if ($.support.transition) {
58243			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
58244		}
58245
58246		if (this.settings.responsive !== false) {
58247			this.on(window, 'resize', this._handlers.onThrottledResize);
58248		}
58249
58250		if (this.settings.mouseDrag) {
58251			this.$element.addClass(this.options.dragClass);
58252			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
58253			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
58254		}
58255
58256		if (this.settings.touchDrag){
58257			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
58258			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
58259		}
58260	};
58261
58262	/**
58263	 * Handles `touchstart` and `mousedown` events.
58264	 * @todo Horizontal swipe threshold as option
58265	 * @todo #261
58266	 * @protected
58267	 * @param {Event} event - The event arguments.
58268	 */
58269	Owl.prototype.onDragStart = function(event) {
58270		var stage = null;
58271
58272		if (event.which === 3) {
58273			return;
58274		}
58275
58276		if ($.support.transform) {
58277			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
58278			stage = {
58279				x: stage[stage.length === 16 ? 12 : 4],
58280				y: stage[stage.length === 16 ? 13 : 5]
58281			};
58282		} else {
58283			stage = this.$stage.position();
58284			stage = {
58285				x: this.settings.rtl ?
58286					stage.left + this.$stage.width() - this.width() + this.settings.margin :
58287					stage.left,
58288				y: stage.top
58289			};
58290		}
58291
58292		if (this.is('animating')) {
58293			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
58294			this.invalidate('position');
58295		}
58296
58297		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
58298
58299		this.speed(0);
58300
58301		this._drag.time = new Date().getTime();
58302		this._drag.target = $(event.target);
58303		this._drag.stage.start = stage;
58304		this._drag.stage.current = stage;
58305		this._drag.pointer = this.pointer(event);
58306
58307		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
58308
58309		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
58310			var delta = this.difference(this._drag.pointer, this.pointer(event));
58311
58312			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
58313
58314			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
58315				return;
58316			}
58317
58318			event.preventDefault();
58319
58320			this.enter('dragging');
58321			this.trigger('drag');
58322		}, this));
58323	};
58324
58325	/**
58326	 * Handles the `touchmove` and `mousemove` events.
58327	 * @todo #261
58328	 * @protected
58329	 * @param {Event} event - The event arguments.
58330	 */
58331	Owl.prototype.onDragMove = function(event) {
58332		var minimum = null,
58333			maximum = null,
58334			pull = null,
58335			delta = this.difference(this._drag.pointer, this.pointer(event)),
58336			stage = this.difference(this._drag.stage.start, delta);
58337
58338		if (!this.is('dragging')) {
58339			return;
58340		}
58341
58342		event.preventDefault();
58343
58344		if (this.settings.loop) {
58345			minimum = this.coordinates(this.minimum());
58346			maximum = this.coordinates(this.maximum() + 1) - minimum;
58347			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
58348		} else {
58349			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
58350			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
58351			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
58352			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
58353		}
58354
58355		this._drag.stage.current = stage;
58356
58357		this.animate(stage.x);
58358	};
58359
58360	/**
58361	 * Handles the `touchend` and `mouseup` events.
58362	 * @todo #261
58363	 * @todo Threshold for click event
58364	 * @protected
58365	 * @param {Event} event - The event arguments.
58366	 */
58367	Owl.prototype.onDragEnd = function(event) {
58368		var delta = this.difference(this._drag.pointer, this.pointer(event)),
58369			stage = this._drag.stage.current,
58370			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
58371
58372		$(document).off('.owl.core');
58373
58374		this.$element.removeClass(this.options.grabClass);
58375
58376		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
58377			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
58378			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
58379			this.invalidate('position');
58380			this.update();
58381
58382			this._drag.direction = direction;
58383
58384			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
58385				this._drag.target.one('click.owl.core', function() { return false; });
58386			}
58387		}
58388
58389		if (!this.is('dragging')) {
58390			return;
58391		}
58392
58393		this.leave('dragging');
58394		this.trigger('dragged');
58395	};
58396
58397	/**
58398	 * Gets absolute position of the closest item for a coordinate.
58399	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
58400	 * @protected
58401	 * @param {Number} coordinate - The coordinate in pixel.
58402	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
58403	 * @return {Number} - The absolute position of the closest item.
58404	 */
58405	Owl.prototype.closest = function(coordinate, direction) {
58406		var position = -1,
58407			pull = 30,
58408			width = this.width(), // visible carousel width
58409			count = this.settings.items,
58410			itemWidth = Math.round(width / count),
58411			coordinates = this.coordinates();
58412
58413		if (!this.settings.freeDrag) {
58414			// check closest item
58415			$.each(coordinates, $.proxy(function(index, value) {
58416				// on a left pull, check on current index
58417				if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
58418					position = index;
58419				// on a right pull, check on previous index
58420				// to do so, subtract width from value and set position = index + 1
58421				} else if (direction === 'right' && coordinate > value - itemWidth - pull && coordinate < value - itemWidth + pull) {
58422					position = index + 1;
58423				} else if (this.op(coordinate, '<', value)
58424					&& this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) {
58425					position = direction === 'left' ? index + 1 : index;
58426				}
58427				return position === -1;
58428			}, this));
58429		}
58430
58431		if (!this.settings.loop) {
58432			// non loop boundries
58433			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
58434				position = coordinate = this.minimum();
58435			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
58436				position = coordinate = this.maximum();
58437			}
58438		}
58439
58440		return position;
58441	};
58442
58443	/**
58444	 * Animates the stage.
58445	 * @todo #270
58446	 * @public
58447	 * @param {Number} coordinate - The coordinate in pixels.
58448	 */
58449	Owl.prototype.animate = function(coordinate) {
58450		var animate = this.speed() > 0;
58451
58452		this.is('animating') && this.onTransitionEnd();
58453
58454		if (animate) {
58455			this.enter('animating');
58456			this.trigger('translate');
58457		}
58458
58459		if ($.support.transform3d && $.support.transition) {
58460			this.$stage.css({
58461				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
58462				transition: (this.speed() / 1000) + 's' + (
58463					this.settings.slideTransition ? ' ' + this.settings.slideTransition : ''
58464				)
58465			});
58466		} else if (animate) {
58467			this.$stage.animate({
58468				left: coordinate + 'px'
58469			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
58470		} else {
58471			this.$stage.css({
58472				left: coordinate + 'px'
58473			});
58474		}
58475	};
58476
58477	/**
58478	 * Checks whether the carousel is in a specific state or not.
58479	 * @param {String} state - The state to check.
58480	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
58481	 */
58482	Owl.prototype.is = function(state) {
58483		return this._states.current[state] && this._states.current[state] > 0;
58484	};
58485
58486	/**
58487	 * Sets the absolute position of the current item.
58488	 * @public
58489	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
58490	 * @returns {Number} - The absolute position of the current item.
58491	 */
58492	Owl.prototype.current = function(position) {
58493		if (position === undefined) {
58494			return this._current;
58495		}
58496
58497		if (this._items.length === 0) {
58498			return undefined;
58499		}
58500
58501		position = this.normalize(position);
58502
58503		if (this._current !== position) {
58504			var event = this.trigger('change', { property: { name: 'position', value: position } });
58505
58506			if (event.data !== undefined) {
58507				position = this.normalize(event.data);
58508			}
58509
58510			this._current = position;
58511
58512			this.invalidate('position');
58513
58514			this.trigger('changed', { property: { name: 'position', value: this._current } });
58515		}
58516
58517		return this._current;
58518	};
58519
58520	/**
58521	 * Invalidates the given part of the update routine.
58522	 * @param {String} [part] - The part to invalidate.
58523	 * @returns {Array.<String>} - The invalidated parts.
58524	 */
58525	Owl.prototype.invalidate = function(part) {
58526		if ($.type(part) === 'string') {
58527			this._invalidated[part] = true;
58528			this.is('valid') && this.leave('valid');
58529		}
58530		return $.map(this._invalidated, function(v, i) { return i });
58531	};
58532
58533	/**
58534	 * Resets the absolute position of the current item.
58535	 * @public
58536	 * @param {Number} position - The absolute position of the new item.
58537	 */
58538	Owl.prototype.reset = function(position) {
58539		position = this.normalize(position);
58540
58541		if (position === undefined) {
58542			return;
58543		}
58544
58545		this._speed = 0;
58546		this._current = position;
58547
58548		this.suppress([ 'translate', 'translated' ]);
58549
58550		this.animate(this.coordinates(position));
58551
58552		this.release([ 'translate', 'translated' ]);
58553	};
58554
58555	/**
58556	 * Normalizes an absolute or a relative position of an item.
58557	 * @public
58558	 * @param {Number} position - The absolute or relative position to normalize.
58559	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
58560	 * @returns {Number} - The normalized position.
58561	 */
58562	Owl.prototype.normalize = function(position, relative) {
58563		var n = this._items.length,
58564			m = relative ? 0 : this._clones.length;
58565
58566		if (!this.isNumeric(position) || n < 1) {
58567			position = undefined;
58568		} else if (position < 0 || position >= n + m) {
58569			position = ((position - m / 2) % n + n) % n + m / 2;
58570		}
58571
58572		return position;
58573	};
58574
58575	/**
58576	 * Converts an absolute position of an item into a relative one.
58577	 * @public
58578	 * @param {Number} position - The absolute position to convert.
58579	 * @returns {Number} - The converted position.
58580	 */
58581	Owl.prototype.relative = function(position) {
58582		position -= this._clones.length / 2;
58583		return this.normalize(position, true);
58584	};
58585
58586	/**
58587	 * Gets the maximum position for the current item.
58588	 * @public
58589	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
58590	 * @returns {Number}
58591	 */
58592	Owl.prototype.maximum = function(relative) {
58593		var settings = this.settings,
58594			maximum = this._coordinates.length,
58595			iterator,
58596			reciprocalItemsWidth,
58597			elementWidth;
58598
58599		if (settings.loop) {
58600			maximum = this._clones.length / 2 + this._items.length - 1;
58601		} else if (settings.autoWidth || settings.merge) {
58602			iterator = this._items.length;
58603			if (iterator) {
58604				reciprocalItemsWidth = this._items[--iterator].width();
58605				elementWidth = this.$element.width();
58606				while (iterator--) {
58607					reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
58608					if (reciprocalItemsWidth > elementWidth) {
58609						break;
58610					}
58611				}
58612			}
58613			maximum = iterator + 1;
58614		} else if (settings.center) {
58615			maximum = this._items.length - 1;
58616		} else {
58617			maximum = this._items.length - settings.items;
58618		}
58619
58620		if (relative) {
58621			maximum -= this._clones.length / 2;
58622		}
58623
58624		return Math.max(maximum, 0);
58625	};
58626
58627	/**
58628	 * Gets the minimum position for the current item.
58629	 * @public
58630	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
58631	 * @returns {Number}
58632	 */
58633	Owl.prototype.minimum = function(relative) {
58634		return relative ? 0 : this._clones.length / 2;
58635	};
58636
58637	/**
58638	 * Gets an item at the specified relative position.
58639	 * @public
58640	 * @param {Number} [position] - The relative position of the item.
58641	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
58642	 */
58643	Owl.prototype.items = function(position) {
58644		if (position === undefined) {
58645			return this._items.slice();
58646		}
58647
58648		position = this.normalize(position, true);
58649		return this._items[position];
58650	};
58651
58652	/**
58653	 * Gets an item at the specified relative position.
58654	 * @public
58655	 * @param {Number} [position] - The relative position of the item.
58656	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
58657	 */
58658	Owl.prototype.mergers = function(position) {
58659		if (position === undefined) {
58660			return this._mergers.slice();
58661		}
58662
58663		position = this.normalize(position, true);
58664		return this._mergers[position];
58665	};
58666
58667	/**
58668	 * Gets the absolute positions of clones for an item.
58669	 * @public
58670	 * @param {Number} [position] - The relative position of the item.
58671	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
58672	 */
58673	Owl.prototype.clones = function(position) {
58674		var odd = this._clones.length / 2,
58675			even = odd + this._items.length,
58676			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
58677
58678		if (position === undefined) {
58679			return $.map(this._clones, function(v, i) { return map(i) });
58680		}
58681
58682		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
58683	};
58684
58685	/**
58686	 * Sets the current animation speed.
58687	 * @public
58688	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
58689	 * @returns {Number} - The current animation speed in milliseconds.
58690	 */
58691	Owl.prototype.speed = function(speed) {
58692		if (speed !== undefined) {
58693			this._speed = speed;
58694		}
58695
58696		return this._speed;
58697	};
58698
58699	/**
58700	 * Gets the coordinate of an item.
58701	 * @todo The name of this method is missleanding.
58702	 * @public
58703	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
58704	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
58705	 */
58706	Owl.prototype.coordinates = function(position) {
58707		var multiplier = 1,
58708			newPosition = position - 1,
58709			coordinate;
58710
58711		if (position === undefined) {
58712			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
58713				return this.coordinates(index);
58714			}, this));
58715		}
58716
58717		if (this.settings.center) {
58718			if (this.settings.rtl) {
58719				multiplier = -1;
58720				newPosition = position + 1;
58721			}
58722
58723			coordinate = this._coordinates[position];
58724			coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
58725		} else {
58726			coordinate = this._coordinates[newPosition] || 0;
58727		}
58728
58729		coordinate = Math.ceil(coordinate);
58730
58731		return coordinate;
58732	};
58733
58734	/**
58735	 * Calculates the speed for a translation.
58736	 * @protected
58737	 * @param {Number} from - The absolute position of the start item.
58738	 * @param {Number} to - The absolute position of the target item.
58739	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
58740	 * @returns {Number} - The time in milliseconds for the translation.
58741	 */
58742	Owl.prototype.duration = function(from, to, factor) {
58743		if (factor === 0) {
58744			return 0;
58745		}
58746
58747		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
58748	};
58749
58750	/**
58751	 * Slides to the specified item.
58752	 * @public
58753	 * @param {Number} position - The position of the item.
58754	 * @param {Number} [speed] - The time in milliseconds for the transition.
58755	 */
58756	Owl.prototype.to = function(position, speed) {
58757		var current = this.current(),
58758			revert = null,
58759			distance = position - this.relative(current),
58760			direction = (distance > 0) - (distance < 0),
58761			items = this._items.length,
58762			minimum = this.minimum(),
58763			maximum = this.maximum();
58764
58765		if (this.settings.loop) {
58766			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
58767				distance += direction * -1 * items;
58768			}
58769
58770			position = current + distance;
58771			revert = ((position - minimum) % items + items) % items + minimum;
58772
58773			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
58774				current = revert - distance;
58775				position = revert;
58776				this.reset(current);
58777			}
58778		} else if (this.settings.rewind) {
58779			maximum += 1;
58780			position = (position % maximum + maximum) % maximum;
58781		} else {
58782			position = Math.max(minimum, Math.min(maximum, position));
58783		}
58784
58785		this.speed(this.duration(current, position, speed));
58786		this.current(position);
58787
58788		if (this.isVisible()) {
58789			this.update();
58790		}
58791	};
58792
58793	/**
58794	 * Slides to the next item.
58795	 * @public
58796	 * @param {Number} [speed] - The time in milliseconds for the transition.
58797	 */
58798	Owl.prototype.next = function(speed) {
58799		speed = speed || false;
58800		this.to(this.relative(this.current()) + 1, speed);
58801	};
58802
58803	/**
58804	 * Slides to the previous item.
58805	 * @public
58806	 * @param {Number} [speed] - The time in milliseconds for the transition.
58807	 */
58808	Owl.prototype.prev = function(speed) {
58809		speed = speed || false;
58810		this.to(this.relative(this.current()) - 1, speed);
58811	};
58812
58813	/**
58814	 * Handles the end of an animation.
58815	 * @protected
58816	 * @param {Event} event - The event arguments.
58817	 */
58818	Owl.prototype.onTransitionEnd = function(event) {
58819
58820		// if css2 animation then event object is undefined
58821		if (event !== undefined) {
58822			event.stopPropagation();
58823
58824			// Catch only owl-stage transitionEnd event
58825			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
58826				return false;
58827			}
58828		}
58829
58830		this.leave('animating');
58831		this.trigger('translated');
58832	};
58833
58834	/**
58835	 * Gets viewport width.
58836	 * @protected
58837	 * @return {Number} - The width in pixel.
58838	 */
58839	Owl.prototype.viewport = function() {
58840		var width;
58841		if (this.options.responsiveBaseElement !== window) {
58842			width = $(this.options.responsiveBaseElement).width();
58843		} else if (window.innerWidth) {
58844			width = window.innerWidth;
58845		} else if (document.documentElement && document.documentElement.clientWidth) {
58846			width = document.documentElement.clientWidth;
58847		} else {
58848			console.warn('Can not detect viewport width.');
58849		}
58850		return width;
58851	};
58852
58853	/**
58854	 * Replaces the current content.
58855	 * @public
58856	 * @param {HTMLElement|jQuery|String} content - The new content.
58857	 */
58858	Owl.prototype.replace = function(content) {
58859		this.$stage.empty();
58860		this._items = [];
58861
58862		if (content) {
58863			content = (content instanceof jQuery) ? content : $(content);
58864		}
58865
58866		if (this.settings.nestedItemSelector) {
58867			content = content.find('.' + this.settings.nestedItemSelector);
58868		}
58869
58870		content.filter(function() {
58871			return this.nodeType === 1;
58872		}).each($.proxy(function(index, item) {
58873			item = this.prepare(item);
58874			this.$stage.append(item);
58875			this._items.push(item);
58876			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
58877		}, this));
58878
58879		this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
58880
58881		this.invalidate('items');
58882	};
58883
58884	/**
58885	 * Adds an item.
58886	 * @todo Use `item` instead of `content` for the event arguments.
58887	 * @public
58888	 * @param {HTMLElement|jQuery|String} content - The item content to add.
58889	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
58890	 */
58891	Owl.prototype.add = function(content, position) {
58892		var current = this.relative(this._current);
58893
58894		position = position === undefined ? this._items.length : this.normalize(position, true);
58895		content = content instanceof jQuery ? content : $(content);
58896
58897		this.trigger('add', { content: content, position: position });
58898
58899		content = this.prepare(content);
58900
58901		if (this._items.length === 0 || position === this._items.length) {
58902			this._items.length === 0 && this.$stage.append(content);
58903			this._items.length !== 0 && this._items[position - 1].after(content);
58904			this._items.push(content);
58905			this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
58906		} else {
58907			this._items[position].before(content);
58908			this._items.splice(position, 0, content);
58909			this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
58910		}
58911
58912		this._items[current] && this.reset(this._items[current].index());
58913
58914		this.invalidate('items');
58915
58916		this.trigger('added', { content: content, position: position });
58917	};
58918
58919	/**
58920	 * Removes an item by its position.
58921	 * @todo Use `item` instead of `content` for the event arguments.
58922	 * @public
58923	 * @param {Number} position - The relative position of the item to remove.
58924	 */
58925	Owl.prototype.remove = function(position) {
58926		position = this.normalize(position, true);
58927
58928		if (position === undefined) {
58929			return;
58930		}
58931
58932		this.trigger('remove', { content: this._items[position], position: position });
58933
58934		this._items[position].remove();
58935		this._items.splice(position, 1);
58936		this._mergers.splice(position, 1);
58937
58938		this.invalidate('items');
58939
58940		this.trigger('removed', { content: null, position: position });
58941	};
58942
58943	/**
58944	 * Preloads images with auto width.
58945	 * @todo Replace by a more generic approach
58946	 * @protected
58947	 */
58948	Owl.prototype.preloadAutoWidthImages = function(images) {
58949		images.each($.proxy(function(i, element) {
58950			this.enter('pre-loading');
58951			element = $(element);
58952			$(new Image()).one('load', $.proxy(function(e) {
58953				element.attr('src', e.target.src);
58954				element.css('opacity', 1);
58955				this.leave('pre-loading');
58956				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
58957			}, this)).attr('src', (window.devicePixelRatio > 1) ? element.attr('data-src-retina') : element.attr('data-src') || element.attr('src'));
58958		}, this));
58959	};
58960
58961	/**
58962	 * Destroys the carousel.
58963	 * @public
58964	 */
58965	Owl.prototype.destroy = function() {
58966
58967		this.$element.off('.owl.core');
58968		this.$stage.off('.owl.core');
58969		$(document).off('.owl.core');
58970
58971		if (this.settings.responsive !== false) {
58972			window.clearTimeout(this.resizeTimer);
58973			this.off(window, 'resize', this._handlers.onThrottledResize);
58974		}
58975
58976		for (var i in this._plugins) {
58977			this._plugins[i].destroy();
58978		}
58979
58980		this.$stage.children('.cloned').remove();
58981
58982		this.$stage.unwrap();
58983		this.$stage.children().contents().unwrap();
58984		this.$stage.children().unwrap();
58985		this.$stage.remove();
58986		this.$element
58987			.removeClass(this.options.refreshClass)
58988			.removeClass(this.options.loadingClass)
58989			.removeClass(this.options.loadedClass)
58990			.removeClass(this.options.rtlClass)
58991			.removeClass(this.options.dragClass)
58992			.removeClass(this.options.grabClass)
58993			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
58994			.removeData('owl.carousel');
58995	};
58996
58997	/**
58998	 * Operators to calculate right-to-left and left-to-right.
58999	 * @protected
59000	 * @param {Number} [a] - The left side operand.
59001	 * @param {String} [o] - The operator.
59002	 * @param {Number} [b] - The right side operand.
59003	 */
59004	Owl.prototype.op = function(a, o, b) {
59005		var rtl = this.settings.rtl;
59006		switch (o) {
59007			case '<':
59008				return rtl ? a > b : a < b;
59009			case '>':
59010				return rtl ? a < b : a > b;
59011			case '>=':
59012				return rtl ? a <= b : a >= b;
59013			case '<=':
59014				return rtl ? a >= b : a <= b;
59015			default:
59016				break;
59017		}
59018	};
59019
59020	/**
59021	 * Attaches to an internal event.
59022	 * @protected
59023	 * @param {HTMLElement} element - The event source.
59024	 * @param {String} event - The event name.
59025	 * @param {Function} listener - The event handler to attach.
59026	 * @param {Boolean} capture - Wether the event should be handled at the capturing p
vendor: 6,976 bytes, lines 59026-59266
59026hase or not.
59027	 */
59028	Owl.prototype.on = function(element, event, listener, capture) {
59029		if (element.addEventListener) {
59030			element.addEventListener(event, listener, capture);
59031		} else if (element.attachEvent) {
59032			element.attachEvent('on' + event, listener);
59033		}
59034	};
59035
59036	/**
59037	 * Detaches from an internal event.
59038	 * @protected
59039	 * @param {HTMLElement} element - The event source.
59040	 * @param {String} event - The event name.
59041	 * @param {Function} listener - The attached event handler to detach.
59042	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
59043	 */
59044	Owl.prototype.off = function(element, event, listener, capture) {
59045		if (element.removeEventListener) {
59046			element.removeEventListener(event, listener, capture);
59047		} else if (element.detachEvent) {
59048			element.detachEvent('on' + event, listener);
59049		}
59050	};
59051
59052	/**
59053	 * Triggers a public event.
59054	 * @todo Remove `status`, `relatedTarget` should be used instead.
59055	 * @protected
59056	 * @param {String} name - The event name.
59057	 * @param {*} [data=null] - The event data.
59058	 * @param {String} [namespace=carousel] - The event namespace.
59059	 * @param {String} [state] - The state which is associated with the event.
59060	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
59061	 * @returns {Event} - The event arguments.
59062	 */
59063	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
59064		var status = {
59065			item: { count: this._items.length, index: this.current() }
59066		}, handler = $.camelCase(
59067			$.grep([ 'on', name, namespace ], function(v) { return v })
59068				.join('-').toLowerCase()
59069		), event = $.Event(
59070			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
59071			$.extend({ relatedTarget: this }, status, data)
59072		);
59073
59074		if (!this._supress[name]) {
59075			$.each(this._plugins, function(name, plugin) {
59076				if (plugin.onTrigger) {
59077					plugin.onTrigger(event);
59078				}
59079			});
59080
59081			this.register({ type: Owl.Type.Event, name: name });
59082			this.$element.trigger(event);
59083
59084			if (this.settings && typeof this.settings[handler] === 'function') {
59085				this.settings[handler].call(this, event);
59086			}
59087		}
59088
59089		return event;
59090	};
59091
59092	/**
59093	 * Enters a state.
59094	 * @param name - The state name.
59095	 */
59096	Owl.prototype.enter = function(name) {
59097		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
59098			if (this._states.current[name] === undefined) {
59099				this._states.current[name] = 0;
59100			}
59101
59102			this._states.current[name]++;
59103		}, this));
59104	};
59105
59106	/**
59107	 * Leaves a state.
59108	 * @param name - The state name.
59109	 */
59110	Owl.prototype.leave = function(name) {
59111		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
59112			this._states.current[name]--;
59113		}, this));
59114	};
59115
59116	/**
59117	 * Registers an event or state.
59118	 * @public
59119	 * @param {Object} object - The event or state to register.
59120	 */
59121	Owl.prototype.register = function(object) {
59122		if (object.type === Owl.Type.Event) {
59123			if (!$.event.special[object.name]) {
59124				$.event.special[object.name] = {};
59125			}
59126
59127			if (!$.event.special[object.name].owl) {
59128				var _default = $.event.special[object.name]._default;
59129				$.event.special[object.name]._default = function(e) {
59130					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
59131						return _default.apply(this, arguments);
59132					}
59133					return e.namespace && e.namespace.indexOf('owl') > -1;
59134				};
59135				$.event.special[object.name].owl = true;
59136			}
59137		} else if (object.type === Owl.Type.State) {
59138			if (!this._states.tags[object.name]) {
59139				this._states.tags[object.name] = object.tags;
59140			} else {
59141				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
59142			}
59143
59144			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
59145				return $.inArray(tag, this._states.tags[object.name]) === i;
59146			}, this));
59147		}
59148	};
59149
59150	/**
59151	 * Suppresses events.
59152	 * @protected
59153	 * @param {Array.<String>} events - The events to suppress.
59154	 */
59155	Owl.prototype.suppress = function(events) {
59156		$.each(events, $.proxy(function(index, event) {
59157			this._supress[event] = true;
59158		}, this));
59159	};
59160
59161	/**
59162	 * Releases suppressed events.
59163	 * @protected
59164	 * @param {Array.<String>} events - The events to release.
59165	 */
59166	Owl.prototype.release = function(events) {
59167		$.each(events, $.proxy(function(index, event) {
59168			delete this._supress[event];
59169		}, this));
59170	};
59171
59172	/**
59173	 * Gets unified pointer coordinates from event.
59174	 * @todo #261
59175	 * @protected
59176	 * @param {Event} - The `mousedown` or `touchstart` event.
59177	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
59178	 */
59179	Owl.prototype.pointer = function(event) {
59180		var result = { x: null, y: null };
59181
59182		event = event.originalEvent || event || window.event;
59183
59184		event = event.touches && event.touches.length ?
59185			event.touches[0] : event.changedTouches && event.changedTouches.length ?
59186				event.changedTouches[0] : event;
59187
59188		if (event.pageX) {
59189			result.x = event.pageX;
59190			result.y = event.pageY;
59191		} else {
59192			result.x = event.clientX;
59193			result.y = event.clientY;
59194		}
59195
59196		return result;
59197	};
59198
59199	/**
59200	 * Determines if the input is a Number or something that can be coerced to a Number
59201	 * @protected
59202	 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
59203	 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
59204	 */
59205	Owl.prototype.isNumeric = function(number) {
59206		return !isNaN(parseFloat(number));
59207	};
59208
59209	/**
59210	 * Gets the difference of two vectors.
59211	 * @todo #261
59212	 * @protected
59213	 * @param {Object} - The first vector.
59214	 * @param {Object} - The second vector.
59215	 * @returns {Object} - The difference.
59216	 */
59217	Owl.prototype.difference = function(first, second) {
59218		return {
59219			x: first.x - second.x,
59220			y: first.y - second.y
59221		};
59222	};
59223
59224	/**
59225	 * The jQuery Plugin for the Owl Carousel
59226	 * @todo Navigation plugin `next` and `prev`
59227	 * @public
59228	 */
59229	$.fn.owlCarousel = function(option) {
59230		var args = Array.prototype.slice.call(arguments, 1);
59231
59232		return this.each(function() {
59233			var $this = $(this),
59234				data = $this.data('owl.carousel');
59235
59236			if (!data) {
59237				data = new Owl(this, typeof option == 'object' && option);
59238				$this.data('owl.carousel', data);
59239
59240				$.each([
59241					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
59242				], function(i, event) {
59243					data.register({ type: Owl.Type.Event, name: event });
59244					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
59245						if (e.namespace && e.relatedTarget !== this) {
59246							this.suppress([ event ]);
59247							data[event].apply(this, [].slice.call(arguments, 1));
59248							this.release([ event ]);
59249						}
59250					}, data));
59251				});
59252			}
59253
59254			if (typeof option == 'string' && option.charAt(0) !== '_') {
59255				data[option].apply(data, args);
59256			}
59257		});
59258	};
59259
59260	/**
59261	 * The constructor for the jQuery Plugin
59262	 * @public
59263	 */
59264	$.fn.owlCarousel.Constructor = Owl;
59265
59266})(window.Zepto || window.jQuery, window, document);
vendor: 3,058 bytes, lines 59267-59376
59267// source --> https://vibeudlejning.dk/wp-content/plugins/wpvr-pro/admin/js/jquery.cookie.js?ver=1 
59268/*!
59269 * jQuery Cookie Plugin v1.4.1
59270 * https://github.com/carhartl/jquery-cookie
59271 *
59272 * Copyright 2013 Klaus Hartl
59273 * Released under the MIT license
59274 */
59275(function (factory) {
59276	if (typeof define === 'function' && define.amd) {
59277		// AMD
59278		define(['jquery'], factory);
59279	} else if (typeof exports === 'object') {
59280		// CommonJS
59281		factory(require('jquery'));
59282	} else {
59283		// Browser globals
59284		factory(jQuery);
59285	}
59286}(function ($) {
59287
59288	var pluses = /\+/g;
59289
59290	function encode(s) {
59291		return config.raw ? s : encodeURIComponent(s);
59292	}
59293
59294	function decode(s) {
59295		return config.raw ? s : decodeURIComponent(s);
59296	}
59297
59298	function stringifyCookieValue(value) {
59299		return encode(config.json ? JSON.stringify(value) : String(value));
59300	}
59301
59302	function parseCookieValue(s) {
59303		if (s.indexOf('"') === 0) {
59304			// This is a quoted cookie as according to RFC2068, unescape...
59305			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
59306		}
59307
59308		try {
59309			// Replace server-side written pluses with spaces.
59310			// If we can't decode the cookie, ignore it, it's unusable.
59311			// If we can't parse the cookie, ignore it, it's unusable.
59312			s = decodeURIComponent(s.replace(pluses, ' '));
59313			return config.json ? JSON.parse(s) : s;
59314		} catch(e) {}
59315	}
59316
59317	function read(s, converter) {
59318		var value = config.raw ? s : parseCookieValue(s);
59319		return $.isFunction(converter) ? converter(value) : value;
59320	}
59321
59322	var config = $.cookie = function (key, value, options) {
59323
59324		// Write
59325
59326		if (value !== undefined && !$.isFunction(value)) {
59327			options = $.extend({}, config.defaults, options);
59328
59329			if (typeof options.expires === 'number') {
59330				var days = options.expires, t = options.expires = new Date();
59331				t.setTime(+t + days * 864e+5);
59332			}
59333
59334			return (document.cookie = [
59335				encode(key), '=', stringifyCookieValue(value),
59336				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
59337				options.path    ? '; path=' + options.path : '',
59338				options.domain  ? '; domain=' + options.domain : '',
59339				options.secure  ? '; secure' : ''
59340			].join(''));
59341		}
59342
59343		// Read
59344
59345		var result = key ? undefined : {};
59346
59347		// To prevent the for loop in the first place assign an empty array
59348		// in case there are no cookies at all. Also prevents odd result when
59349		// calling $.cookie().
59350		var cookies = document.cookie ? document.cookie.split('; ') : [];
59351
59352		for (var i = 0, l = cookies.length; i < l; i++) {
59353			var parts = cookies[i].split('=');
59354			var name = decode(parts.shift());
59355			var cookie = parts.join('=');
59356
59357			if (key && key === name) {
59358				// If second argument (value) is a function it's a converter...
59359				result = read(cookie, value);
59360				break;
59361			}
59362
59363			// Prevent storing a cookie that we couldn't decode.
59364			if (!key && (cookie = read(cookie)) !== undefined) {
59365				result[name] = cookie;
59366			}
59367		}
59368
59369		return result;
59370	};
59371
59372	config.defaults = {};
59373
59374	$.removeCookie = function (key, options) {
59375		if ($.cookie(key) === undefined) {
59376			return false;
59377		}
59378
59379		// Must not alter options, thus extending a fresh object...
59380		$.cookie(key, '', $.extend({}, options, { expires: -1 }));
59381		return !$.cookie(key);
59382	};
59383
59384}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.