]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD/mapillary-js/mapillary.unminified.js
Merge pull request #3268 from tomhughes/capitalisation
[rails.git] / vendor / assets / iD / iD / mapillary-js / mapillary.unminified.js
1 (function (global, factory) {
2     typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3     typeof define === 'function' && define.amd ? define(['exports'], factory) :
4     (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.mapillary = {}));
5 }(this, (function (exports) { 'use strict';
6
7     /*! *****************************************************************************
8     Copyright (c) Microsoft Corporation.
9
10     Permission to use, copy, modify, and/or distribute this software for any
11     purpose with or without fee is hereby granted.
12
13     THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14     REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15     AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16     INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17     LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18     OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19     PERFORMANCE OF THIS SOFTWARE.
20     ***************************************************************************** */
21     /* global Reflect, Promise */
22
23     var extendStatics = function(d, b) {
24         extendStatics = Object.setPrototypeOf ||
25             ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
26             function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
27         return extendStatics(d, b);
28     };
29
30     function __extends(d, b) {
31         extendStatics(d, b);
32         function __() { this.constructor = d; }
33         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
34     }
35
36     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
37     function isFunction(x) {
38         return typeof x === 'function';
39     }
40
41     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
42     var _enable_super_gross_mode_that_will_cause_bad_things = false;
43     var config = {
44         Promise: undefined,
45         set useDeprecatedSynchronousErrorHandling(value) {
46             if (value) {
47                 var error = /*@__PURE__*/ new Error();
48                 /*@__PURE__*/ console.warn('DEPRECATED! RxJS was set to use deprecated synchronous error handling behavior by code at: \n' + error.stack);
49             }
50             _enable_super_gross_mode_that_will_cause_bad_things = value;
51         },
52         get useDeprecatedSynchronousErrorHandling() {
53             return _enable_super_gross_mode_that_will_cause_bad_things;
54         },
55     };
56
57     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
58     function hostReportError(err) {
59         setTimeout(function () { throw err; }, 0);
60     }
61
62     /** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */
63     var empty$1 = {
64         closed: true,
65         next: function (value) { },
66         error: function (err) {
67             if (config.useDeprecatedSynchronousErrorHandling) {
68                 throw err;
69             }
70             else {
71                 hostReportError(err);
72             }
73         },
74         complete: function () { }
75     };
76
77     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
78     var isArray$1 = /*@__PURE__*/ (function () { return Array.isArray || (function (x) { return x && typeof x.length === 'number'; }); })();
79
80     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
81     function isObject$1(x) {
82         return x !== null && typeof x === 'object';
83     }
84
85     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
86     var UnsubscriptionErrorImpl = /*@__PURE__*/ (function () {
87         function UnsubscriptionErrorImpl(errors) {
88             Error.call(this);
89             this.message = errors ?
90                 errors.length + " errors occurred during unsubscription:\n" + errors.map(function (err, i) { return i + 1 + ") " + err.toString(); }).join('\n  ') : '';
91             this.name = 'UnsubscriptionError';
92             this.errors = errors;
93             return this;
94         }
95         UnsubscriptionErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
96         return UnsubscriptionErrorImpl;
97     })();
98     var UnsubscriptionError = UnsubscriptionErrorImpl;
99
100     /** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_UnsubscriptionError PURE_IMPORTS_END */
101     var Subscription = /*@__PURE__*/ (function () {
102         function Subscription(unsubscribe) {
103             this.closed = false;
104             this._parentOrParents = null;
105             this._subscriptions = null;
106             if (unsubscribe) {
107                 this._ctorUnsubscribe = true;
108                 this._unsubscribe = unsubscribe;
109             }
110         }
111         Subscription.prototype.unsubscribe = function () {
112             var errors;
113             if (this.closed) {
114                 return;
115             }
116             var _a = this, _parentOrParents = _a._parentOrParents, _ctorUnsubscribe = _a._ctorUnsubscribe, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions;
117             this.closed = true;
118             this._parentOrParents = null;
119             this._subscriptions = null;
120             if (_parentOrParents instanceof Subscription) {
121                 _parentOrParents.remove(this);
122             }
123             else if (_parentOrParents !== null) {
124                 for (var index = 0; index < _parentOrParents.length; ++index) {
125                     var parent_1 = _parentOrParents[index];
126                     parent_1.remove(this);
127                 }
128             }
129             if (isFunction(_unsubscribe)) {
130                 if (_ctorUnsubscribe) {
131                     this._unsubscribe = undefined;
132                 }
133                 try {
134                     _unsubscribe.call(this);
135                 }
136                 catch (e) {
137                     errors = e instanceof UnsubscriptionError ? flattenUnsubscriptionErrors(e.errors) : [e];
138                 }
139             }
140             if (isArray$1(_subscriptions)) {
141                 var index = -1;
142                 var len = _subscriptions.length;
143                 while (++index < len) {
144                     var sub = _subscriptions[index];
145                     if (isObject$1(sub)) {
146                         try {
147                             sub.unsubscribe();
148                         }
149                         catch (e) {
150                             errors = errors || [];
151                             if (e instanceof UnsubscriptionError) {
152                                 errors = errors.concat(flattenUnsubscriptionErrors(e.errors));
153                             }
154                             else {
155                                 errors.push(e);
156                             }
157                         }
158                     }
159                 }
160             }
161             if (errors) {
162                 throw new UnsubscriptionError(errors);
163             }
164         };
165         Subscription.prototype.add = function (teardown) {
166             var subscription = teardown;
167             if (!teardown) {
168                 return Subscription.EMPTY;
169             }
170             switch (typeof teardown) {
171                 case 'function':
172                     subscription = new Subscription(teardown);
173                 case 'object':
174                     if (subscription === this || subscription.closed || typeof subscription.unsubscribe !== 'function') {
175                         return subscription;
176                     }
177                     else if (this.closed) {
178                         subscription.unsubscribe();
179                         return subscription;
180                     }
181                     else if (!(subscription instanceof Subscription)) {
182                         var tmp = subscription;
183                         subscription = new Subscription();
184                         subscription._subscriptions = [tmp];
185                     }
186                     break;
187                 default: {
188                     throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.');
189                 }
190             }
191             var _parentOrParents = subscription._parentOrParents;
192             if (_parentOrParents === null) {
193                 subscription._parentOrParents = this;
194             }
195             else if (_parentOrParents instanceof Subscription) {
196                 if (_parentOrParents === this) {
197                     return subscription;
198                 }
199                 subscription._parentOrParents = [_parentOrParents, this];
200             }
201             else if (_parentOrParents.indexOf(this) === -1) {
202                 _parentOrParents.push(this);
203             }
204             else {
205                 return subscription;
206             }
207             var subscriptions = this._subscriptions;
208             if (subscriptions === null) {
209                 this._subscriptions = [subscription];
210             }
211             else {
212                 subscriptions.push(subscription);
213             }
214             return subscription;
215         };
216         Subscription.prototype.remove = function (subscription) {
217             var subscriptions = this._subscriptions;
218             if (subscriptions) {
219                 var subscriptionIndex = subscriptions.indexOf(subscription);
220                 if (subscriptionIndex !== -1) {
221                     subscriptions.splice(subscriptionIndex, 1);
222                 }
223             }
224         };
225         Subscription.EMPTY = (function (empty) {
226             empty.closed = true;
227             return empty;
228         }(new Subscription()));
229         return Subscription;
230     }());
231     function flattenUnsubscriptionErrors(errors) {
232         return errors.reduce(function (errs, err) { return errs.concat((err instanceof UnsubscriptionError) ? err.errors : err); }, []);
233     }
234
235     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
236     var rxSubscriber = /*@__PURE__*/ (function () {
237         return typeof Symbol === 'function'
238             ? /*@__PURE__*/ Symbol('rxSubscriber')
239             : '@@rxSubscriber_' + /*@__PURE__*/ Math.random();
240     })();
241
242     /** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */
243     var Subscriber = /*@__PURE__*/ (function (_super) {
244         __extends(Subscriber, _super);
245         function Subscriber(destinationOrNext, error, complete) {
246             var _this = _super.call(this) || this;
247             _this.syncErrorValue = null;
248             _this.syncErrorThrown = false;
249             _this.syncErrorThrowable = false;
250             _this.isStopped = false;
251             switch (arguments.length) {
252                 case 0:
253                     _this.destination = empty$1;
254                     break;
255                 case 1:
256                     if (!destinationOrNext) {
257                         _this.destination = empty$1;
258                         break;
259                     }
260                     if (typeof destinationOrNext === 'object') {
261                         if (destinationOrNext instanceof Subscriber) {
262                             _this.syncErrorThrowable = destinationOrNext.syncErrorThrowable;
263                             _this.destination = destinationOrNext;
264                             destinationOrNext.add(_this);
265                         }
266                         else {
267                             _this.syncErrorThrowable = true;
268                             _this.destination = new SafeSubscriber(_this, destinationOrNext);
269                         }
270                         break;
271                     }
272                 default:
273                     _this.syncErrorThrowable = true;
274                     _this.destination = new SafeSubscriber(_this, destinationOrNext, error, complete);
275                     break;
276             }
277             return _this;
278         }
279         Subscriber.prototype[rxSubscriber] = function () { return this; };
280         Subscriber.create = function (next, error, complete) {
281             var subscriber = new Subscriber(next, error, complete);
282             subscriber.syncErrorThrowable = false;
283             return subscriber;
284         };
285         Subscriber.prototype.next = function (value) {
286             if (!this.isStopped) {
287                 this._next(value);
288             }
289         };
290         Subscriber.prototype.error = function (err) {
291             if (!this.isStopped) {
292                 this.isStopped = true;
293                 this._error(err);
294             }
295         };
296         Subscriber.prototype.complete = function () {
297             if (!this.isStopped) {
298                 this.isStopped = true;
299                 this._complete();
300             }
301         };
302         Subscriber.prototype.unsubscribe = function () {
303             if (this.closed) {
304                 return;
305             }
306             this.isStopped = true;
307             _super.prototype.unsubscribe.call(this);
308         };
309         Subscriber.prototype._next = function (value) {
310             this.destination.next(value);
311         };
312         Subscriber.prototype._error = function (err) {
313             this.destination.error(err);
314             this.unsubscribe();
315         };
316         Subscriber.prototype._complete = function () {
317             this.destination.complete();
318             this.unsubscribe();
319         };
320         Subscriber.prototype._unsubscribeAndRecycle = function () {
321             var _parentOrParents = this._parentOrParents;
322             this._parentOrParents = null;
323             this.unsubscribe();
324             this.closed = false;
325             this.isStopped = false;
326             this._parentOrParents = _parentOrParents;
327             return this;
328         };
329         return Subscriber;
330     }(Subscription));
331     var SafeSubscriber = /*@__PURE__*/ (function (_super) {
332         __extends(SafeSubscriber, _super);
333         function SafeSubscriber(_parentSubscriber, observerOrNext, error, complete) {
334             var _this = _super.call(this) || this;
335             _this._parentSubscriber = _parentSubscriber;
336             var next;
337             var context = _this;
338             if (isFunction(observerOrNext)) {
339                 next = observerOrNext;
340             }
341             else if (observerOrNext) {
342                 next = observerOrNext.next;
343                 error = observerOrNext.error;
344                 complete = observerOrNext.complete;
345                 if (observerOrNext !== empty$1) {
346                     context = Object.create(observerOrNext);
347                     if (isFunction(context.unsubscribe)) {
348                         _this.add(context.unsubscribe.bind(context));
349                     }
350                     context.unsubscribe = _this.unsubscribe.bind(_this);
351                 }
352             }
353             _this._context = context;
354             _this._next = next;
355             _this._error = error;
356             _this._complete = complete;
357             return _this;
358         }
359         SafeSubscriber.prototype.next = function (value) {
360             if (!this.isStopped && this._next) {
361                 var _parentSubscriber = this._parentSubscriber;
362                 if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
363                     this.__tryOrUnsub(this._next, value);
364                 }
365                 else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) {
366                     this.unsubscribe();
367                 }
368             }
369         };
370         SafeSubscriber.prototype.error = function (err) {
371             if (!this.isStopped) {
372                 var _parentSubscriber = this._parentSubscriber;
373                 var useDeprecatedSynchronousErrorHandling = config.useDeprecatedSynchronousErrorHandling;
374                 if (this._error) {
375                     if (!useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
376                         this.__tryOrUnsub(this._error, err);
377                         this.unsubscribe();
378                     }
379                     else {
380                         this.__tryOrSetError(_parentSubscriber, this._error, err);
381                         this.unsubscribe();
382                     }
383                 }
384                 else if (!_parentSubscriber.syncErrorThrowable) {
385                     this.unsubscribe();
386                     if (useDeprecatedSynchronousErrorHandling) {
387                         throw err;
388                     }
389                     hostReportError(err);
390                 }
391                 else {
392                     if (useDeprecatedSynchronousErrorHandling) {
393                         _parentSubscriber.syncErrorValue = err;
394                         _parentSubscriber.syncErrorThrown = true;
395                     }
396                     else {
397                         hostReportError(err);
398                     }
399                     this.unsubscribe();
400                 }
401             }
402         };
403         SafeSubscriber.prototype.complete = function () {
404             var _this = this;
405             if (!this.isStopped) {
406                 var _parentSubscriber = this._parentSubscriber;
407                 if (this._complete) {
408                     var wrappedComplete = function () { return _this._complete.call(_this._context); };
409                     if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
410                         this.__tryOrUnsub(wrappedComplete);
411                         this.unsubscribe();
412                     }
413                     else {
414                         this.__tryOrSetError(_parentSubscriber, wrappedComplete);
415                         this.unsubscribe();
416                     }
417                 }
418                 else {
419                     this.unsubscribe();
420                 }
421             }
422         };
423         SafeSubscriber.prototype.__tryOrUnsub = function (fn, value) {
424             try {
425                 fn.call(this._context, value);
426             }
427             catch (err) {
428                 this.unsubscribe();
429                 if (config.useDeprecatedSynchronousErrorHandling) {
430                     throw err;
431                 }
432                 else {
433                     hostReportError(err);
434                 }
435             }
436         };
437         SafeSubscriber.prototype.__tryOrSetError = function (parent, fn, value) {
438             if (!config.useDeprecatedSynchronousErrorHandling) {
439                 throw new Error('bad call');
440             }
441             try {
442                 fn.call(this._context, value);
443             }
444             catch (err) {
445                 if (config.useDeprecatedSynchronousErrorHandling) {
446                     parent.syncErrorValue = err;
447                     parent.syncErrorThrown = true;
448                     return true;
449                 }
450                 else {
451                     hostReportError(err);
452                     return true;
453                 }
454             }
455             return false;
456         };
457         SafeSubscriber.prototype._unsubscribe = function () {
458             var _parentSubscriber = this._parentSubscriber;
459             this._context = null;
460             this._parentSubscriber = null;
461             _parentSubscriber.unsubscribe();
462         };
463         return SafeSubscriber;
464     }(Subscriber));
465
466     /** PURE_IMPORTS_START _Subscriber PURE_IMPORTS_END */
467     function canReportError(observer) {
468         while (observer) {
469             var _a = observer, closed_1 = _a.closed, destination = _a.destination, isStopped = _a.isStopped;
470             if (closed_1 || isStopped) {
471                 return false;
472             }
473             else if (destination && destination instanceof Subscriber) {
474                 observer = destination;
475             }
476             else {
477                 observer = null;
478             }
479         }
480         return true;
481     }
482
483     /** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */
484     function toSubscriber(nextOrObserver, error, complete) {
485         if (nextOrObserver) {
486             if (nextOrObserver instanceof Subscriber) {
487                 return nextOrObserver;
488             }
489             if (nextOrObserver[rxSubscriber]) {
490                 return nextOrObserver[rxSubscriber]();
491             }
492         }
493         if (!nextOrObserver && !error && !complete) {
494             return new Subscriber(empty$1);
495         }
496         return new Subscriber(nextOrObserver, error, complete);
497     }
498
499     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
500     var observable = /*@__PURE__*/ (function () { return typeof Symbol === 'function' && Symbol.observable || '@@observable'; })();
501
502     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
503     function identity(x) {
504         return x;
505     }
506
507     /** PURE_IMPORTS_START _identity PURE_IMPORTS_END */
508     function pipe() {
509         var fns = [];
510         for (var _i = 0; _i < arguments.length; _i++) {
511             fns[_i] = arguments[_i];
512         }
513         return pipeFromArray(fns);
514     }
515     function pipeFromArray(fns) {
516         if (fns.length === 0) {
517             return identity;
518         }
519         if (fns.length === 1) {
520             return fns[0];
521         }
522         return function piped(input) {
523             return fns.reduce(function (prev, fn) { return fn(prev); }, input);
524         };
525     }
526
527     /** PURE_IMPORTS_START _util_canReportError,_util_toSubscriber,_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */
528     var Observable = /*@__PURE__*/ (function () {
529         function Observable(subscribe) {
530             this._isScalar = false;
531             if (subscribe) {
532                 this._subscribe = subscribe;
533             }
534         }
535         Observable.prototype.lift = function (operator) {
536             var observable = new Observable();
537             observable.source = this;
538             observable.operator = operator;
539             return observable;
540         };
541         Observable.prototype.subscribe = function (observerOrNext, error, complete) {
542             var operator = this.operator;
543             var sink = toSubscriber(observerOrNext, error, complete);
544             if (operator) {
545                 sink.add(operator.call(sink, this.source));
546             }
547             else {
548                 sink.add(this.source || (config.useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ?
549                     this._subscribe(sink) :
550                     this._trySubscribe(sink));
551             }
552             if (config.useDeprecatedSynchronousErrorHandling) {
553                 if (sink.syncErrorThrowable) {
554                     sink.syncErrorThrowable = false;
555                     if (sink.syncErrorThrown) {
556                         throw sink.syncErrorValue;
557                     }
558                 }
559             }
560             return sink;
561         };
562         Observable.prototype._trySubscribe = function (sink) {
563             try {
564                 return this._subscribe(sink);
565             }
566             catch (err) {
567                 if (config.useDeprecatedSynchronousErrorHandling) {
568                     sink.syncErrorThrown = true;
569                     sink.syncErrorValue = err;
570                 }
571                 if (canReportError(sink)) {
572                     sink.error(err);
573                 }
574                 else {
575                     console.warn(err);
576                 }
577             }
578         };
579         Observable.prototype.forEach = function (next, promiseCtor) {
580             var _this = this;
581             promiseCtor = getPromiseCtor(promiseCtor);
582             return new promiseCtor(function (resolve, reject) {
583                 var subscription;
584                 subscription = _this.subscribe(function (value) {
585                     try {
586                         next(value);
587                     }
588                     catch (err) {
589                         reject(err);
590                         if (subscription) {
591                             subscription.unsubscribe();
592                         }
593                     }
594                 }, reject, resolve);
595             });
596         };
597         Observable.prototype._subscribe = function (subscriber) {
598             var source = this.source;
599             return source && source.subscribe(subscriber);
600         };
601         Observable.prototype[observable] = function () {
602             return this;
603         };
604         Observable.prototype.pipe = function () {
605             var operations = [];
606             for (var _i = 0; _i < arguments.length; _i++) {
607                 operations[_i] = arguments[_i];
608             }
609             if (operations.length === 0) {
610                 return this;
611             }
612             return pipeFromArray(operations)(this);
613         };
614         Observable.prototype.toPromise = function (promiseCtor) {
615             var _this = this;
616             promiseCtor = getPromiseCtor(promiseCtor);
617             return new promiseCtor(function (resolve, reject) {
618                 var value;
619                 _this.subscribe(function (x) { return value = x; }, function (err) { return reject(err); }, function () { return resolve(value); });
620             });
621         };
622         Observable.create = function (subscribe) {
623             return new Observable(subscribe);
624         };
625         return Observable;
626     }());
627     function getPromiseCtor(promiseCtor) {
628         if (!promiseCtor) {
629             promiseCtor = Promise;
630         }
631         if (!promiseCtor) {
632             throw new Error('no Promise impl found');
633         }
634         return promiseCtor;
635     }
636
637     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
638     var ObjectUnsubscribedErrorImpl = /*@__PURE__*/ (function () {
639         function ObjectUnsubscribedErrorImpl() {
640             Error.call(this);
641             this.message = 'object unsubscribed';
642             this.name = 'ObjectUnsubscribedError';
643             return this;
644         }
645         ObjectUnsubscribedErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
646         return ObjectUnsubscribedErrorImpl;
647     })();
648     var ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl;
649
650     /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */
651     var SubjectSubscription = /*@__PURE__*/ (function (_super) {
652         __extends(SubjectSubscription, _super);
653         function SubjectSubscription(subject, subscriber) {
654             var _this = _super.call(this) || this;
655             _this.subject = subject;
656             _this.subscriber = subscriber;
657             _this.closed = false;
658             return _this;
659         }
660         SubjectSubscription.prototype.unsubscribe = function () {
661             if (this.closed) {
662                 return;
663             }
664             this.closed = true;
665             var subject = this.subject;
666             var observers = subject.observers;
667             this.subject = null;
668             if (!observers || observers.length === 0 || subject.isStopped || subject.closed) {
669                 return;
670             }
671             var subscriberIndex = observers.indexOf(this.subscriber);
672             if (subscriberIndex !== -1) {
673                 observers.splice(subscriberIndex, 1);
674             }
675         };
676         return SubjectSubscription;
677     }(Subscription));
678
679     /** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */
680     var SubjectSubscriber = /*@__PURE__*/ (function (_super) {
681         __extends(SubjectSubscriber, _super);
682         function SubjectSubscriber(destination) {
683             var _this = _super.call(this, destination) || this;
684             _this.destination = destination;
685             return _this;
686         }
687         return SubjectSubscriber;
688     }(Subscriber));
689     var Subject = /*@__PURE__*/ (function (_super) {
690         __extends(Subject, _super);
691         function Subject() {
692             var _this = _super.call(this) || this;
693             _this.observers = [];
694             _this.closed = false;
695             _this.isStopped = false;
696             _this.hasError = false;
697             _this.thrownError = null;
698             return _this;
699         }
700         Subject.prototype[rxSubscriber] = function () {
701             return new SubjectSubscriber(this);
702         };
703         Subject.prototype.lift = function (operator) {
704             var subject = new AnonymousSubject(this, this);
705             subject.operator = operator;
706             return subject;
707         };
708         Subject.prototype.next = function (value) {
709             if (this.closed) {
710                 throw new ObjectUnsubscribedError();
711             }
712             if (!this.isStopped) {
713                 var observers = this.observers;
714                 var len = observers.length;
715                 var copy = observers.slice();
716                 for (var i = 0; i < len; i++) {
717                     copy[i].next(value);
718                 }
719             }
720         };
721         Subject.prototype.error = function (err) {
722             if (this.closed) {
723                 throw new ObjectUnsubscribedError();
724             }
725             this.hasError = true;
726             this.thrownError = err;
727             this.isStopped = true;
728             var observers = this.observers;
729             var len = observers.length;
730             var copy = observers.slice();
731             for (var i = 0; i < len; i++) {
732                 copy[i].error(err);
733             }
734             this.observers.length = 0;
735         };
736         Subject.prototype.complete = function () {
737             if (this.closed) {
738                 throw new ObjectUnsubscribedError();
739             }
740             this.isStopped = true;
741             var observers = this.observers;
742             var len = observers.length;
743             var copy = observers.slice();
744             for (var i = 0; i < len; i++) {
745                 copy[i].complete();
746             }
747             this.observers.length = 0;
748         };
749         Subject.prototype.unsubscribe = function () {
750             this.isStopped = true;
751             this.closed = true;
752             this.observers = null;
753         };
754         Subject.prototype._trySubscribe = function (subscriber) {
755             if (this.closed) {
756                 throw new ObjectUnsubscribedError();
757             }
758             else {
759                 return _super.prototype._trySubscribe.call(this, subscriber);
760             }
761         };
762         Subject.prototype._subscribe = function (subscriber) {
763             if (this.closed) {
764                 throw new ObjectUnsubscribedError();
765             }
766             else if (this.hasError) {
767                 subscriber.error(this.thrownError);
768                 return Subscription.EMPTY;
769             }
770             else if (this.isStopped) {
771                 subscriber.complete();
772                 return Subscription.EMPTY;
773             }
774             else {
775                 this.observers.push(subscriber);
776                 return new SubjectSubscription(this, subscriber);
777             }
778         };
779         Subject.prototype.asObservable = function () {
780             var observable = new Observable();
781             observable.source = this;
782             return observable;
783         };
784         Subject.create = function (destination, source) {
785             return new AnonymousSubject(destination, source);
786         };
787         return Subject;
788     }(Observable));
789     var AnonymousSubject = /*@__PURE__*/ (function (_super) {
790         __extends(AnonymousSubject, _super);
791         function AnonymousSubject(destination, source) {
792             var _this = _super.call(this) || this;
793             _this.destination = destination;
794             _this.source = source;
795             return _this;
796         }
797         AnonymousSubject.prototype.next = function (value) {
798             var destination = this.destination;
799             if (destination && destination.next) {
800                 destination.next(value);
801             }
802         };
803         AnonymousSubject.prototype.error = function (err) {
804             var destination = this.destination;
805             if (destination && destination.error) {
806                 this.destination.error(err);
807             }
808         };
809         AnonymousSubject.prototype.complete = function () {
810             var destination = this.destination;
811             if (destination && destination.complete) {
812                 this.destination.complete();
813             }
814         };
815         AnonymousSubject.prototype._subscribe = function (subscriber) {
816             var source = this.source;
817             if (source) {
818                 return this.source.subscribe(subscriber);
819             }
820             else {
821                 return Subscription.EMPTY;
822             }
823         };
824         return AnonymousSubject;
825     }(Subject));
826
827     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
828     function refCount() {
829         return function refCountOperatorFunction(source) {
830             return source.lift(new RefCountOperator(source));
831         };
832     }
833     var RefCountOperator = /*@__PURE__*/ (function () {
834         function RefCountOperator(connectable) {
835             this.connectable = connectable;
836         }
837         RefCountOperator.prototype.call = function (subscriber, source) {
838             var connectable = this.connectable;
839             connectable._refCount++;
840             var refCounter = new RefCountSubscriber(subscriber, connectable);
841             var subscription = source.subscribe(refCounter);
842             if (!refCounter.closed) {
843                 refCounter.connection = connectable.connect();
844             }
845             return subscription;
846         };
847         return RefCountOperator;
848     }());
849     var RefCountSubscriber = /*@__PURE__*/ (function (_super) {
850         __extends(RefCountSubscriber, _super);
851         function RefCountSubscriber(destination, connectable) {
852             var _this = _super.call(this, destination) || this;
853             _this.connectable = connectable;
854             return _this;
855         }
856         RefCountSubscriber.prototype._unsubscribe = function () {
857             var connectable = this.connectable;
858             if (!connectable) {
859                 this.connection = null;
860                 return;
861             }
862             this.connectable = null;
863             var refCount = connectable._refCount;
864             if (refCount <= 0) {
865                 this.connection = null;
866                 return;
867             }
868             connectable._refCount = refCount - 1;
869             if (refCount > 1) {
870                 this.connection = null;
871                 return;
872             }
873             var connection = this.connection;
874             var sharedConnection = connectable._connection;
875             this.connection = null;
876             if (sharedConnection && (!connection || sharedConnection === connection)) {
877                 sharedConnection.unsubscribe();
878             }
879         };
880         return RefCountSubscriber;
881     }(Subscriber));
882
883     /** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */
884     var ConnectableObservable = /*@__PURE__*/ (function (_super) {
885         __extends(ConnectableObservable, _super);
886         function ConnectableObservable(source, subjectFactory) {
887             var _this = _super.call(this) || this;
888             _this.source = source;
889             _this.subjectFactory = subjectFactory;
890             _this._refCount = 0;
891             _this._isComplete = false;
892             return _this;
893         }
894         ConnectableObservable.prototype._subscribe = function (subscriber) {
895             return this.getSubject().subscribe(subscriber);
896         };
897         ConnectableObservable.prototype.getSubject = function () {
898             var subject = this._subject;
899             if (!subject || subject.isStopped) {
900                 this._subject = this.subjectFactory();
901             }
902             return this._subject;
903         };
904         ConnectableObservable.prototype.connect = function () {
905             var connection = this._connection;
906             if (!connection) {
907                 this._isComplete = false;
908                 connection = this._connection = new Subscription();
909                 connection.add(this.source
910                     .subscribe(new ConnectableSubscriber(this.getSubject(), this)));
911                 if (connection.closed) {
912                     this._connection = null;
913                     connection = Subscription.EMPTY;
914                 }
915             }
916             return connection;
917         };
918         ConnectableObservable.prototype.refCount = function () {
919             return refCount()(this);
920         };
921         return ConnectableObservable;
922     }(Observable));
923     var connectableObservableDescriptor = /*@__PURE__*/ (function () {
924         var connectableProto = ConnectableObservable.prototype;
925         return {
926             operator: { value: null },
927             _refCount: { value: 0, writable: true },
928             _subject: { value: null, writable: true },
929             _connection: { value: null, writable: true },
930             _subscribe: { value: connectableProto._subscribe },
931             _isComplete: { value: connectableProto._isComplete, writable: true },
932             getSubject: { value: connectableProto.getSubject },
933             connect: { value: connectableProto.connect },
934             refCount: { value: connectableProto.refCount }
935         };
936     })();
937     var ConnectableSubscriber = /*@__PURE__*/ (function (_super) {
938         __extends(ConnectableSubscriber, _super);
939         function ConnectableSubscriber(destination, connectable) {
940             var _this = _super.call(this, destination) || this;
941             _this.connectable = connectable;
942             return _this;
943         }
944         ConnectableSubscriber.prototype._error = function (err) {
945             this._unsubscribe();
946             _super.prototype._error.call(this, err);
947         };
948         ConnectableSubscriber.prototype._complete = function () {
949             this.connectable._isComplete = true;
950             this._unsubscribe();
951             _super.prototype._complete.call(this);
952         };
953         ConnectableSubscriber.prototype._unsubscribe = function () {
954             var connectable = this.connectable;
955             if (connectable) {
956                 this.connectable = null;
957                 var connection = connectable._connection;
958                 connectable._refCount = 0;
959                 connectable._subject = null;
960                 connectable._connection = null;
961                 if (connection) {
962                     connection.unsubscribe();
963                 }
964             }
965         };
966         return ConnectableSubscriber;
967     }(SubjectSubscriber));
968
969     /** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */
970     var BehaviorSubject = /*@__PURE__*/ (function (_super) {
971         __extends(BehaviorSubject, _super);
972         function BehaviorSubject(_value) {
973             var _this = _super.call(this) || this;
974             _this._value = _value;
975             return _this;
976         }
977         Object.defineProperty(BehaviorSubject.prototype, "value", {
978             get: function () {
979                 return this.getValue();
980             },
981             enumerable: true,
982             configurable: true
983         });
984         BehaviorSubject.prototype._subscribe = function (subscriber) {
985             var subscription = _super.prototype._subscribe.call(this, subscriber);
986             if (subscription && !subscription.closed) {
987                 subscriber.next(this._value);
988             }
989             return subscription;
990         };
991         BehaviorSubject.prototype.getValue = function () {
992             if (this.hasError) {
993                 throw this.thrownError;
994             }
995             else if (this.closed) {
996                 throw new ObjectUnsubscribedError();
997             }
998             else {
999                 return this._value;
1000             }
1001         };
1002         BehaviorSubject.prototype.next = function (value) {
1003             _super.prototype.next.call(this, this._value = value);
1004         };
1005         return BehaviorSubject;
1006     }(Subject));
1007
1008     /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */
1009     var Action = /*@__PURE__*/ (function (_super) {
1010         __extends(Action, _super);
1011         function Action(scheduler, work) {
1012             return _super.call(this) || this;
1013         }
1014         Action.prototype.schedule = function (state, delay) {
1015             return this;
1016         };
1017         return Action;
1018     }(Subscription));
1019
1020     /** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */
1021     var AsyncAction = /*@__PURE__*/ (function (_super) {
1022         __extends(AsyncAction, _super);
1023         function AsyncAction(scheduler, work) {
1024             var _this = _super.call(this, scheduler, work) || this;
1025             _this.scheduler = scheduler;
1026             _this.work = work;
1027             _this.pending = false;
1028             return _this;
1029         }
1030         AsyncAction.prototype.schedule = function (state, delay) {
1031             if (delay === void 0) {
1032                 delay = 0;
1033             }
1034             if (this.closed) {
1035                 return this;
1036             }
1037             this.state = state;
1038             var id = this.id;
1039             var scheduler = this.scheduler;
1040             if (id != null) {
1041                 this.id = this.recycleAsyncId(scheduler, id, delay);
1042             }
1043             this.pending = true;
1044             this.delay = delay;
1045             this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
1046             return this;
1047         };
1048         AsyncAction.prototype.requestAsyncId = function (scheduler, id, delay) {
1049             if (delay === void 0) {
1050                 delay = 0;
1051             }
1052             return setInterval(scheduler.flush.bind(scheduler, this), delay);
1053         };
1054         AsyncAction.prototype.recycleAsyncId = function (scheduler, id, delay) {
1055             if (delay === void 0) {
1056                 delay = 0;
1057             }
1058             if (delay !== null && this.delay === delay && this.pending === false) {
1059                 return id;
1060             }
1061             clearInterval(id);
1062             return undefined;
1063         };
1064         AsyncAction.prototype.execute = function (state, delay) {
1065             if (this.closed) {
1066                 return new Error('executing a cancelled action');
1067             }
1068             this.pending = false;
1069             var error = this._execute(state, delay);
1070             if (error) {
1071                 return error;
1072             }
1073             else if (this.pending === false && this.id != null) {
1074                 this.id = this.recycleAsyncId(this.scheduler, this.id, null);
1075             }
1076         };
1077         AsyncAction.prototype._execute = function (state, delay) {
1078             var errored = false;
1079             var errorValue = undefined;
1080             try {
1081                 this.work(state);
1082             }
1083             catch (e) {
1084                 errored = true;
1085                 errorValue = !!e && e || new Error(e);
1086             }
1087             if (errored) {
1088                 this.unsubscribe();
1089                 return errorValue;
1090             }
1091         };
1092         AsyncAction.prototype._unsubscribe = function () {
1093             var id = this.id;
1094             var scheduler = this.scheduler;
1095             var actions = scheduler.actions;
1096             var index = actions.indexOf(this);
1097             this.work = null;
1098             this.state = null;
1099             this.pending = false;
1100             this.scheduler = null;
1101             if (index !== -1) {
1102                 actions.splice(index, 1);
1103             }
1104             if (id != null) {
1105                 this.id = this.recycleAsyncId(scheduler, id, null);
1106             }
1107             this.delay = null;
1108         };
1109         return AsyncAction;
1110     }(Action));
1111
1112     /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */
1113     var QueueAction = /*@__PURE__*/ (function (_super) {
1114         __extends(QueueAction, _super);
1115         function QueueAction(scheduler, work) {
1116             var _this = _super.call(this, scheduler, work) || this;
1117             _this.scheduler = scheduler;
1118             _this.work = work;
1119             return _this;
1120         }
1121         QueueAction.prototype.schedule = function (state, delay) {
1122             if (delay === void 0) {
1123                 delay = 0;
1124             }
1125             if (delay > 0) {
1126                 return _super.prototype.schedule.call(this, state, delay);
1127             }
1128             this.delay = delay;
1129             this.state = state;
1130             this.scheduler.flush(this);
1131             return this;
1132         };
1133         QueueAction.prototype.execute = function (state, delay) {
1134             return (delay > 0 || this.closed) ?
1135                 _super.prototype.execute.call(this, state, delay) :
1136                 this._execute(state, delay);
1137         };
1138         QueueAction.prototype.requestAsyncId = function (scheduler, id, delay) {
1139             if (delay === void 0) {
1140                 delay = 0;
1141             }
1142             if ((delay !== null && delay > 0) || (delay === null && this.delay > 0)) {
1143                 return _super.prototype.requestAsyncId.call(this, scheduler, id, delay);
1144             }
1145             return scheduler.flush(this);
1146         };
1147         return QueueAction;
1148     }(AsyncAction));
1149
1150     var Scheduler = /*@__PURE__*/ (function () {
1151         function Scheduler(SchedulerAction, now) {
1152             if (now === void 0) {
1153                 now = Scheduler.now;
1154             }
1155             this.SchedulerAction = SchedulerAction;
1156             this.now = now;
1157         }
1158         Scheduler.prototype.schedule = function (work, delay, state) {
1159             if (delay === void 0) {
1160                 delay = 0;
1161             }
1162             return new this.SchedulerAction(this, work).schedule(state, delay);
1163         };
1164         Scheduler.now = function () { return Date.now(); };
1165         return Scheduler;
1166     }());
1167
1168     /** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */
1169     var AsyncScheduler = /*@__PURE__*/ (function (_super) {
1170         __extends(AsyncScheduler, _super);
1171         function AsyncScheduler(SchedulerAction, now) {
1172             if (now === void 0) {
1173                 now = Scheduler.now;
1174             }
1175             var _this = _super.call(this, SchedulerAction, function () {
1176                 if (AsyncScheduler.delegate && AsyncScheduler.delegate !== _this) {
1177                     return AsyncScheduler.delegate.now();
1178                 }
1179                 else {
1180                     return now();
1181                 }
1182             }) || this;
1183             _this.actions = [];
1184             _this.active = false;
1185             _this.scheduled = undefined;
1186             return _this;
1187         }
1188         AsyncScheduler.prototype.schedule = function (work, delay, state) {
1189             if (delay === void 0) {
1190                 delay = 0;
1191             }
1192             if (AsyncScheduler.delegate && AsyncScheduler.delegate !== this) {
1193                 return AsyncScheduler.delegate.schedule(work, delay, state);
1194             }
1195             else {
1196                 return _super.prototype.schedule.call(this, work, delay, state);
1197             }
1198         };
1199         AsyncScheduler.prototype.flush = function (action) {
1200             var actions = this.actions;
1201             if (this.active) {
1202                 actions.push(action);
1203                 return;
1204             }
1205             var error;
1206             this.active = true;
1207             do {
1208                 if (error = action.execute(action.state, action.delay)) {
1209                     break;
1210                 }
1211             } while (action = actions.shift());
1212             this.active = false;
1213             if (error) {
1214                 while (action = actions.shift()) {
1215                     action.unsubscribe();
1216                 }
1217                 throw error;
1218             }
1219         };
1220         return AsyncScheduler;
1221     }(Scheduler));
1222
1223     /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */
1224     var QueueScheduler = /*@__PURE__*/ (function (_super) {
1225         __extends(QueueScheduler, _super);
1226         function QueueScheduler() {
1227             return _super !== null && _super.apply(this, arguments) || this;
1228         }
1229         return QueueScheduler;
1230     }(AsyncScheduler));
1231
1232     /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */
1233     var queueScheduler = /*@__PURE__*/ new QueueScheduler(QueueAction);
1234     var queue = queueScheduler;
1235
1236     /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
1237     var EMPTY$1 = /*@__PURE__*/ new Observable(function (subscriber) { return subscriber.complete(); });
1238     function empty(scheduler) {
1239         return scheduler ? emptyScheduled(scheduler) : EMPTY$1;
1240     }
1241     function emptyScheduled(scheduler) {
1242         return new Observable(function (subscriber) { return scheduler.schedule(function () { return subscriber.complete(); }); });
1243     }
1244
1245     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1246     function isScheduler(value) {
1247         return value && typeof value.schedule === 'function';
1248     }
1249
1250     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1251     var subscribeToArray = function (array) {
1252         return function (subscriber) {
1253             for (var i = 0, len = array.length; i < len && !subscriber.closed; i++) {
1254                 subscriber.next(array[i]);
1255             }
1256             subscriber.complete();
1257         };
1258     };
1259
1260     /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
1261     function scheduleArray(input, scheduler) {
1262         return new Observable(function (subscriber) {
1263             var sub = new Subscription();
1264             var i = 0;
1265             sub.add(scheduler.schedule(function () {
1266                 if (i === input.length) {
1267                     subscriber.complete();
1268                     return;
1269                 }
1270                 subscriber.next(input[i++]);
1271                 if (!subscriber.closed) {
1272                     sub.add(this.schedule());
1273                 }
1274             }));
1275             return sub;
1276         });
1277     }
1278
1279     /** PURE_IMPORTS_START _Observable,_util_subscribeToArray,_scheduled_scheduleArray PURE_IMPORTS_END */
1280     function fromArray(input, scheduler) {
1281         if (!scheduler) {
1282             return new Observable(subscribeToArray(input));
1283         }
1284         else {
1285             return scheduleArray(input, scheduler);
1286         }
1287     }
1288
1289     /** PURE_IMPORTS_START _util_isScheduler,_fromArray,_scheduled_scheduleArray PURE_IMPORTS_END */
1290     function of() {
1291         var args = [];
1292         for (var _i = 0; _i < arguments.length; _i++) {
1293             args[_i] = arguments[_i];
1294         }
1295         var scheduler = args[args.length - 1];
1296         if (isScheduler(scheduler)) {
1297             args.pop();
1298             return scheduleArray(args, scheduler);
1299         }
1300         else {
1301             return fromArray(args);
1302         }
1303     }
1304
1305     /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
1306     function throwError(error, scheduler) {
1307         if (!scheduler) {
1308             return new Observable(function (subscriber) { return subscriber.error(error); });
1309         }
1310         else {
1311             return new Observable(function (subscriber) { return scheduler.schedule(dispatch$1, 0, { error: error, subscriber: subscriber }); });
1312         }
1313     }
1314     function dispatch$1(_a) {
1315         var error = _a.error, subscriber = _a.subscriber;
1316         subscriber.error(error);
1317     }
1318
1319     /** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */
1320     var Notification = /*@__PURE__*/ (function () {
1321         function Notification(kind, value, error) {
1322             this.kind = kind;
1323             this.value = value;
1324             this.error = error;
1325             this.hasValue = kind === 'N';
1326         }
1327         Notification.prototype.observe = function (observer) {
1328             switch (this.kind) {
1329                 case 'N':
1330                     return observer.next && observer.next(this.value);
1331                 case 'E':
1332                     return observer.error && observer.error(this.error);
1333                 case 'C':
1334                     return observer.complete && observer.complete();
1335             }
1336         };
1337         Notification.prototype.do = function (next, error, complete) {
1338             var kind = this.kind;
1339             switch (kind) {
1340                 case 'N':
1341                     return next && next(this.value);
1342                 case 'E':
1343                     return error && error(this.error);
1344                 case 'C':
1345                     return complete && complete();
1346             }
1347         };
1348         Notification.prototype.accept = function (nextOrObserver, error, complete) {
1349             if (nextOrObserver && typeof nextOrObserver.next === 'function') {
1350                 return this.observe(nextOrObserver);
1351             }
1352             else {
1353                 return this.do(nextOrObserver, error, complete);
1354             }
1355         };
1356         Notification.prototype.toObservable = function () {
1357             var kind = this.kind;
1358             switch (kind) {
1359                 case 'N':
1360                     return of(this.value);
1361                 case 'E':
1362                     return throwError(this.error);
1363                 case 'C':
1364                     return empty();
1365             }
1366             throw new Error('unexpected notification kind value');
1367         };
1368         Notification.createNext = function (value) {
1369             if (typeof value !== 'undefined') {
1370                 return new Notification('N', value);
1371             }
1372             return Notification.undefinedValueNotification;
1373         };
1374         Notification.createError = function (err) {
1375             return new Notification('E', undefined, err);
1376         };
1377         Notification.createComplete = function () {
1378             return Notification.completeNotification;
1379         };
1380         Notification.completeNotification = new Notification('C');
1381         Notification.undefinedValueNotification = new Notification('N', undefined);
1382         return Notification;
1383     }());
1384
1385     /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */
1386     var ObserveOnSubscriber = /*@__PURE__*/ (function (_super) {
1387         __extends(ObserveOnSubscriber, _super);
1388         function ObserveOnSubscriber(destination, scheduler, delay) {
1389             if (delay === void 0) {
1390                 delay = 0;
1391             }
1392             var _this = _super.call(this, destination) || this;
1393             _this.scheduler = scheduler;
1394             _this.delay = delay;
1395             return _this;
1396         }
1397         ObserveOnSubscriber.dispatch = function (arg) {
1398             var notification = arg.notification, destination = arg.destination;
1399             notification.observe(destination);
1400             this.unsubscribe();
1401         };
1402         ObserveOnSubscriber.prototype.scheduleMessage = function (notification) {
1403             var destination = this.destination;
1404             destination.add(this.scheduler.schedule(ObserveOnSubscriber.dispatch, this.delay, new ObserveOnMessage(notification, this.destination)));
1405         };
1406         ObserveOnSubscriber.prototype._next = function (value) {
1407             this.scheduleMessage(Notification.createNext(value));
1408         };
1409         ObserveOnSubscriber.prototype._error = function (err) {
1410             this.scheduleMessage(Notification.createError(err));
1411             this.unsubscribe();
1412         };
1413         ObserveOnSubscriber.prototype._complete = function () {
1414             this.scheduleMessage(Notification.createComplete());
1415             this.unsubscribe();
1416         };
1417         return ObserveOnSubscriber;
1418     }(Subscriber));
1419     var ObserveOnMessage = /*@__PURE__*/ (function () {
1420         function ObserveOnMessage(notification, destination) {
1421             this.notification = notification;
1422             this.destination = destination;
1423         }
1424         return ObserveOnMessage;
1425     }());
1426
1427     /** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */
1428     var ReplaySubject = /*@__PURE__*/ (function (_super) {
1429         __extends(ReplaySubject, _super);
1430         function ReplaySubject(bufferSize, windowTime, scheduler) {
1431             if (bufferSize === void 0) {
1432                 bufferSize = Number.POSITIVE_INFINITY;
1433             }
1434             if (windowTime === void 0) {
1435                 windowTime = Number.POSITIVE_INFINITY;
1436             }
1437             var _this = _super.call(this) || this;
1438             _this.scheduler = scheduler;
1439             _this._events = [];
1440             _this._infiniteTimeWindow = false;
1441             _this._bufferSize = bufferSize < 1 ? 1 : bufferSize;
1442             _this._windowTime = windowTime < 1 ? 1 : windowTime;
1443             if (windowTime === Number.POSITIVE_INFINITY) {
1444                 _this._infiniteTimeWindow = true;
1445                 _this.next = _this.nextInfiniteTimeWindow;
1446             }
1447             else {
1448                 _this.next = _this.nextTimeWindow;
1449             }
1450             return _this;
1451         }
1452         ReplaySubject.prototype.nextInfiniteTimeWindow = function (value) {
1453             if (!this.isStopped) {
1454                 var _events = this._events;
1455                 _events.push(value);
1456                 if (_events.length > this._bufferSize) {
1457                     _events.shift();
1458                 }
1459             }
1460             _super.prototype.next.call(this, value);
1461         };
1462         ReplaySubject.prototype.nextTimeWindow = function (value) {
1463             if (!this.isStopped) {
1464                 this._events.push(new ReplayEvent(this._getNow(), value));
1465                 this._trimBufferThenGetEvents();
1466             }
1467             _super.prototype.next.call(this, value);
1468         };
1469         ReplaySubject.prototype._subscribe = function (subscriber) {
1470             var _infiniteTimeWindow = this._infiniteTimeWindow;
1471             var _events = _infiniteTimeWindow ? this._events : this._trimBufferThenGetEvents();
1472             var scheduler = this.scheduler;
1473             var len = _events.length;
1474             var subscription;
1475             if (this.closed) {
1476                 throw new ObjectUnsubscribedError();
1477             }
1478             else if (this.isStopped || this.hasError) {
1479                 subscription = Subscription.EMPTY;
1480             }
1481             else {
1482                 this.observers.push(subscriber);
1483                 subscription = new SubjectSubscription(this, subscriber);
1484             }
1485             if (scheduler) {
1486                 subscriber.add(subscriber = new ObserveOnSubscriber(subscriber, scheduler));
1487             }
1488             if (_infiniteTimeWindow) {
1489                 for (var i = 0; i < len && !subscriber.closed; i++) {
1490                     subscriber.next(_events[i]);
1491                 }
1492             }
1493             else {
1494                 for (var i = 0; i < len && !subscriber.closed; i++) {
1495                     subscriber.next(_events[i].value);
1496                 }
1497             }
1498             if (this.hasError) {
1499                 subscriber.error(this.thrownError);
1500             }
1501             else if (this.isStopped) {
1502                 subscriber.complete();
1503             }
1504             return subscription;
1505         };
1506         ReplaySubject.prototype._getNow = function () {
1507             return (this.scheduler || queue).now();
1508         };
1509         ReplaySubject.prototype._trimBufferThenGetEvents = function () {
1510             var now = this._getNow();
1511             var _bufferSize = this._bufferSize;
1512             var _windowTime = this._windowTime;
1513             var _events = this._events;
1514             var eventsCount = _events.length;
1515             var spliceCount = 0;
1516             while (spliceCount < eventsCount) {
1517                 if ((now - _events[spliceCount].time) < _windowTime) {
1518                     break;
1519                 }
1520                 spliceCount++;
1521             }
1522             if (eventsCount > _bufferSize) {
1523                 spliceCount = Math.max(spliceCount, eventsCount - _bufferSize);
1524             }
1525             if (spliceCount > 0) {
1526                 _events.splice(0, spliceCount);
1527             }
1528             return _events;
1529         };
1530         return ReplaySubject;
1531     }(Subject));
1532     var ReplayEvent = /*@__PURE__*/ (function () {
1533         function ReplayEvent(time, value) {
1534             this.time = time;
1535             this.value = value;
1536         }
1537         return ReplayEvent;
1538     }());
1539
1540     /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */
1541     var asyncScheduler = /*@__PURE__*/ new AsyncScheduler(AsyncAction);
1542     var async = asyncScheduler;
1543
1544     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1545     function noop() { }
1546
1547     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1548     var ArgumentOutOfRangeErrorImpl = /*@__PURE__*/ (function () {
1549         function ArgumentOutOfRangeErrorImpl() {
1550             Error.call(this);
1551             this.message = 'argument out of range';
1552             this.name = 'ArgumentOutOfRangeError';
1553             return this;
1554         }
1555         ArgumentOutOfRangeErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
1556         return ArgumentOutOfRangeErrorImpl;
1557     })();
1558     var ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl;
1559
1560     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1561     var EmptyErrorImpl = /*@__PURE__*/ (function () {
1562         function EmptyErrorImpl() {
1563             Error.call(this);
1564             this.message = 'no elements in sequence';
1565             this.name = 'EmptyError';
1566             return this;
1567         }
1568         EmptyErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
1569         return EmptyErrorImpl;
1570     })();
1571     var EmptyError = EmptyErrorImpl;
1572
1573     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1574     var TimeoutErrorImpl = /*@__PURE__*/ (function () {
1575         function TimeoutErrorImpl() {
1576             Error.call(this);
1577             this.message = 'Timeout has occurred';
1578             this.name = 'TimeoutError';
1579             return this;
1580         }
1581         TimeoutErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
1582         return TimeoutErrorImpl;
1583     })();
1584     var TimeoutError = TimeoutErrorImpl;
1585
1586     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
1587     function map(project, thisArg) {
1588         return function mapOperation(source) {
1589             if (typeof project !== 'function') {
1590                 throw new TypeError('argument is not a function. Are you looking for `mapTo()`?');
1591             }
1592             return source.lift(new MapOperator(project, thisArg));
1593         };
1594     }
1595     var MapOperator = /*@__PURE__*/ (function () {
1596         function MapOperator(project, thisArg) {
1597             this.project = project;
1598             this.thisArg = thisArg;
1599         }
1600         MapOperator.prototype.call = function (subscriber, source) {
1601             return source.subscribe(new MapSubscriber(subscriber, this.project, this.thisArg));
1602         };
1603         return MapOperator;
1604     }());
1605     var MapSubscriber = /*@__PURE__*/ (function (_super) {
1606         __extends(MapSubscriber, _super);
1607         function MapSubscriber(destination, project, thisArg) {
1608             var _this = _super.call(this, destination) || this;
1609             _this.project = project;
1610             _this.count = 0;
1611             _this.thisArg = thisArg || _this;
1612             return _this;
1613         }
1614         MapSubscriber.prototype._next = function (value) {
1615             var result;
1616             try {
1617                 result = this.project.call(this.thisArg, value, this.count++);
1618             }
1619             catch (err) {
1620                 this.destination.error(err);
1621                 return;
1622             }
1623             this.destination.next(result);
1624         };
1625         return MapSubscriber;
1626     }(Subscriber));
1627
1628     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
1629     var OuterSubscriber = /*@__PURE__*/ (function (_super) {
1630         __extends(OuterSubscriber, _super);
1631         function OuterSubscriber() {
1632             return _super !== null && _super.apply(this, arguments) || this;
1633         }
1634         OuterSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
1635             this.destination.next(innerValue);
1636         };
1637         OuterSubscriber.prototype.notifyError = function (error, innerSub) {
1638             this.destination.error(error);
1639         };
1640         OuterSubscriber.prototype.notifyComplete = function (innerSub) {
1641             this.destination.complete();
1642         };
1643         return OuterSubscriber;
1644     }(Subscriber));
1645
1646     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
1647     var InnerSubscriber = /*@__PURE__*/ (function (_super) {
1648         __extends(InnerSubscriber, _super);
1649         function InnerSubscriber(parent, outerValue, outerIndex) {
1650             var _this = _super.call(this) || this;
1651             _this.parent = parent;
1652             _this.outerValue = outerValue;
1653             _this.outerIndex = outerIndex;
1654             _this.index = 0;
1655             return _this;
1656         }
1657         InnerSubscriber.prototype._next = function (value) {
1658             this.parent.notifyNext(this.outerValue, value, this.outerIndex, this.index++, this);
1659         };
1660         InnerSubscriber.prototype._error = function (error) {
1661             this.parent.notifyError(error, this);
1662             this.unsubscribe();
1663         };
1664         InnerSubscriber.prototype._complete = function () {
1665             this.parent.notifyComplete(this);
1666             this.unsubscribe();
1667         };
1668         return InnerSubscriber;
1669     }(Subscriber));
1670
1671     /** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */
1672     var subscribeToPromise = function (promise) {
1673         return function (subscriber) {
1674             promise.then(function (value) {
1675                 if (!subscriber.closed) {
1676                     subscriber.next(value);
1677                     subscriber.complete();
1678                 }
1679             }, function (err) { return subscriber.error(err); })
1680                 .then(null, hostReportError);
1681             return subscriber;
1682         };
1683     };
1684
1685     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1686     function getSymbolIterator() {
1687         if (typeof Symbol !== 'function' || !Symbol.iterator) {
1688             return '@@iterator';
1689         }
1690         return Symbol.iterator;
1691     }
1692     var iterator = /*@__PURE__*/ getSymbolIterator();
1693
1694     /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
1695     var subscribeToIterable = function (iterable) {
1696         return function (subscriber) {
1697             var iterator$1 = iterable[iterator]();
1698             do {
1699                 var item = void 0;
1700                 try {
1701                     item = iterator$1.next();
1702                 }
1703                 catch (err) {
1704                     subscriber.error(err);
1705                     return subscriber;
1706                 }
1707                 if (item.done) {
1708                     subscriber.complete();
1709                     break;
1710                 }
1711                 subscriber.next(item.value);
1712                 if (subscriber.closed) {
1713                     break;
1714                 }
1715             } while (true);
1716             if (typeof iterator$1.return === 'function') {
1717                 subscriber.add(function () {
1718                     if (iterator$1.return) {
1719                         iterator$1.return();
1720                     }
1721                 });
1722             }
1723             return subscriber;
1724         };
1725     };
1726
1727     /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
1728     var subscribeToObservable = function (obj) {
1729         return function (subscriber) {
1730             var obs = obj[observable]();
1731             if (typeof obs.subscribe !== 'function') {
1732                 throw new TypeError('Provided object does not correctly implement Symbol.observable');
1733             }
1734             else {
1735                 return obs.subscribe(subscriber);
1736             }
1737         };
1738     };
1739
1740     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1741     var isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });
1742
1743     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
1744     function isPromise(value) {
1745         return !!value && typeof value.subscribe !== 'function' && typeof value.then === 'function';
1746     }
1747
1748     /** PURE_IMPORTS_START _subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */
1749     var subscribeTo = function (result) {
1750         if (!!result && typeof result[observable] === 'function') {
1751             return subscribeToObservable(result);
1752         }
1753         else if (isArrayLike(result)) {
1754             return subscribeToArray(result);
1755         }
1756         else if (isPromise(result)) {
1757             return subscribeToPromise(result);
1758         }
1759         else if (!!result && typeof result[iterator] === 'function') {
1760             return subscribeToIterable(result);
1761         }
1762         else {
1763             var value = isObject$1(result) ? 'an invalid object' : "'" + result + "'";
1764             var msg = "You provided " + value + " where a stream was expected."
1765                 + ' You can provide an Observable, Promise, Array, or Iterable.';
1766             throw new TypeError(msg);
1767         }
1768     };
1769
1770     /** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo,_Observable PURE_IMPORTS_END */
1771     function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, innerSubscriber) {
1772         if (innerSubscriber === void 0) {
1773             innerSubscriber = new InnerSubscriber(outerSubscriber, outerValue, outerIndex);
1774         }
1775         if (innerSubscriber.closed) {
1776             return undefined;
1777         }
1778         if (result instanceof Observable) {
1779             return result.subscribe(innerSubscriber);
1780         }
1781         return subscribeTo(result)(innerSubscriber);
1782     }
1783
1784     /** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */
1785     var NONE = {};
1786     function combineLatest() {
1787         var observables = [];
1788         for (var _i = 0; _i < arguments.length; _i++) {
1789             observables[_i] = arguments[_i];
1790         }
1791         var resultSelector = undefined;
1792         var scheduler = undefined;
1793         if (isScheduler(observables[observables.length - 1])) {
1794             scheduler = observables.pop();
1795         }
1796         if (typeof observables[observables.length - 1] === 'function') {
1797             resultSelector = observables.pop();
1798         }
1799         if (observables.length === 1 && isArray$1(observables[0])) {
1800             observables = observables[0];
1801         }
1802         return fromArray(observables, scheduler).lift(new CombineLatestOperator(resultSelector));
1803     }
1804     var CombineLatestOperator = /*@__PURE__*/ (function () {
1805         function CombineLatestOperator(resultSelector) {
1806             this.resultSelector = resultSelector;
1807         }
1808         CombineLatestOperator.prototype.call = function (subscriber, source) {
1809             return source.subscribe(new CombineLatestSubscriber(subscriber, this.resultSelector));
1810         };
1811         return CombineLatestOperator;
1812     }());
1813     var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) {
1814         __extends(CombineLatestSubscriber, _super);
1815         function CombineLatestSubscriber(destination, resultSelector) {
1816             var _this = _super.call(this, destination) || this;
1817             _this.resultSelector = resultSelector;
1818             _this.active = 0;
1819             _this.values = [];
1820             _this.observables = [];
1821             return _this;
1822         }
1823         CombineLatestSubscriber.prototype._next = function (observable) {
1824             this.values.push(NONE);
1825             this.observables.push(observable);
1826         };
1827         CombineLatestSubscriber.prototype._complete = function () {
1828             var observables = this.observables;
1829             var len = observables.length;
1830             if (len === 0) {
1831                 this.destination.complete();
1832             }
1833             else {
1834                 this.active = len;
1835                 this.toRespond = len;
1836                 for (var i = 0; i < len; i++) {
1837                     var observable = observables[i];
1838                     this.add(subscribeToResult(this, observable, undefined, i));
1839                 }
1840             }
1841         };
1842         CombineLatestSubscriber.prototype.notifyComplete = function (unused) {
1843             if ((this.active -= 1) === 0) {
1844                 this.destination.complete();
1845             }
1846         };
1847         CombineLatestSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) {
1848             var values = this.values;
1849             var oldVal = values[outerIndex];
1850             var toRespond = !this.toRespond
1851                 ? 0
1852                 : oldVal === NONE ? --this.toRespond : this.toRespond;
1853             values[outerIndex] = innerValue;
1854             if (toRespond === 0) {
1855                 if (this.resultSelector) {
1856                     this._tryResultSelector(values);
1857                 }
1858                 else {
1859                     this.destination.next(values.slice());
1860                 }
1861             }
1862         };
1863         CombineLatestSubscriber.prototype._tryResultSelector = function (values) {
1864             var result;
1865             try {
1866                 result = this.resultSelector.apply(this, values);
1867             }
1868             catch (err) {
1869                 this.destination.error(err);
1870                 return;
1871             }
1872             this.destination.next(result);
1873         };
1874         return CombineLatestSubscriber;
1875     }(OuterSubscriber));
1876
1877     /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable PURE_IMPORTS_END */
1878     function scheduleObservable(input, scheduler) {
1879         return new Observable(function (subscriber) {
1880             var sub = new Subscription();
1881             sub.add(scheduler.schedule(function () {
1882                 var observable$1 = input[observable]();
1883                 sub.add(observable$1.subscribe({
1884                     next: function (value) { sub.add(scheduler.schedule(function () { return subscriber.next(value); })); },
1885                     error: function (err) { sub.add(scheduler.schedule(function () { return subscriber.error(err); })); },
1886                     complete: function () { sub.add(scheduler.schedule(function () { return subscriber.complete(); })); },
1887                 }));
1888             }));
1889             return sub;
1890         });
1891     }
1892
1893     /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
1894     function schedulePromise(input, scheduler) {
1895         return new Observable(function (subscriber) {
1896             var sub = new Subscription();
1897             sub.add(scheduler.schedule(function () {
1898                 return input.then(function (value) {
1899                     sub.add(scheduler.schedule(function () {
1900                         subscriber.next(value);
1901                         sub.add(scheduler.schedule(function () { return subscriber.complete(); }));
1902                     }));
1903                 }, function (err) {
1904                     sub.add(scheduler.schedule(function () { return subscriber.error(err); }));
1905                 });
1906             }));
1907             return sub;
1908         });
1909     }
1910
1911     /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator PURE_IMPORTS_END */
1912     function scheduleIterable(input, scheduler) {
1913         if (!input) {
1914             throw new Error('Iterable cannot be null');
1915         }
1916         return new Observable(function (subscriber) {
1917             var sub = new Subscription();
1918             var iterator$1;
1919             sub.add(function () {
1920                 if (iterator$1 && typeof iterator$1.return === 'function') {
1921                     iterator$1.return();
1922                 }
1923             });
1924             sub.add(scheduler.schedule(function () {
1925                 iterator$1 = input[iterator]();
1926                 sub.add(scheduler.schedule(function () {
1927                     if (subscriber.closed) {
1928                         return;
1929                     }
1930                     var value;
1931                     var done;
1932                     try {
1933                         var result = iterator$1.next();
1934                         value = result.value;
1935                         done = result.done;
1936                     }
1937                     catch (err) {
1938                         subscriber.error(err);
1939                         return;
1940                     }
1941                     if (done) {
1942                         subscriber.complete();
1943                     }
1944                     else {
1945                         subscriber.next(value);
1946                         this.schedule();
1947                     }
1948                 }));
1949             }));
1950             return sub;
1951         });
1952     }
1953
1954     /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
1955     function isInteropObservable(input) {
1956         return input && typeof input[observable] === 'function';
1957     }
1958
1959     /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
1960     function isIterable(input) {
1961         return input && typeof input[iterator] === 'function';
1962     }
1963
1964     /** PURE_IMPORTS_START _scheduleObservable,_schedulePromise,_scheduleArray,_scheduleIterable,_util_isInteropObservable,_util_isPromise,_util_isArrayLike,_util_isIterable PURE_IMPORTS_END */
1965     function scheduled(input, scheduler) {
1966         if (input != null) {
1967             if (isInteropObservable(input)) {
1968                 return scheduleObservable(input, scheduler);
1969             }
1970             else if (isPromise(input)) {
1971                 return schedulePromise(input, scheduler);
1972             }
1973             else if (isArrayLike(input)) {
1974                 return scheduleArray(input, scheduler);
1975             }
1976             else if (isIterable(input) || typeof input === 'string') {
1977                 return scheduleIterable(input, scheduler);
1978             }
1979         }
1980         throw new TypeError((input !== null && typeof input || input) + ' is not observable');
1981     }
1982
1983     /** PURE_IMPORTS_START _Observable,_util_subscribeTo,_scheduled_scheduled PURE_IMPORTS_END */
1984     function from(input, scheduler) {
1985         if (!scheduler) {
1986             if (input instanceof Observable) {
1987                 return input;
1988             }
1989             return new Observable(subscribeTo(input));
1990         }
1991         else {
1992             return scheduled(input, scheduler);
1993         }
1994     }
1995
1996     /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_util_subscribeTo PURE_IMPORTS_END */
1997     var SimpleInnerSubscriber = /*@__PURE__*/ (function (_super) {
1998         __extends(SimpleInnerSubscriber, _super);
1999         function SimpleInnerSubscriber(parent) {
2000             var _this = _super.call(this) || this;
2001             _this.parent = parent;
2002             return _this;
2003         }
2004         SimpleInnerSubscriber.prototype._next = function (value) {
2005             this.parent.notifyNext(value);
2006         };
2007         SimpleInnerSubscriber.prototype._error = function (error) {
2008             this.parent.notifyError(error);
2009             this.unsubscribe();
2010         };
2011         SimpleInnerSubscriber.prototype._complete = function () {
2012             this.parent.notifyComplete();
2013             this.unsubscribe();
2014         };
2015         return SimpleInnerSubscriber;
2016     }(Subscriber));
2017     var SimpleOuterSubscriber = /*@__PURE__*/ (function (_super) {
2018         __extends(SimpleOuterSubscriber, _super);
2019         function SimpleOuterSubscriber() {
2020             return _super !== null && _super.apply(this, arguments) || this;
2021         }
2022         SimpleOuterSubscriber.prototype.notifyNext = function (innerValue) {
2023             this.destination.next(innerValue);
2024         };
2025         SimpleOuterSubscriber.prototype.notifyError = function (err) {
2026             this.destination.error(err);
2027         };
2028         SimpleOuterSubscriber.prototype.notifyComplete = function () {
2029             this.destination.complete();
2030         };
2031         return SimpleOuterSubscriber;
2032     }(Subscriber));
2033     function innerSubscribe(result, innerSubscriber) {
2034         if (innerSubscriber.closed) {
2035             return undefined;
2036         }
2037         if (result instanceof Observable) {
2038             return result.subscribe(innerSubscriber);
2039         }
2040         return subscribeTo(result)(innerSubscriber);
2041     }
2042
2043     /** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */
2044     function mergeMap(project, resultSelector, concurrent) {
2045         if (concurrent === void 0) {
2046             concurrent = Number.POSITIVE_INFINITY;
2047         }
2048         if (typeof resultSelector === 'function') {
2049             return function (source) { return source.pipe(mergeMap(function (a, i) { return from(project(a, i)).pipe(map(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); };
2050         }
2051         else if (typeof resultSelector === 'number') {
2052             concurrent = resultSelector;
2053         }
2054         return function (source) { return source.lift(new MergeMapOperator(project, concurrent)); };
2055     }
2056     var MergeMapOperator = /*@__PURE__*/ (function () {
2057         function MergeMapOperator(project, concurrent) {
2058             if (concurrent === void 0) {
2059                 concurrent = Number.POSITIVE_INFINITY;
2060             }
2061             this.project = project;
2062             this.concurrent = concurrent;
2063         }
2064         MergeMapOperator.prototype.call = function (observer, source) {
2065             return source.subscribe(new MergeMapSubscriber(observer, this.project, this.concurrent));
2066         };
2067         return MergeMapOperator;
2068     }());
2069     var MergeMapSubscriber = /*@__PURE__*/ (function (_super) {
2070         __extends(MergeMapSubscriber, _super);
2071         function MergeMapSubscriber(destination, project, concurrent) {
2072             if (concurrent === void 0) {
2073                 concurrent = Number.POSITIVE_INFINITY;
2074             }
2075             var _this = _super.call(this, destination) || this;
2076             _this.project = project;
2077             _this.concurrent = concurrent;
2078             _this.hasCompleted = false;
2079             _this.buffer = [];
2080             _this.active = 0;
2081             _this.index = 0;
2082             return _this;
2083         }
2084         MergeMapSubscriber.prototype._next = function (value) {
2085             if (this.active < this.concurrent) {
2086                 this._tryNext(value);
2087             }
2088             else {
2089                 this.buffer.push(value);
2090             }
2091         };
2092         MergeMapSubscriber.prototype._tryNext = function (value) {
2093             var result;
2094             var index = this.index++;
2095             try {
2096                 result = this.project(value, index);
2097             }
2098             catch (err) {
2099                 this.destination.error(err);
2100                 return;
2101             }
2102             this.active++;
2103             this._innerSub(result);
2104         };
2105         MergeMapSubscriber.prototype._innerSub = function (ish) {
2106             var innerSubscriber = new SimpleInnerSubscriber(this);
2107             var destination = this.destination;
2108             destination.add(innerSubscriber);
2109             var innerSubscription = innerSubscribe(ish, innerSubscriber);
2110             if (innerSubscription !== innerSubscriber) {
2111                 destination.add(innerSubscription);
2112             }
2113         };
2114         MergeMapSubscriber.prototype._complete = function () {
2115             this.hasCompleted = true;
2116             if (this.active === 0 && this.buffer.length === 0) {
2117                 this.destination.complete();
2118             }
2119             this.unsubscribe();
2120         };
2121         MergeMapSubscriber.prototype.notifyNext = function (innerValue) {
2122             this.destination.next(innerValue);
2123         };
2124         MergeMapSubscriber.prototype.notifyComplete = function () {
2125             var buffer = this.buffer;
2126             this.active--;
2127             if (buffer.length > 0) {
2128                 this._next(buffer.shift());
2129             }
2130             else if (this.active === 0 && this.hasCompleted) {
2131                 this.destination.complete();
2132             }
2133         };
2134         return MergeMapSubscriber;
2135     }(SimpleOuterSubscriber));
2136
2137     /** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */
2138     function mergeAll(concurrent) {
2139         if (concurrent === void 0) {
2140             concurrent = Number.POSITIVE_INFINITY;
2141         }
2142         return mergeMap(identity, concurrent);
2143     }
2144
2145     /** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */
2146     function concatAll() {
2147         return mergeAll(1);
2148     }
2149
2150     /** PURE_IMPORTS_START _of,_operators_concatAll PURE_IMPORTS_END */
2151     function concat() {
2152         var observables = [];
2153         for (var _i = 0; _i < arguments.length; _i++) {
2154             observables[_i] = arguments[_i];
2155         }
2156         return concatAll()(of.apply(void 0, observables));
2157     }
2158
2159     /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */
2160     function fromEvent(target, eventName, options, resultSelector) {
2161         if (isFunction(options)) {
2162             resultSelector = options;
2163             options = undefined;
2164         }
2165         if (resultSelector) {
2166             return fromEvent(target, eventName, options).pipe(map(function (args) { return isArray$1(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
2167         }
2168         return new Observable(function (subscriber) {
2169             function handler(e) {
2170                 if (arguments.length > 1) {
2171                     subscriber.next(Array.prototype.slice.call(arguments));
2172                 }
2173                 else {
2174                     subscriber.next(e);
2175                 }
2176             }
2177             setupSubscription(target, eventName, handler, subscriber, options);
2178         });
2179     }
2180     function setupSubscription(sourceObj, eventName, handler, subscriber, options) {
2181         var unsubscribe;
2182         if (isEventTarget(sourceObj)) {
2183             var source_1 = sourceObj;
2184             sourceObj.addEventListener(eventName, handler, options);
2185             unsubscribe = function () { return source_1.removeEventListener(eventName, handler, options); };
2186         }
2187         else if (isJQueryStyleEventEmitter(sourceObj)) {
2188             var source_2 = sourceObj;
2189             sourceObj.on(eventName, handler);
2190             unsubscribe = function () { return source_2.off(eventName, handler); };
2191         }
2192         else if (isNodeStyleEventEmitter(sourceObj)) {
2193             var source_3 = sourceObj;
2194             sourceObj.addListener(eventName, handler);
2195             unsubscribe = function () { return source_3.removeListener(eventName, handler); };
2196         }
2197         else if (sourceObj && sourceObj.length) {
2198             for (var i = 0, len = sourceObj.length; i < len; i++) {
2199                 setupSubscription(sourceObj[i], eventName, handler, subscriber, options);
2200             }
2201         }
2202         else {
2203             throw new TypeError('Invalid event target');
2204         }
2205         subscriber.add(unsubscribe);
2206     }
2207     function isNodeStyleEventEmitter(sourceObj) {
2208         return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
2209     }
2210     function isJQueryStyleEventEmitter(sourceObj) {
2211         return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
2212     }
2213     function isEventTarget(sourceObj) {
2214         return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
2215     }
2216
2217     /** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */
2218     function isNumeric(val) {
2219         return !isArray$1(val) && (val - parseFloat(val) + 1) >= 0;
2220     }
2221
2222     /** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */
2223     function merge() {
2224         var observables = [];
2225         for (var _i = 0; _i < arguments.length; _i++) {
2226             observables[_i] = arguments[_i];
2227         }
2228         var concurrent = Number.POSITIVE_INFINITY;
2229         var scheduler = null;
2230         var last = observables[observables.length - 1];
2231         if (isScheduler(last)) {
2232             scheduler = observables.pop();
2233             if (observables.length > 1 && typeof observables[observables.length - 1] === 'number') {
2234                 concurrent = observables.pop();
2235             }
2236         }
2237         else if (typeof last === 'number') {
2238             concurrent = observables.pop();
2239         }
2240         if (scheduler === null && observables.length === 1 && observables[0] instanceof Observable) {
2241             return observables[0];
2242         }
2243         return mergeAll(concurrent)(fromArray(observables, scheduler));
2244     }
2245
2246     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
2247     function filter(predicate, thisArg) {
2248         return function filterOperatorFunction(source) {
2249             return source.lift(new FilterOperator(predicate, thisArg));
2250         };
2251     }
2252     var FilterOperator = /*@__PURE__*/ (function () {
2253         function FilterOperator(predicate, thisArg) {
2254             this.predicate = predicate;
2255             this.thisArg = thisArg;
2256         }
2257         FilterOperator.prototype.call = function (subscriber, source) {
2258             return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg));
2259         };
2260         return FilterOperator;
2261     }());
2262     var FilterSubscriber = /*@__PURE__*/ (function (_super) {
2263         __extends(FilterSubscriber, _super);
2264         function FilterSubscriber(destination, predicate, thisArg) {
2265             var _this = _super.call(this, destination) || this;
2266             _this.predicate = predicate;
2267             _this.thisArg = thisArg;
2268             _this.count = 0;
2269             return _this;
2270         }
2271         FilterSubscriber.prototype._next = function (value) {
2272             var result;
2273             try {
2274                 result = this.predicate.call(this.thisArg, value, this.count++);
2275             }
2276             catch (err) {
2277                 this.destination.error(err);
2278                 return;
2279             }
2280             if (result) {
2281                 this.destination.next(value);
2282             }
2283         };
2284         return FilterSubscriber;
2285     }(Subscriber));
2286
2287     /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */
2288     function timer(dueTime, periodOrScheduler, scheduler) {
2289         if (dueTime === void 0) {
2290             dueTime = 0;
2291         }
2292         var period = -1;
2293         if (isNumeric(periodOrScheduler)) {
2294             period = Number(periodOrScheduler) < 1 && 1 || Number(periodOrScheduler);
2295         }
2296         else if (isScheduler(periodOrScheduler)) {
2297             scheduler = periodOrScheduler;
2298         }
2299         if (!isScheduler(scheduler)) {
2300             scheduler = async;
2301         }
2302         return new Observable(function (subscriber) {
2303             var due = isNumeric(dueTime)
2304                 ? dueTime
2305                 : (+dueTime - scheduler.now());
2306             return scheduler.schedule(dispatch, due, {
2307                 index: 0, period: period, subscriber: subscriber
2308             });
2309         });
2310     }
2311     function dispatch(state) {
2312         var index = state.index, period = state.period, subscriber = state.subscriber;
2313         subscriber.next(index);
2314         if (subscriber.closed) {
2315             return;
2316         }
2317         else if (period === -1) {
2318             return subscriber.complete();
2319         }
2320         state.index = index + 1;
2321         this.schedule(state, period);
2322     }
2323
2324     /** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_.._internal_symbol_iterator,_innerSubscribe PURE_IMPORTS_END */
2325     function zip() {
2326         var observables = [];
2327         for (var _i = 0; _i < arguments.length; _i++) {
2328             observables[_i] = arguments[_i];
2329         }
2330         var resultSelector = observables[observables.length - 1];
2331         if (typeof resultSelector === 'function') {
2332             observables.pop();
2333         }
2334         return fromArray(observables, undefined).lift(new ZipOperator(resultSelector));
2335     }
2336     var ZipOperator = /*@__PURE__*/ (function () {
2337         function ZipOperator(resultSelector) {
2338             this.resultSelector = resultSelector;
2339         }
2340         ZipOperator.prototype.call = function (subscriber, source) {
2341             return source.subscribe(new ZipSubscriber(subscriber, this.resultSelector));
2342         };
2343         return ZipOperator;
2344     }());
2345     var ZipSubscriber = /*@__PURE__*/ (function (_super) {
2346         __extends(ZipSubscriber, _super);
2347         function ZipSubscriber(destination, resultSelector, values) {
2348             var _this = _super.call(this, destination) || this;
2349             _this.resultSelector = resultSelector;
2350             _this.iterators = [];
2351             _this.active = 0;
2352             _this.resultSelector = (typeof resultSelector === 'function') ? resultSelector : undefined;
2353             return _this;
2354         }
2355         ZipSubscriber.prototype._next = function (value) {
2356             var iterators = this.iterators;
2357             if (isArray$1(value)) {
2358                 iterators.push(new StaticArrayIterator(value));
2359             }
2360             else if (typeof value[iterator] === 'function') {
2361                 iterators.push(new StaticIterator(value[iterator]()));
2362             }
2363             else {
2364                 iterators.push(new ZipBufferIterator(this.destination, this, value));
2365             }
2366         };
2367         ZipSubscriber.prototype._complete = function () {
2368             var iterators = this.iterators;
2369             var len = iterators.length;
2370             this.unsubscribe();
2371             if (len === 0) {
2372                 this.destination.complete();
2373                 return;
2374             }
2375             this.active = len;
2376             for (var i = 0; i < len; i++) {
2377                 var iterator = iterators[i];
2378                 if (iterator.stillUnsubscribed) {
2379                     var destination = this.destination;
2380                     destination.add(iterator.subscribe());
2381                 }
2382                 else {
2383                     this.active--;
2384                 }
2385             }
2386         };
2387         ZipSubscriber.prototype.notifyInactive = function () {
2388             this.active--;
2389             if (this.active === 0) {
2390                 this.destination.complete();
2391             }
2392         };
2393         ZipSubscriber.prototype.checkIterators = function () {
2394             var iterators = this.iterators;
2395             var len = iterators.length;
2396             var destination = this.destination;
2397             for (var i = 0; i < len; i++) {
2398                 var iterator = iterators[i];
2399                 if (typeof iterator.hasValue === 'function' && !iterator.hasValue()) {
2400                     return;
2401                 }
2402             }
2403             var shouldComplete = false;
2404             var args = [];
2405             for (var i = 0; i < len; i++) {
2406                 var iterator = iterators[i];
2407                 var result = iterator.next();
2408                 if (iterator.hasCompleted()) {
2409                     shouldComplete = true;
2410                 }
2411                 if (result.done) {
2412                     destination.complete();
2413                     return;
2414                 }
2415                 args.push(result.value);
2416             }
2417             if (this.resultSelector) {
2418                 this._tryresultSelector(args);
2419             }
2420             else {
2421                 destination.next(args);
2422             }
2423             if (shouldComplete) {
2424                 destination.complete();
2425             }
2426         };
2427         ZipSubscriber.prototype._tryresultSelector = function (args) {
2428             var result;
2429             try {
2430                 result = this.resultSelector.apply(this, args);
2431             }
2432             catch (err) {
2433                 this.destination.error(err);
2434                 return;
2435             }
2436             this.destination.next(result);
2437         };
2438         return ZipSubscriber;
2439     }(Subscriber));
2440     var StaticIterator = /*@__PURE__*/ (function () {
2441         function StaticIterator(iterator) {
2442             this.iterator = iterator;
2443             this.nextResult = iterator.next();
2444         }
2445         StaticIterator.prototype.hasValue = function () {
2446             return true;
2447         };
2448         StaticIterator.prototype.next = function () {
2449             var result = this.nextResult;
2450             this.nextResult = this.iterator.next();
2451             return result;
2452         };
2453         StaticIterator.prototype.hasCompleted = function () {
2454             var nextResult = this.nextResult;
2455             return Boolean(nextResult && nextResult.done);
2456         };
2457         return StaticIterator;
2458     }());
2459     var StaticArrayIterator = /*@__PURE__*/ (function () {
2460         function StaticArrayIterator(array) {
2461             this.array = array;
2462             this.index = 0;
2463             this.length = 0;
2464             this.length = array.length;
2465         }
2466         StaticArrayIterator.prototype[iterator] = function () {
2467             return this;
2468         };
2469         StaticArrayIterator.prototype.next = function (value) {
2470             var i = this.index++;
2471             var array = this.array;
2472             return i < this.length ? { value: array[i], done: false } : { value: null, done: true };
2473         };
2474         StaticArrayIterator.prototype.hasValue = function () {
2475             return this.array.length > this.index;
2476         };
2477         StaticArrayIterator.prototype.hasCompleted = function () {
2478             return this.array.length === this.index;
2479         };
2480         return StaticArrayIterator;
2481     }());
2482     var ZipBufferIterator = /*@__PURE__*/ (function (_super) {
2483         __extends(ZipBufferIterator, _super);
2484         function ZipBufferIterator(destination, parent, observable) {
2485             var _this = _super.call(this, destination) || this;
2486             _this.parent = parent;
2487             _this.observable = observable;
2488             _this.stillUnsubscribed = true;
2489             _this.buffer = [];
2490             _this.isComplete = false;
2491             return _this;
2492         }
2493         ZipBufferIterator.prototype[iterator] = function () {
2494             return this;
2495         };
2496         ZipBufferIterator.prototype.next = function () {
2497             var buffer = this.buffer;
2498             if (buffer.length === 0 && this.isComplete) {
2499                 return { value: null, done: true };
2500             }
2501             else {
2502                 return { value: buffer.shift(), done: false };
2503             }
2504         };
2505         ZipBufferIterator.prototype.hasValue = function () {
2506             return this.buffer.length > 0;
2507         };
2508         ZipBufferIterator.prototype.hasCompleted = function () {
2509             return this.buffer.length === 0 && this.isComplete;
2510         };
2511         ZipBufferIterator.prototype.notifyComplete = function () {
2512             if (this.buffer.length > 0) {
2513                 this.isComplete = true;
2514                 this.parent.notifyInactive();
2515             }
2516             else {
2517                 this.destination.complete();
2518             }
2519         };
2520         ZipBufferIterator.prototype.notifyNext = function (innerValue) {
2521             this.buffer.push(innerValue);
2522             this.parent.checkIterators();
2523         };
2524         ZipBufferIterator.prototype.subscribe = function () {
2525             return innerSubscribe(this.observable, new SimpleInnerSubscriber(this));
2526         };
2527         return ZipBufferIterator;
2528     }(SimpleOuterSubscriber));
2529
2530     /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
2531     function audit(durationSelector) {
2532         return function auditOperatorFunction(source) {
2533             return source.lift(new AuditOperator(durationSelector));
2534         };
2535     }
2536     var AuditOperator = /*@__PURE__*/ (function () {
2537         function AuditOperator(durationSelector) {
2538             this.durationSelector = durationSelector;
2539         }
2540         AuditOperator.prototype.call = function (subscriber, source) {
2541             return source.subscribe(new AuditSubscriber(subscriber, this.durationSelector));
2542         };
2543         return AuditOperator;
2544     }());
2545     var AuditSubscriber = /*@__PURE__*/ (function (_super) {
2546         __extends(AuditSubscriber, _super);
2547         function AuditSubscriber(destination, durationSelector) {
2548             var _this = _super.call(this, destination) || this;
2549             _this.durationSelector = durationSelector;
2550             _this.hasValue = false;
2551             return _this;
2552         }
2553         AuditSubscriber.prototype._next = function (value) {
2554             this.value = value;
2555             this.hasValue = true;
2556             if (!this.throttled) {
2557                 var duration = void 0;
2558                 try {
2559                     var durationSelector = this.durationSelector;
2560                     duration = durationSelector(value);
2561                 }
2562                 catch (err) {
2563                     return this.destination.error(err);
2564                 }
2565                 var innerSubscription = innerSubscribe(duration, new SimpleInnerSubscriber(this));
2566                 if (!innerSubscription || innerSubscription.closed) {
2567                     this.clearThrottle();
2568                 }
2569                 else {
2570                     this.add(this.throttled = innerSubscription);
2571                 }
2572             }
2573         };
2574         AuditSubscriber.prototype.clearThrottle = function () {
2575             var _a = this, value = _a.value, hasValue = _a.hasValue, throttled = _a.throttled;
2576             if (throttled) {
2577                 this.remove(throttled);
2578                 this.throttled = undefined;
2579                 throttled.unsubscribe();
2580             }
2581             if (hasValue) {
2582                 this.value = undefined;
2583                 this.hasValue = false;
2584                 this.destination.next(value);
2585             }
2586         };
2587         AuditSubscriber.prototype.notifyNext = function () {
2588             this.clearThrottle();
2589         };
2590         AuditSubscriber.prototype.notifyComplete = function () {
2591             this.clearThrottle();
2592         };
2593         return AuditSubscriber;
2594     }(SimpleOuterSubscriber));
2595
2596     /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */
2597     function auditTime(duration, scheduler) {
2598         if (scheduler === void 0) {
2599             scheduler = async;
2600         }
2601         return audit(function () { return timer(duration, scheduler); });
2602     }
2603
2604     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
2605     function bufferCount(bufferSize, startBufferEvery) {
2606         if (startBufferEvery === void 0) {
2607             startBufferEvery = null;
2608         }
2609         return function bufferCountOperatorFunction(source) {
2610             return source.lift(new BufferCountOperator(bufferSize, startBufferEvery));
2611         };
2612     }
2613     var BufferCountOperator = /*@__PURE__*/ (function () {
2614         function BufferCountOperator(bufferSize, startBufferEvery) {
2615             this.bufferSize = bufferSize;
2616             this.startBufferEvery = startBufferEvery;
2617             if (!startBufferEvery || bufferSize === startBufferEvery) {
2618                 this.subscriberClass = BufferCountSubscriber;
2619             }
2620             else {
2621                 this.subscriberClass = BufferSkipCountSubscriber;
2622             }
2623         }
2624         BufferCountOperator.prototype.call = function (subscriber, source) {
2625             return source.subscribe(new this.subscriberClass(subscriber, this.bufferSize, this.startBufferEvery));
2626         };
2627         return BufferCountOperator;
2628     }());
2629     var BufferCountSubscriber = /*@__PURE__*/ (function (_super) {
2630         __extends(BufferCountSubscriber, _super);
2631         function BufferCountSubscriber(destination, bufferSize) {
2632             var _this = _super.call(this, destination) || this;
2633             _this.bufferSize = bufferSize;
2634             _this.buffer = [];
2635             return _this;
2636         }
2637         BufferCountSubscriber.prototype._next = function (value) {
2638             var buffer = this.buffer;
2639             buffer.push(value);
2640             if (buffer.length == this.bufferSize) {
2641                 this.destination.next(buffer);
2642                 this.buffer = [];
2643             }
2644         };
2645         BufferCountSubscriber.prototype._complete = function () {
2646             var buffer = this.buffer;
2647             if (buffer.length > 0) {
2648                 this.destination.next(buffer);
2649             }
2650             _super.prototype._complete.call(this);
2651         };
2652         return BufferCountSubscriber;
2653     }(Subscriber));
2654     var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) {
2655         __extends(BufferSkipCountSubscriber, _super);
2656         function BufferSkipCountSubscriber(destination, bufferSize, startBufferEvery) {
2657             var _this = _super.call(this, destination) || this;
2658             _this.bufferSize = bufferSize;
2659             _this.startBufferEvery = startBufferEvery;
2660             _this.buffers = [];
2661             _this.count = 0;
2662             return _this;
2663         }
2664         BufferSkipCountSubscriber.prototype._next = function (value) {
2665             var _a = this, bufferSize = _a.bufferSize, startBufferEvery = _a.startBufferEvery, buffers = _a.buffers, count = _a.count;
2666             this.count++;
2667             if (count % startBufferEvery === 0) {
2668                 buffers.push([]);
2669             }
2670             for (var i = buffers.length; i--;) {
2671                 var buffer = buffers[i];
2672                 buffer.push(value);
2673                 if (buffer.length === bufferSize) {
2674                     buffers.splice(i, 1);
2675                     this.destination.next(buffer);
2676                 }
2677             }
2678         };
2679         BufferSkipCountSubscriber.prototype._complete = function () {
2680             var _a = this, buffers = _a.buffers, destination = _a.destination;
2681             while (buffers.length > 0) {
2682                 var buffer = buffers.shift();
2683                 if (buffer.length > 0) {
2684                     destination.next(buffer);
2685                 }
2686             }
2687             _super.prototype._complete.call(this);
2688         };
2689         return BufferSkipCountSubscriber;
2690     }(Subscriber));
2691
2692     /** PURE_IMPORTS_START tslib,_Subscription,_innerSubscribe PURE_IMPORTS_END */
2693     function bufferWhen(closingSelector) {
2694         return function (source) {
2695             return source.lift(new BufferWhenOperator(closingSelector));
2696         };
2697     }
2698     var BufferWhenOperator = /*@__PURE__*/ (function () {
2699         function BufferWhenOperator(closingSelector) {
2700             this.closingSelector = closingSelector;
2701         }
2702         BufferWhenOperator.prototype.call = function (subscriber, source) {
2703             return source.subscribe(new BufferWhenSubscriber(subscriber, this.closingSelector));
2704         };
2705         return BufferWhenOperator;
2706     }());
2707     var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) {
2708         __extends(BufferWhenSubscriber, _super);
2709         function BufferWhenSubscriber(destination, closingSelector) {
2710             var _this = _super.call(this, destination) || this;
2711             _this.closingSelector = closingSelector;
2712             _this.subscribing = false;
2713             _this.openBuffer();
2714             return _this;
2715         }
2716         BufferWhenSubscriber.prototype._next = function (value) {
2717             this.buffer.push(value);
2718         };
2719         BufferWhenSubscriber.prototype._complete = function () {
2720             var buffer = this.buffer;
2721             if (buffer) {
2722                 this.destination.next(buffer);
2723             }
2724             _super.prototype._complete.call(this);
2725         };
2726         BufferWhenSubscriber.prototype._unsubscribe = function () {
2727             this.buffer = undefined;
2728             this.subscribing = false;
2729         };
2730         BufferWhenSubscriber.prototype.notifyNext = function () {
2731             this.openBuffer();
2732         };
2733         BufferWhenSubscriber.prototype.notifyComplete = function () {
2734             if (this.subscribing) {
2735                 this.complete();
2736             }
2737             else {
2738                 this.openBuffer();
2739             }
2740         };
2741         BufferWhenSubscriber.prototype.openBuffer = function () {
2742             var closingSubscription = this.closingSubscription;
2743             if (closingSubscription) {
2744                 this.remove(closingSubscription);
2745                 closingSubscription.unsubscribe();
2746             }
2747             var buffer = this.buffer;
2748             if (this.buffer) {
2749                 this.destination.next(buffer);
2750             }
2751             this.buffer = [];
2752             var closingNotifier;
2753             try {
2754                 var closingSelector = this.closingSelector;
2755                 closingNotifier = closingSelector();
2756             }
2757             catch (err) {
2758                 return this.error(err);
2759             }
2760             closingSubscription = new Subscription();
2761             this.closingSubscription = closingSubscription;
2762             this.add(closingSubscription);
2763             this.subscribing = true;
2764             closingSubscription.add(innerSubscribe(closingNotifier, new SimpleInnerSubscriber(this)));
2765             this.subscribing = false;
2766         };
2767         return BufferWhenSubscriber;
2768     }(SimpleOuterSubscriber));
2769
2770     /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
2771     function catchError(selector) {
2772         return function catchErrorOperatorFunction(source) {
2773             var operator = new CatchOperator(selector);
2774             var caught = source.lift(operator);
2775             return (operator.caught = caught);
2776         };
2777     }
2778     var CatchOperator = /*@__PURE__*/ (function () {
2779         function CatchOperator(selector) {
2780             this.selector = selector;
2781         }
2782         CatchOperator.prototype.call = function (subscriber, source) {
2783             return source.subscribe(new CatchSubscriber(subscriber, this.selector, this.caught));
2784         };
2785         return CatchOperator;
2786     }());
2787     var CatchSubscriber = /*@__PURE__*/ (function (_super) {
2788         __extends(CatchSubscriber, _super);
2789         function CatchSubscriber(destination, selector, caught) {
2790             var _this = _super.call(this, destination) || this;
2791             _this.selector = selector;
2792             _this.caught = caught;
2793             return _this;
2794         }
2795         CatchSubscriber.prototype.error = function (err) {
2796             if (!this.isStopped) {
2797                 var result = void 0;
2798                 try {
2799                     result = this.selector(err, this.caught);
2800                 }
2801                 catch (err2) {
2802                     _super.prototype.error.call(this, err2);
2803                     return;
2804                 }
2805                 this._unsubscribeAndRecycle();
2806                 var innerSubscriber = new SimpleInnerSubscriber(this);
2807                 this.add(innerSubscriber);
2808                 var innerSubscription = innerSubscribe(result, innerSubscriber);
2809                 if (innerSubscription !== innerSubscriber) {
2810                     this.add(innerSubscription);
2811                 }
2812             }
2813         };
2814         return CatchSubscriber;
2815     }(SimpleOuterSubscriber));
2816
2817     /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */
2818     function concatMap(project, resultSelector) {
2819         return mergeMap(project, resultSelector, 1);
2820     }
2821
2822     /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */
2823     function debounceTime(dueTime, scheduler) {
2824         if (scheduler === void 0) {
2825             scheduler = async;
2826         }
2827         return function (source) { return source.lift(new DebounceTimeOperator(dueTime, scheduler)); };
2828     }
2829     var DebounceTimeOperator = /*@__PURE__*/ (function () {
2830         function DebounceTimeOperator(dueTime, scheduler) {
2831             this.dueTime = dueTime;
2832             this.scheduler = scheduler;
2833         }
2834         DebounceTimeOperator.prototype.call = function (subscriber, source) {
2835             return source.subscribe(new DebounceTimeSubscriber(subscriber, this.dueTime, this.scheduler));
2836         };
2837         return DebounceTimeOperator;
2838     }());
2839     var DebounceTimeSubscriber = /*@__PURE__*/ (function (_super) {
2840         __extends(DebounceTimeSubscriber, _super);
2841         function DebounceTimeSubscriber(destination, dueTime, scheduler) {
2842             var _this = _super.call(this, destination) || this;
2843             _this.dueTime = dueTime;
2844             _this.scheduler = scheduler;
2845             _this.debouncedSubscription = null;
2846             _this.lastValue = null;
2847             _this.hasValue = false;
2848             return _this;
2849         }
2850         DebounceTimeSubscriber.prototype._next = function (value) {
2851             this.clearDebounce();
2852             this.lastValue = value;
2853             this.hasValue = true;
2854             this.add(this.debouncedSubscription = this.scheduler.schedule(dispatchNext, this.dueTime, this));
2855         };
2856         DebounceTimeSubscriber.prototype._complete = function () {
2857             this.debouncedNext();
2858             this.destination.complete();
2859         };
2860         DebounceTimeSubscriber.prototype.debouncedNext = function () {
2861             this.clearDebounce();
2862             if (this.hasValue) {
2863                 var lastValue = this.lastValue;
2864                 this.lastValue = null;
2865                 this.hasValue = false;
2866                 this.destination.next(lastValue);
2867             }
2868         };
2869         DebounceTimeSubscriber.prototype.clearDebounce = function () {
2870             var debouncedSubscription = this.debouncedSubscription;
2871             if (debouncedSubscription !== null) {
2872                 this.remove(debouncedSubscription);
2873                 debouncedSubscription.unsubscribe();
2874                 this.debouncedSubscription = null;
2875             }
2876         };
2877         return DebounceTimeSubscriber;
2878     }(Subscriber));
2879     function dispatchNext(subscriber) {
2880         subscriber.debouncedNext();
2881     }
2882
2883     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
2884     function defaultIfEmpty(defaultValue) {
2885         if (defaultValue === void 0) {
2886             defaultValue = null;
2887         }
2888         return function (source) { return source.lift(new DefaultIfEmptyOperator(defaultValue)); };
2889     }
2890     var DefaultIfEmptyOperator = /*@__PURE__*/ (function () {
2891         function DefaultIfEmptyOperator(defaultValue) {
2892             this.defaultValue = defaultValue;
2893         }
2894         DefaultIfEmptyOperator.prototype.call = function (subscriber, source) {
2895             return source.subscribe(new DefaultIfEmptySubscriber(subscriber, this.defaultValue));
2896         };
2897         return DefaultIfEmptyOperator;
2898     }());
2899     var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) {
2900         __extends(DefaultIfEmptySubscriber, _super);
2901         function DefaultIfEmptySubscriber(destination, defaultValue) {
2902             var _this = _super.call(this, destination) || this;
2903             _this.defaultValue = defaultValue;
2904             _this.isEmpty = true;
2905             return _this;
2906         }
2907         DefaultIfEmptySubscriber.prototype._next = function (value) {
2908             this.isEmpty = false;
2909             this.destination.next(value);
2910         };
2911         DefaultIfEmptySubscriber.prototype._complete = function () {
2912             if (this.isEmpty) {
2913                 this.destination.next(this.defaultValue);
2914             }
2915             this.destination.complete();
2916         };
2917         return DefaultIfEmptySubscriber;
2918     }(Subscriber));
2919
2920     /** PURE_IMPORTS_START  PURE_IMPORTS_END */
2921     function isDate(value) {
2922         return value instanceof Date && !isNaN(+value);
2923     }
2924
2925     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
2926     function distinctUntilChanged(compare, keySelector) {
2927         return function (source) { return source.lift(new DistinctUntilChangedOperator(compare, keySelector)); };
2928     }
2929     var DistinctUntilChangedOperator = /*@__PURE__*/ (function () {
2930         function DistinctUntilChangedOperator(compare, keySelector) {
2931             this.compare = compare;
2932             this.keySelector = keySelector;
2933         }
2934         DistinctUntilChangedOperator.prototype.call = function (subscriber, source) {
2935             return source.subscribe(new DistinctUntilChangedSubscriber(subscriber, this.compare, this.keySelector));
2936         };
2937         return DistinctUntilChangedOperator;
2938     }());
2939     var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) {
2940         __extends(DistinctUntilChangedSubscriber, _super);
2941         function DistinctUntilChangedSubscriber(destination, compare, keySelector) {
2942             var _this = _super.call(this, destination) || this;
2943             _this.keySelector = keySelector;
2944             _this.hasKey = false;
2945             if (typeof compare === 'function') {
2946                 _this.compare = compare;
2947             }
2948             return _this;
2949         }
2950         DistinctUntilChangedSubscriber.prototype.compare = function (x, y) {
2951             return x === y;
2952         };
2953         DistinctUntilChangedSubscriber.prototype._next = function (value) {
2954             var key;
2955             try {
2956                 var keySelector = this.keySelector;
2957                 key = keySelector ? keySelector(value) : value;
2958             }
2959             catch (err) {
2960                 return this.destination.error(err);
2961             }
2962             var result = false;
2963             if (this.hasKey) {
2964                 try {
2965                     var compare = this.compare;
2966                     result = compare(this.key, key);
2967                 }
2968                 catch (err) {
2969                     return this.destination.error(err);
2970                 }
2971             }
2972             else {
2973                 this.hasKey = true;
2974             }
2975             if (!result) {
2976                 this.key = key;
2977                 this.destination.next(value);
2978             }
2979         };
2980         return DistinctUntilChangedSubscriber;
2981     }(Subscriber));
2982
2983     /** PURE_IMPORTS_START tslib,_util_EmptyError,_Subscriber PURE_IMPORTS_END */
2984     function throwIfEmpty(errorFactory) {
2985         if (errorFactory === void 0) {
2986             errorFactory = defaultErrorFactory;
2987         }
2988         return function (source) {
2989             return source.lift(new ThrowIfEmptyOperator(errorFactory));
2990         };
2991     }
2992     var ThrowIfEmptyOperator = /*@__PURE__*/ (function () {
2993         function ThrowIfEmptyOperator(errorFactory) {
2994             this.errorFactory = errorFactory;
2995         }
2996         ThrowIfEmptyOperator.prototype.call = function (subscriber, source) {
2997             return source.subscribe(new ThrowIfEmptySubscriber(subscriber, this.errorFactory));
2998         };
2999         return ThrowIfEmptyOperator;
3000     }());
3001     var ThrowIfEmptySubscriber = /*@__PURE__*/ (function (_super) {
3002         __extends(ThrowIfEmptySubscriber, _super);
3003         function ThrowIfEmptySubscriber(destination, errorFactory) {
3004             var _this = _super.call(this, destination) || this;
3005             _this.errorFactory = errorFactory;
3006             _this.hasValue = false;
3007             return _this;
3008         }
3009         ThrowIfEmptySubscriber.prototype._next = function (value) {
3010             this.hasValue = true;
3011             this.destination.next(value);
3012         };
3013         ThrowIfEmptySubscriber.prototype._complete = function () {
3014             if (!this.hasValue) {
3015                 var err = void 0;
3016                 try {
3017                     err = this.errorFactory();
3018                 }
3019                 catch (e) {
3020                     err = e;
3021                 }
3022                 this.destination.error(err);
3023             }
3024             else {
3025                 return this.destination.complete();
3026             }
3027         };
3028         return ThrowIfEmptySubscriber;
3029     }(Subscriber));
3030     function defaultErrorFactory() {
3031         return new EmptyError();
3032     }
3033
3034     /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
3035     function take(count) {
3036         return function (source) {
3037             if (count === 0) {
3038                 return empty();
3039             }
3040             else {
3041                 return source.lift(new TakeOperator(count));
3042             }
3043         };
3044     }
3045     var TakeOperator = /*@__PURE__*/ (function () {
3046         function TakeOperator(total) {
3047             this.total = total;
3048             if (this.total < 0) {
3049                 throw new ArgumentOutOfRangeError;
3050             }
3051         }
3052         TakeOperator.prototype.call = function (subscriber, source) {
3053             return source.subscribe(new TakeSubscriber(subscriber, this.total));
3054         };
3055         return TakeOperator;
3056     }());
3057     var TakeSubscriber = /*@__PURE__*/ (function (_super) {
3058         __extends(TakeSubscriber, _super);
3059         function TakeSubscriber(destination, total) {
3060             var _this = _super.call(this, destination) || this;
3061             _this.total = total;
3062             _this.count = 0;
3063             return _this;
3064         }
3065         TakeSubscriber.prototype._next = function (value) {
3066             var total = this.total;
3067             var count = ++this.count;
3068             if (count <= total) {
3069                 this.destination.next(value);
3070                 if (count === total) {
3071                     this.destination.complete();
3072                     this.unsubscribe();
3073                 }
3074             }
3075         };
3076         return TakeSubscriber;
3077     }(Subscriber));
3078
3079     /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
3080     function expand(project, concurrent, scheduler) {
3081         if (concurrent === void 0) {
3082             concurrent = Number.POSITIVE_INFINITY;
3083         }
3084         concurrent = (concurrent || 0) < 1 ? Number.POSITIVE_INFINITY : concurrent;
3085         return function (source) { return source.lift(new ExpandOperator(project, concurrent, scheduler)); };
3086     }
3087     var ExpandOperator = /*@__PURE__*/ (function () {
3088         function ExpandOperator(project, concurrent, scheduler) {
3089             this.project = project;
3090             this.concurrent = concurrent;
3091             this.scheduler = scheduler;
3092         }
3093         ExpandOperator.prototype.call = function (subscriber, source) {
3094             return source.subscribe(new ExpandSubscriber(subscriber, this.project, this.concurrent, this.scheduler));
3095         };
3096         return ExpandOperator;
3097     }());
3098     var ExpandSubscriber = /*@__PURE__*/ (function (_super) {
3099         __extends(ExpandSubscriber, _super);
3100         function ExpandSubscriber(destination, project, concurrent, scheduler) {
3101             var _this = _super.call(this, destination) || this;
3102             _this.project = project;
3103             _this.concurrent = concurrent;
3104             _this.scheduler = scheduler;
3105             _this.index = 0;
3106             _this.active = 0;
3107             _this.hasCompleted = false;
3108             if (concurrent < Number.POSITIVE_INFINITY) {
3109                 _this.buffer = [];
3110             }
3111             return _this;
3112         }
3113         ExpandSubscriber.dispatch = function (arg) {
3114             var subscriber = arg.subscriber, result = arg.result, value = arg.value, index = arg.index;
3115             subscriber.subscribeToProjection(result, value, index);
3116         };
3117         ExpandSubscriber.prototype._next = function (value) {
3118             var destination = this.destination;
3119             if (destination.closed) {
3120                 this._complete();
3121                 return;
3122             }
3123             var index = this.index++;
3124             if (this.active < this.concurrent) {
3125                 destination.next(value);
3126                 try {
3127                     var project = this.project;
3128                     var result = project(value, index);
3129                     if (!this.scheduler) {
3130                         this.subscribeToProjection(result, value, index);
3131                     }
3132                     else {
3133                         var state = { subscriber: this, result: result, value: value, index: index };
3134                         var destination_1 = this.destination;
3135                         destination_1.add(this.scheduler.schedule(ExpandSubscriber.dispatch, 0, state));
3136                     }
3137                 }
3138                 catch (e) {
3139                     destination.error(e);
3140                 }
3141             }
3142             else {
3143                 this.buffer.push(value);
3144             }
3145         };
3146         ExpandSubscriber.prototype.subscribeToProjection = function (result, value, index) {
3147             this.active++;
3148             var destination = this.destination;
3149             destination.add(innerSubscribe(result, new SimpleInnerSubscriber(this)));
3150         };
3151         ExpandSubscriber.prototype._complete = function () {
3152             this.hasCompleted = true;
3153             if (this.hasCompleted && this.active === 0) {
3154                 this.destination.complete();
3155             }
3156             this.unsubscribe();
3157         };
3158         ExpandSubscriber.prototype.notifyNext = function (innerValue) {
3159             this._next(innerValue);
3160         };
3161         ExpandSubscriber.prototype.notifyComplete = function () {
3162             var buffer = this.buffer;
3163             this.active--;
3164             if (buffer && buffer.length > 0) {
3165                 this._next(buffer.shift());
3166             }
3167             if (this.hasCompleted && this.active === 0) {
3168                 this.destination.complete();
3169             }
3170         };
3171         return ExpandSubscriber;
3172     }(SimpleOuterSubscriber));
3173
3174     /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */
3175     function finalize(callback) {
3176         return function (source) { return source.lift(new FinallyOperator(callback)); };
3177     }
3178     var FinallyOperator = /*@__PURE__*/ (function () {
3179         function FinallyOperator(callback) {
3180             this.callback = callback;
3181         }
3182         FinallyOperator.prototype.call = function (subscriber, source) {
3183             return source.subscribe(new FinallySubscriber(subscriber, this.callback));
3184         };
3185         return FinallyOperator;
3186     }());
3187     var FinallySubscriber = /*@__PURE__*/ (function (_super) {
3188         __extends(FinallySubscriber, _super);
3189         function FinallySubscriber(destination, callback) {
3190             var _this = _super.call(this, destination) || this;
3191             _this.add(new Subscription(callback));
3192             return _this;
3193         }
3194         return FinallySubscriber;
3195     }(Subscriber));
3196
3197     /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */
3198     function first(predicate, defaultValue) {
3199         var hasDefaultValue = arguments.length >= 2;
3200         return function (source) { return source.pipe(predicate ? filter(function (v, i) { return predicate(v, i, source); }) : identity, take(1), hasDefaultValue ? defaultIfEmpty(defaultValue) : throwIfEmpty(function () { return new EmptyError(); })); };
3201     }
3202
3203     /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
3204     function takeLast(count) {
3205         return function takeLastOperatorFunction(source) {
3206             if (count === 0) {
3207                 return empty();
3208             }
3209             else {
3210                 return source.lift(new TakeLastOperator(count));
3211             }
3212         };
3213     }
3214     var TakeLastOperator = /*@__PURE__*/ (function () {
3215         function TakeLastOperator(total) {
3216             this.total = total;
3217             if (this.total < 0) {
3218                 throw new ArgumentOutOfRangeError;
3219             }
3220         }
3221         TakeLastOperator.prototype.call = function (subscriber, source) {
3222             return source.subscribe(new TakeLastSubscriber(subscriber, this.total));
3223         };
3224         return TakeLastOperator;
3225     }());
3226     var TakeLastSubscriber = /*@__PURE__*/ (function (_super) {
3227         __extends(TakeLastSubscriber, _super);
3228         function TakeLastSubscriber(destination, total) {
3229             var _this = _super.call(this, destination) || this;
3230             _this.total = total;
3231             _this.ring = new Array();
3232             _this.count = 0;
3233             return _this;
3234         }
3235         TakeLastSubscriber.prototype._next = function (value) {
3236             var ring = this.ring;
3237             var total = this.total;
3238             var count = this.count++;
3239             if (ring.length < total) {
3240                 ring.push(value);
3241             }
3242             else {
3243                 var index = count % total;
3244                 ring[index] = value;
3245             }
3246         };
3247         TakeLastSubscriber.prototype._complete = function () {
3248             var destination = this.destination;
3249             var count = this.count;
3250             if (count > 0) {
3251                 var total = this.count >= this.total ? this.total : this.count;
3252                 var ring = this.ring;
3253                 for (var i = 0; i < total; i++) {
3254                     var idx = (count++) % total;
3255                     destination.next(ring[idx]);
3256                 }
3257             }
3258             destination.complete();
3259         };
3260         return TakeLastSubscriber;
3261     }(Subscriber));
3262
3263     /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */
3264     function last(predicate, defaultValue) {
3265         var hasDefaultValue = arguments.length >= 2;
3266         return function (source) { return source.pipe(predicate ? filter(function (v, i) { return predicate(v, i, source); }) : identity, takeLast(1), hasDefaultValue ? defaultIfEmpty(defaultValue) : throwIfEmpty(function () { return new EmptyError(); })); };
3267     }
3268
3269     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3270     function scan(accumulator, seed) {
3271         var hasSeed = false;
3272         if (arguments.length >= 2) {
3273             hasSeed = true;
3274         }
3275         return function scanOperatorFunction(source) {
3276             return source.lift(new ScanOperator(accumulator, seed, hasSeed));
3277         };
3278     }
3279     var ScanOperator = /*@__PURE__*/ (function () {
3280         function ScanOperator(accumulator, seed, hasSeed) {
3281             if (hasSeed === void 0) {
3282                 hasSeed = false;
3283             }
3284             this.accumulator = accumulator;
3285             this.seed = seed;
3286             this.hasSeed = hasSeed;
3287         }
3288         ScanOperator.prototype.call = function (subscriber, source) {
3289             return source.subscribe(new ScanSubscriber(subscriber, this.accumulator, this.seed, this.hasSeed));
3290         };
3291         return ScanOperator;
3292     }());
3293     var ScanSubscriber = /*@__PURE__*/ (function (_super) {
3294         __extends(ScanSubscriber, _super);
3295         function ScanSubscriber(destination, accumulator, _seed, hasSeed) {
3296             var _this = _super.call(this, destination) || this;
3297             _this.accumulator = accumulator;
3298             _this._seed = _seed;
3299             _this.hasSeed = hasSeed;
3300             _this.index = 0;
3301             return _this;
3302         }
3303         Object.defineProperty(ScanSubscriber.prototype, "seed", {
3304             get: function () {
3305                 return this._seed;
3306             },
3307             set: function (value) {
3308                 this.hasSeed = true;
3309                 this._seed = value;
3310             },
3311             enumerable: true,
3312             configurable: true
3313         });
3314         ScanSubscriber.prototype._next = function (value) {
3315             if (!this.hasSeed) {
3316                 this.seed = value;
3317                 this.destination.next(value);
3318             }
3319             else {
3320                 return this._tryNext(value);
3321             }
3322         };
3323         ScanSubscriber.prototype._tryNext = function (value) {
3324             var index = this.index++;
3325             var result;
3326             try {
3327                 result = this.accumulator(this.seed, value, index);
3328             }
3329             catch (err) {
3330                 this.destination.error(err);
3331             }
3332             this.seed = result;
3333             this.destination.next(result);
3334         };
3335         return ScanSubscriber;
3336     }(Subscriber));
3337
3338     /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */
3339     function reduce(accumulator, seed) {
3340         if (arguments.length >= 2) {
3341             return function reduceOperatorFunctionWithSeed(source) {
3342                 return pipe(scan(accumulator, seed), takeLast(1), defaultIfEmpty(seed))(source);
3343             };
3344         }
3345         return function reduceOperatorFunction(source) {
3346             return pipe(scan(function (acc, value, index) { return accumulator(acc, value, index + 1); }), takeLast(1))(source);
3347         };
3348     }
3349
3350     /** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */
3351     function multicast(subjectOrSubjectFactory, selector) {
3352         return function multicastOperatorFunction(source) {
3353             var subjectFactory;
3354             if (typeof subjectOrSubjectFactory === 'function') {
3355                 subjectFactory = subjectOrSubjectFactory;
3356             }
3357             else {
3358                 subjectFactory = function subjectFactory() {
3359                     return subjectOrSubjectFactory;
3360                 };
3361             }
3362             if (typeof selector === 'function') {
3363                 return source.lift(new MulticastOperator(subjectFactory, selector));
3364             }
3365             var connectable = Object.create(source, connectableObservableDescriptor);
3366             connectable.source = source;
3367             connectable.subjectFactory = subjectFactory;
3368             return connectable;
3369         };
3370     }
3371     var MulticastOperator = /*@__PURE__*/ (function () {
3372         function MulticastOperator(subjectFactory, selector) {
3373             this.subjectFactory = subjectFactory;
3374             this.selector = selector;
3375         }
3376         MulticastOperator.prototype.call = function (subscriber, source) {
3377             var selector = this.selector;
3378             var subject = this.subjectFactory();
3379             var subscription = selector(subject).subscribe(subscriber);
3380             subscription.add(source.subscribe(subject));
3381             return subscription;
3382         };
3383         return MulticastOperator;
3384     }());
3385
3386     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3387     function pairwise() {
3388         return function (source) { return source.lift(new PairwiseOperator()); };
3389     }
3390     var PairwiseOperator = /*@__PURE__*/ (function () {
3391         function PairwiseOperator() {
3392         }
3393         PairwiseOperator.prototype.call = function (subscriber, source) {
3394             return source.subscribe(new PairwiseSubscriber(subscriber));
3395         };
3396         return PairwiseOperator;
3397     }());
3398     var PairwiseSubscriber = /*@__PURE__*/ (function (_super) {
3399         __extends(PairwiseSubscriber, _super);
3400         function PairwiseSubscriber(destination) {
3401             var _this = _super.call(this, destination) || this;
3402             _this.hasPrev = false;
3403             return _this;
3404         }
3405         PairwiseSubscriber.prototype._next = function (value) {
3406             var pair;
3407             if (this.hasPrev) {
3408                 pair = [this.prev, value];
3409             }
3410             else {
3411                 this.hasPrev = true;
3412             }
3413             this.prev = value;
3414             if (pair) {
3415                 this.destination.next(pair);
3416             }
3417         };
3418         return PairwiseSubscriber;
3419     }(Subscriber));
3420
3421     /** PURE_IMPORTS_START _map PURE_IMPORTS_END */
3422     function pluck() {
3423         var properties = [];
3424         for (var _i = 0; _i < arguments.length; _i++) {
3425             properties[_i] = arguments[_i];
3426         }
3427         var length = properties.length;
3428         if (length === 0) {
3429             throw new Error('list of properties cannot be empty.');
3430         }
3431         return function (source) { return map(plucker(properties, length))(source); };
3432     }
3433     function plucker(props, length) {
3434         var mapper = function (x) {
3435             var currentProp = x;
3436             for (var i = 0; i < length; i++) {
3437                 var p = currentProp != null ? currentProp[props[i]] : undefined;
3438                 if (p !== void 0) {
3439                     currentProp = p;
3440                 }
3441                 else {
3442                     return undefined;
3443                 }
3444             }
3445             return currentProp;
3446         };
3447         return mapper;
3448     }
3449
3450     /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */
3451     function publish(selector) {
3452         return selector ?
3453             multicast(function () { return new Subject(); }, selector) :
3454             multicast(new Subject());
3455     }
3456
3457     /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */
3458     function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) {
3459         if (selectorOrScheduler && typeof selectorOrScheduler !== 'function') {
3460             scheduler = selectorOrScheduler;
3461         }
3462         var selector = typeof selectorOrScheduler === 'function' ? selectorOrScheduler : undefined;
3463         var subject = new ReplaySubject(bufferSize, windowTime, scheduler);
3464         return function (source) { return multicast(function () { return subject; }, selector)(source); };
3465     }
3466
3467     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3468     function retry(count) {
3469         if (count === void 0) {
3470             count = -1;
3471         }
3472         return function (source) { return source.lift(new RetryOperator(count, source)); };
3473     }
3474     var RetryOperator = /*@__PURE__*/ (function () {
3475         function RetryOperator(count, source) {
3476             this.count = count;
3477             this.source = source;
3478         }
3479         RetryOperator.prototype.call = function (subscriber, source) {
3480             return source.subscribe(new RetrySubscriber(subscriber, this.count, this.source));
3481         };
3482         return RetryOperator;
3483     }());
3484     var RetrySubscriber = /*@__PURE__*/ (function (_super) {
3485         __extends(RetrySubscriber, _super);
3486         function RetrySubscriber(destination, count, source) {
3487             var _this = _super.call(this, destination) || this;
3488             _this.count = count;
3489             _this.source = source;
3490             return _this;
3491         }
3492         RetrySubscriber.prototype.error = function (err) {
3493             if (!this.isStopped) {
3494                 var _a = this, source = _a.source, count = _a.count;
3495                 if (count === 0) {
3496                     return _super.prototype.error.call(this, err);
3497                 }
3498                 else if (count > -1) {
3499                     this.count = count - 1;
3500                 }
3501                 source.subscribe(this._unsubscribeAndRecycle());
3502             }
3503         };
3504         return RetrySubscriber;
3505     }(Subscriber));
3506
3507     /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
3508     function sample(notifier) {
3509         return function (source) { return source.lift(new SampleOperator(notifier)); };
3510     }
3511     var SampleOperator = /*@__PURE__*/ (function () {
3512         function SampleOperator(notifier) {
3513             this.notifier = notifier;
3514         }
3515         SampleOperator.prototype.call = function (subscriber, source) {
3516             var sampleSubscriber = new SampleSubscriber(subscriber);
3517             var subscription = source.subscribe(sampleSubscriber);
3518             subscription.add(innerSubscribe(this.notifier, new SimpleInnerSubscriber(sampleSubscriber)));
3519             return subscription;
3520         };
3521         return SampleOperator;
3522     }());
3523     var SampleSubscriber = /*@__PURE__*/ (function (_super) {
3524         __extends(SampleSubscriber, _super);
3525         function SampleSubscriber() {
3526             var _this = _super !== null && _super.apply(this, arguments) || this;
3527             _this.hasValue = false;
3528             return _this;
3529         }
3530         SampleSubscriber.prototype._next = function (value) {
3531             this.value = value;
3532             this.hasValue = true;
3533         };
3534         SampleSubscriber.prototype.notifyNext = function () {
3535             this.emitValue();
3536         };
3537         SampleSubscriber.prototype.notifyComplete = function () {
3538             this.emitValue();
3539         };
3540         SampleSubscriber.prototype.emitValue = function () {
3541             if (this.hasValue) {
3542                 this.hasValue = false;
3543                 this.destination.next(this.value);
3544             }
3545         };
3546         return SampleSubscriber;
3547     }(SimpleOuterSubscriber));
3548
3549     /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */
3550     function shareSubjectFactory() {
3551         return new Subject();
3552     }
3553     function share() {
3554         return function (source) { return refCount()(multicast(shareSubjectFactory)(source)); };
3555     }
3556
3557     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3558     function skip(count) {
3559         return function (source) { return source.lift(new SkipOperator(count)); };
3560     }
3561     var SkipOperator = /*@__PURE__*/ (function () {
3562         function SkipOperator(total) {
3563             this.total = total;
3564         }
3565         SkipOperator.prototype.call = function (subscriber, source) {
3566             return source.subscribe(new SkipSubscriber(subscriber, this.total));
3567         };
3568         return SkipOperator;
3569     }());
3570     var SkipSubscriber = /*@__PURE__*/ (function (_super) {
3571         __extends(SkipSubscriber, _super);
3572         function SkipSubscriber(destination, total) {
3573             var _this = _super.call(this, destination) || this;
3574             _this.total = total;
3575             _this.count = 0;
3576             return _this;
3577         }
3578         SkipSubscriber.prototype._next = function (x) {
3579             if (++this.count > this.total) {
3580                 this.destination.next(x);
3581             }
3582         };
3583         return SkipSubscriber;
3584     }(Subscriber));
3585
3586     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3587     function skipWhile(predicate) {
3588         return function (source) { return source.lift(new SkipWhileOperator(predicate)); };
3589     }
3590     var SkipWhileOperator = /*@__PURE__*/ (function () {
3591         function SkipWhileOperator(predicate) {
3592             this.predicate = predicate;
3593         }
3594         SkipWhileOperator.prototype.call = function (subscriber, source) {
3595             return source.subscribe(new SkipWhileSubscriber(subscriber, this.predicate));
3596         };
3597         return SkipWhileOperator;
3598     }());
3599     var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) {
3600         __extends(SkipWhileSubscriber, _super);
3601         function SkipWhileSubscriber(destination, predicate) {
3602             var _this = _super.call(this, destination) || this;
3603             _this.predicate = predicate;
3604             _this.skipping = true;
3605             _this.index = 0;
3606             return _this;
3607         }
3608         SkipWhileSubscriber.prototype._next = function (value) {
3609             var destination = this.destination;
3610             if (this.skipping) {
3611                 this.tryCallPredicate(value);
3612             }
3613             if (!this.skipping) {
3614                 destination.next(value);
3615             }
3616         };
3617         SkipWhileSubscriber.prototype.tryCallPredicate = function (value) {
3618             try {
3619                 var result = this.predicate(value, this.index++);
3620                 this.skipping = Boolean(result);
3621             }
3622             catch (err) {
3623                 this.destination.error(err);
3624             }
3625         };
3626         return SkipWhileSubscriber;
3627     }(Subscriber));
3628
3629     /** PURE_IMPORTS_START _observable_concat,_util_isScheduler PURE_IMPORTS_END */
3630     function startWith() {
3631         var array = [];
3632         for (var _i = 0; _i < arguments.length; _i++) {
3633             array[_i] = arguments[_i];
3634         }
3635         var scheduler = array[array.length - 1];
3636         if (isScheduler(scheduler)) {
3637             array.pop();
3638             return function (source) { return concat(array, source, scheduler); };
3639         }
3640         else {
3641             return function (source) { return concat(array, source); };
3642         }
3643     }
3644
3645     /** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */
3646     function switchMap(project, resultSelector) {
3647         if (typeof resultSelector === 'function') {
3648             return function (source) { return source.pipe(switchMap(function (a, i) { return from(project(a, i)).pipe(map(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
3649         }
3650         return function (source) { return source.lift(new SwitchMapOperator(project)); };
3651     }
3652     var SwitchMapOperator = /*@__PURE__*/ (function () {
3653         function SwitchMapOperator(project) {
3654             this.project = project;
3655         }
3656         SwitchMapOperator.prototype.call = function (subscriber, source) {
3657             return source.subscribe(new SwitchMapSubscriber(subscriber, this.project));
3658         };
3659         return SwitchMapOperator;
3660     }());
3661     var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) {
3662         __extends(SwitchMapSubscriber, _super);
3663         function SwitchMapSubscriber(destination, project) {
3664             var _this = _super.call(this, destination) || this;
3665             _this.project = project;
3666             _this.index = 0;
3667             return _this;
3668         }
3669         SwitchMapSubscriber.prototype._next = function (value) {
3670             var result;
3671             var index = this.index++;
3672             try {
3673                 result = this.project(value, index);
3674             }
3675             catch (error) {
3676                 this.destination.error(error);
3677                 return;
3678             }
3679             this._innerSub(result);
3680         };
3681         SwitchMapSubscriber.prototype._innerSub = function (result) {
3682             var innerSubscription = this.innerSubscription;
3683             if (innerSubscription) {
3684                 innerSubscription.unsubscribe();
3685             }
3686             var innerSubscriber = new SimpleInnerSubscriber(this);
3687             var destination = this.destination;
3688             destination.add(innerSubscriber);
3689             this.innerSubscription = innerSubscribe(result, innerSubscriber);
3690             if (this.innerSubscription !== innerSubscriber) {
3691                 destination.add(this.innerSubscription);
3692             }
3693         };
3694         SwitchMapSubscriber.prototype._complete = function () {
3695             var innerSubscription = this.innerSubscription;
3696             if (!innerSubscription || innerSubscription.closed) {
3697                 _super.prototype._complete.call(this);
3698             }
3699             this.unsubscribe();
3700         };
3701         SwitchMapSubscriber.prototype._unsubscribe = function () {
3702             this.innerSubscription = undefined;
3703         };
3704         SwitchMapSubscriber.prototype.notifyComplete = function () {
3705             this.innerSubscription = undefined;
3706             if (this.isStopped) {
3707                 _super.prototype._complete.call(this);
3708             }
3709         };
3710         SwitchMapSubscriber.prototype.notifyNext = function (innerValue) {
3711             this.destination.next(innerValue);
3712         };
3713         return SwitchMapSubscriber;
3714     }(SimpleOuterSubscriber));
3715
3716     /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
3717     function takeUntil(notifier) {
3718         return function (source) { return source.lift(new TakeUntilOperator(notifier)); };
3719     }
3720     var TakeUntilOperator = /*@__PURE__*/ (function () {
3721         function TakeUntilOperator(notifier) {
3722             this.notifier = notifier;
3723         }
3724         TakeUntilOperator.prototype.call = function (subscriber, source) {
3725             var takeUntilSubscriber = new TakeUntilSubscriber(subscriber);
3726             var notifierSubscription = innerSubscribe(this.notifier, new SimpleInnerSubscriber(takeUntilSubscriber));
3727             if (notifierSubscription && !takeUntilSubscriber.seenValue) {
3728                 takeUntilSubscriber.add(notifierSubscription);
3729                 return source.subscribe(takeUntilSubscriber);
3730             }
3731             return takeUntilSubscriber;
3732         };
3733         return TakeUntilOperator;
3734     }());
3735     var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) {
3736         __extends(TakeUntilSubscriber, _super);
3737         function TakeUntilSubscriber(destination) {
3738             var _this = _super.call(this, destination) || this;
3739             _this.seenValue = false;
3740             return _this;
3741         }
3742         TakeUntilSubscriber.prototype.notifyNext = function () {
3743             this.seenValue = true;
3744             this.complete();
3745         };
3746         TakeUntilSubscriber.prototype.notifyComplete = function () {
3747         };
3748         return TakeUntilSubscriber;
3749     }(SimpleOuterSubscriber));
3750
3751     /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
3752     function takeWhile(predicate, inclusive) {
3753         if (inclusive === void 0) {
3754             inclusive = false;
3755         }
3756         return function (source) {
3757             return source.lift(new TakeWhileOperator(predicate, inclusive));
3758         };
3759     }
3760     var TakeWhileOperator = /*@__PURE__*/ (function () {
3761         function TakeWhileOperator(predicate, inclusive) {
3762             this.predicate = predicate;
3763             this.inclusive = inclusive;
3764         }
3765         TakeWhileOperator.prototype.call = function (subscriber, source) {
3766             return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate, this.inclusive));
3767         };
3768         return TakeWhileOperator;
3769     }());
3770     var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) {
3771         __extends(TakeWhileSubscriber, _super);
3772         function TakeWhileSubscriber(destination, predicate, inclusive) {
3773             var _this = _super.call(this, destination) || this;
3774             _this.predicate = predicate;
3775             _this.inclusive = inclusive;
3776             _this.index = 0;
3777             return _this;
3778         }
3779         TakeWhileSubscriber.prototype._next = function (value) {
3780             var destination = this.destination;
3781             var result;
3782             try {
3783                 result = this.predicate(value, this.index++);
3784             }
3785             catch (err) {
3786                 destination.error(err);
3787                 return;
3788             }
3789             this.nextOrComplete(value, result);
3790         };
3791         TakeWhileSubscriber.prototype.nextOrComplete = function (value, predicateResult) {
3792             var destination = this.destination;
3793             if (Boolean(predicateResult)) {
3794                 destination.next(value);
3795             }
3796             else {
3797                 if (this.inclusive) {
3798                     destination.next(value);
3799                 }
3800                 destination.complete();
3801             }
3802         };
3803         return TakeWhileSubscriber;
3804     }(Subscriber));
3805
3806     /** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */
3807     function tap(nextOrObserver, error, complete) {
3808         return function tapOperatorFunction(source) {
3809             return source.lift(new DoOperator(nextOrObserver, error, complete));
3810         };
3811     }
3812     var DoOperator = /*@__PURE__*/ (function () {
3813         function DoOperator(nextOrObserver, error, complete) {
3814             this.nextOrObserver = nextOrObserver;
3815             this.error = error;
3816             this.complete = complete;
3817         }
3818         DoOperator.prototype.call = function (subscriber, source) {
3819             return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
3820         };
3821         return DoOperator;
3822     }());
3823     var TapSubscriber = /*@__PURE__*/ (function (_super) {
3824         __extends(TapSubscriber, _super);
3825         function TapSubscriber(destination, observerOrNext, error, complete) {
3826             var _this = _super.call(this, destination) || this;
3827             _this._tapNext = noop;
3828             _this._tapError = noop;
3829             _this._tapComplete = noop;
3830             _this._tapError = error || noop;
3831             _this._tapComplete = complete || noop;
3832             if (isFunction(observerOrNext)) {
3833                 _this._context = _this;
3834                 _this._tapNext = observerOrNext;
3835             }
3836             else if (observerOrNext) {
3837                 _this._context = observerOrNext;
3838                 _this._tapNext = observerOrNext.next || noop;
3839                 _this._tapError = observerOrNext.error || noop;
3840                 _this._tapComplete = observerOrNext.complete || noop;
3841             }
3842             return _this;
3843         }
3844         TapSubscriber.prototype._next = function (value) {
3845             try {
3846                 this._tapNext.call(this._context, value);
3847             }
3848             catch (err) {
3849                 this.destination.error(err);
3850                 return;
3851             }
3852             this.destination.next(value);
3853         };
3854         TapSubscriber.prototype._error = function (err) {
3855             try {
3856                 this._tapError.call(this._context, err);
3857             }
3858             catch (err) {
3859                 this.destination.error(err);
3860                 return;
3861             }
3862             this.destination.error(err);
3863         };
3864         TapSubscriber.prototype._complete = function () {
3865             try {
3866                 this._tapComplete.call(this._context);
3867             }
3868             catch (err) {
3869                 this.destination.error(err);
3870                 return;
3871             }
3872             return this.destination.complete();
3873         };
3874         return TapSubscriber;
3875     }(Subscriber));
3876
3877     /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */
3878     function timeoutWith(due, withObservable, scheduler) {
3879         if (scheduler === void 0) {
3880             scheduler = async;
3881         }
3882         return function (source) {
3883             var absoluteTimeout = isDate(due);
3884             var waitFor = absoluteTimeout ? (+due - scheduler.now()) : Math.abs(due);
3885             return source.lift(new TimeoutWithOperator(waitFor, absoluteTimeout, withObservable, scheduler));
3886         };
3887     }
3888     var TimeoutWithOperator = /*@__PURE__*/ (function () {
3889         function TimeoutWithOperator(waitFor, absoluteTimeout, withObservable, scheduler) {
3890             this.waitFor = waitFor;
3891             this.absoluteTimeout = absoluteTimeout;
3892             this.withObservable = withObservable;
3893             this.scheduler = scheduler;
3894         }
3895         TimeoutWithOperator.prototype.call = function (subscriber, source) {
3896             return source.subscribe(new TimeoutWithSubscriber(subscriber, this.absoluteTimeout, this.waitFor, this.withObservable, this.scheduler));
3897         };
3898         return TimeoutWithOperator;
3899     }());
3900     var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) {
3901         __extends(TimeoutWithSubscriber, _super);
3902         function TimeoutWithSubscriber(destination, absoluteTimeout, waitFor, withObservable, scheduler) {
3903             var _this = _super.call(this, destination) || this;
3904             _this.absoluteTimeout = absoluteTimeout;
3905             _this.waitFor = waitFor;
3906             _this.withObservable = withObservable;
3907             _this.scheduler = scheduler;
3908             _this.scheduleTimeout();
3909             return _this;
3910         }
3911         TimeoutWithSubscriber.dispatchTimeout = function (subscriber) {
3912             var withObservable = subscriber.withObservable;
3913             subscriber._unsubscribeAndRecycle();
3914             subscriber.add(innerSubscribe(withObservable, new SimpleInnerSubscriber(subscriber)));
3915         };
3916         TimeoutWithSubscriber.prototype.scheduleTimeout = function () {
3917             var action = this.action;
3918             if (action) {
3919                 this.action = action.schedule(this, this.waitFor);
3920             }
3921             else {
3922                 this.add(this.action = this.scheduler.schedule(TimeoutWithSubscriber.dispatchTimeout, this.waitFor, this));
3923             }
3924         };
3925         TimeoutWithSubscriber.prototype._next = function (value) {
3926             if (!this.absoluteTimeout) {
3927                 this.scheduleTimeout();
3928             }
3929             _super.prototype._next.call(this, value);
3930         };
3931         TimeoutWithSubscriber.prototype._unsubscribe = function () {
3932             this.action = undefined;
3933             this.scheduler = null;
3934             this.withObservable = null;
3935         };
3936         return TimeoutWithSubscriber;
3937     }(SimpleOuterSubscriber));
3938
3939     /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */
3940     function timeout(due, scheduler) {
3941         if (scheduler === void 0) {
3942             scheduler = async;
3943         }
3944         return timeoutWith(due, throwError(new TimeoutError()), scheduler);
3945     }
3946
3947     /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
3948     function withLatestFrom() {
3949         var args = [];
3950         for (var _i = 0; _i < arguments.length; _i++) {
3951             args[_i] = arguments[_i];
3952         }
3953         return function (source) {
3954             var project;
3955             if (typeof args[args.length - 1] === 'function') {
3956                 project = args.pop();
3957             }
3958             var observables = args;
3959             return source.lift(new WithLatestFromOperator(observables, project));
3960         };
3961     }
3962     var WithLatestFromOperator = /*@__PURE__*/ (function () {
3963         function WithLatestFromOperator(observables, project) {
3964             this.observables = observables;
3965             this.project = project;
3966         }
3967         WithLatestFromOperator.prototype.call = function (subscriber, source) {
3968             return source.subscribe(new WithLatestFromSubscriber(subscriber, this.observables, this.project));
3969         };
3970         return WithLatestFromOperator;
3971     }());
3972     var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) {
3973         __extends(WithLatestFromSubscriber, _super);
3974         function WithLatestFromSubscriber(destination, observables, project) {
3975             var _this = _super.call(this, destination) || this;
3976             _this.observables = observables;
3977             _this.project = project;
3978             _this.toRespond = [];
3979             var len = observables.length;
3980             _this.values = new Array(len);
3981             for (var i = 0; i < len; i++) {
3982                 _this.toRespond.push(i);
3983             }
3984             for (var i = 0; i < len; i++) {
3985                 var observable = observables[i];
3986                 _this.add(subscribeToResult(_this, observable, undefined, i));
3987             }
3988             return _this;
3989         }
3990         WithLatestFromSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) {
3991             this.values[outerIndex] = innerValue;
3992             var toRespond = this.toRespond;
3993             if (toRespond.length > 0) {
3994                 var found = toRespond.indexOf(outerIndex);
3995                 if (found !== -1) {
3996                     toRespond.splice(found, 1);
3997                 }
3998             }
3999         };
4000         WithLatestFromSubscriber.prototype.notifyComplete = function () {
4001         };
4002         WithLatestFromSubscriber.prototype._next = function (value) {
4003             if (this.toRespond.length === 0) {
4004                 var args = [value].concat(this.values);
4005                 if (this.project) {
4006                     this._tryProject(args);
4007                 }
4008                 else {
4009                     this.destination.next(args);
4010                 }
4011             }
4012         };
4013         WithLatestFromSubscriber.prototype._tryProject = function (args) {
4014             var result;
4015             try {
4016                 result = this.project.apply(this, args);
4017             }
4018             catch (err) {
4019                 this.destination.error(err);
4020                 return;
4021             }
4022             this.destination.next(result);
4023         };
4024         return WithLatestFromSubscriber;
4025     }(OuterSubscriber));
4026
4027     /**
4028      * @class Filter
4029      *
4030      * @classdesc Represents a class for creating image filters. Implementation and
4031      * definitions based on https://github.com/mapbox/feature-filter.
4032      */
4033     class FilterCreator {
4034         /**
4035          * Create a filter from a filter expression.
4036          *
4037          * @description The following filters are supported:
4038          *
4039          * Comparison
4040          * `==`
4041          * `!=`
4042          * `<`
4043          * `<=`
4044          * `>`
4045          * `>=`
4046          *
4047          * Set membership
4048          * `in`
4049          * `!in`
4050          *
4051          * Combining
4052          * `all`
4053          *
4054          * @param {FilterExpression} filter - Comparison, set membership or combinding filter
4055          * expression.
4056          * @returns {FilterFunction} Function taking a image and returning a boolean that
4057          * indicates whether the image passed the test or not.
4058          */
4059         createFilter(filter) {
4060             return new Function("node", "return " + this._compile(filter) + ";");
4061         }
4062         _compile(filter) {
4063             if (filter == null || filter.length <= 1) {
4064                 return "true";
4065             }
4066             const operator = filter[0];
4067             const operation = operator === "==" ? this._compileComparisonOp("===", filter[1], filter[2], false) :
4068                 operator === "!=" ? this._compileComparisonOp("!==", filter[1], filter[2], false) :
4069                     operator === ">" ||
4070                         operator === ">=" ||
4071                         operator === "<" ||
4072                         operator === "<=" ? this._compileComparisonOp(operator, filter[1], filter[2], true) :
4073                         operator === "in" ?
4074                             this._compileInOp(filter[1], filter.slice(2)) :
4075                             operator === "!in" ?
4076                                 this._compileNegation(this._compileInOp(filter[1], filter.slice(2))) :
4077                                 operator === "all" ? this._compileLogicalOp(filter.slice(1), "&&") :
4078                                     "true";
4079             return "(" + operation + ")";
4080         }
4081         _compare(a, b) {
4082             return a < b ? -1 : a > b ? 1 : 0;
4083         }
4084         _compileComparisonOp(operator, property, value, checkType) {
4085             const left = this._compilePropertyReference(property);
4086             const right = JSON.stringify(value);
4087             return (checkType ? "typeof " + left + "===typeof " + right + "&&" : "") + left + operator + right;
4088         }
4089         _compileInOp(property, values) {
4090             const compare = this._compare;
4091             const left = JSON.stringify(values.sort(compare));
4092             const right = this._compilePropertyReference(property);
4093             return left + ".indexOf(" + right + ")!==-1";
4094         }
4095         _compileLogicalOp(filters, operator) {
4096             const compile = this._compile.bind(this);
4097             return filters.map(compile).join(operator);
4098         }
4099         _compileNegation(expression) {
4100             return "!(" + expression + ")";
4101         }
4102         _compilePropertyReference(property) {
4103             return "node[" + JSON.stringify(property) + "]";
4104         }
4105     }
4106
4107     // threejs.org/license
4108     const REVISION = '125';
4109     const CullFaceNone = 0;
4110     const CullFaceBack = 1;
4111     const CullFaceFront = 2;
4112     const PCFShadowMap = 1;
4113     const PCFSoftShadowMap = 2;
4114     const VSMShadowMap = 3;
4115     const FrontSide = 0;
4116     const BackSide = 1;
4117     const DoubleSide = 2;
4118     const FlatShading = 1;
4119     const NoBlending = 0;
4120     const NormalBlending = 1;
4121     const AdditiveBlending = 2;
4122     const SubtractiveBlending = 3;
4123     const MultiplyBlending = 4;
4124     const CustomBlending = 5;
4125     const AddEquation = 100;
4126     const SubtractEquation = 101;
4127     const ReverseSubtractEquation = 102;
4128     const MinEquation = 103;
4129     const MaxEquation = 104;
4130     const ZeroFactor = 200;
4131     const OneFactor = 201;
4132     const SrcColorFactor = 202;
4133     const OneMinusSrcColorFactor = 203;
4134     const SrcAlphaFactor = 204;
4135     const OneMinusSrcAlphaFactor = 205;
4136     const DstAlphaFactor = 206;
4137     const OneMinusDstAlphaFactor = 207;
4138     const DstColorFactor = 208;
4139     const OneMinusDstColorFactor = 209;
4140     const SrcAlphaSaturateFactor = 210;
4141     const NeverDepth = 0;
4142     const AlwaysDepth = 1;
4143     const LessDepth = 2;
4144     const LessEqualDepth = 3;
4145     const EqualDepth = 4;
4146     const GreaterEqualDepth = 5;
4147     const GreaterDepth = 6;
4148     const NotEqualDepth = 7;
4149     const MultiplyOperation = 0;
4150     const MixOperation = 1;
4151     const AddOperation = 2;
4152     const NoToneMapping = 0;
4153     const LinearToneMapping = 1;
4154     const ReinhardToneMapping = 2;
4155     const CineonToneMapping = 3;
4156     const ACESFilmicToneMapping = 4;
4157     const CustomToneMapping = 5;
4158
4159     const UVMapping = 300;
4160     const CubeReflectionMapping = 301;
4161     const CubeRefractionMapping = 302;
4162     const EquirectangularReflectionMapping = 303;
4163     const EquirectangularRefractionMapping = 304;
4164     const CubeUVReflectionMapping = 306;
4165     const CubeUVRefractionMapping = 307;
4166     const RepeatWrapping = 1000;
4167     const ClampToEdgeWrapping = 1001;
4168     const MirroredRepeatWrapping = 1002;
4169     const NearestFilter = 1003;
4170     const NearestMipmapNearestFilter = 1004;
4171     const NearestMipmapLinearFilter = 1005;
4172     const LinearFilter = 1006;
4173     const LinearMipmapNearestFilter = 1007;
4174     const LinearMipmapLinearFilter = 1008;
4175     const UnsignedByteType = 1009;
4176     const ByteType = 1010;
4177     const ShortType = 1011;
4178     const UnsignedShortType = 1012;
4179     const IntType = 1013;
4180     const UnsignedIntType = 1014;
4181     const FloatType = 1015;
4182     const HalfFloatType = 1016;
4183     const UnsignedShort4444Type = 1017;
4184     const UnsignedShort5551Type = 1018;
4185     const UnsignedShort565Type = 1019;
4186     const UnsignedInt248Type = 1020;
4187     const AlphaFormat = 1021;
4188     const RGBFormat = 1022;
4189     const RGBAFormat = 1023;
4190     const LuminanceFormat = 1024;
4191     const LuminanceAlphaFormat = 1025;
4192     const DepthFormat = 1026;
4193     const DepthStencilFormat = 1027;
4194     const RedFormat = 1028;
4195     const RedIntegerFormat = 1029;
4196     const RGFormat = 1030;
4197     const RGIntegerFormat = 1031;
4198     const RGBIntegerFormat = 1032;
4199     const RGBAIntegerFormat = 1033;
4200
4201     const RGB_S3TC_DXT1_Format = 33776;
4202     const RGBA_S3TC_DXT1_Format = 33777;
4203     const RGBA_S3TC_DXT3_Format = 33778;
4204     const RGBA_S3TC_DXT5_Format = 33779;
4205     const RGB_PVRTC_4BPPV1_Format = 35840;
4206     const RGB_PVRTC_2BPPV1_Format = 35841;
4207     const RGBA_PVRTC_4BPPV1_Format = 35842;
4208     const RGBA_PVRTC_2BPPV1_Format = 35843;
4209     const RGB_ETC1_Format = 36196;
4210     const RGB_ETC2_Format = 37492;
4211     const RGBA_ETC2_EAC_Format = 37496;
4212     const RGBA_ASTC_4x4_Format = 37808;
4213     const RGBA_ASTC_5x4_Format = 37809;
4214     const RGBA_ASTC_5x5_Format = 37810;
4215     const RGBA_ASTC_6x5_Format = 37811;
4216     const RGBA_ASTC_6x6_Format = 37812;
4217     const RGBA_ASTC_8x5_Format = 37813;
4218     const RGBA_ASTC_8x6_Format = 37814;
4219     const RGBA_ASTC_8x8_Format = 37815;
4220     const RGBA_ASTC_10x5_Format = 37816;
4221     const RGBA_ASTC_10x6_Format = 37817;
4222     const RGBA_ASTC_10x8_Format = 37818;
4223     const RGBA_ASTC_10x10_Format = 37819;
4224     const RGBA_ASTC_12x10_Format = 37820;
4225     const RGBA_ASTC_12x12_Format = 37821;
4226     const RGBA_BPTC_Format = 36492;
4227     const SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
4228     const SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
4229     const SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
4230     const SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
4231     const SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
4232     const SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
4233     const SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
4234     const SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
4235     const SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
4236     const SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
4237     const SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
4238     const SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
4239     const SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
4240     const SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
4241     const LoopOnce = 2200;
4242     const LoopRepeat = 2201;
4243     const LoopPingPong = 2202;
4244     const InterpolateDiscrete = 2300;
4245     const InterpolateLinear = 2301;
4246     const InterpolateSmooth = 2302;
4247     const ZeroCurvatureEnding = 2400;
4248     const ZeroSlopeEnding = 2401;
4249     const WrapAroundEnding = 2402;
4250     const NormalAnimationBlendMode = 2500;
4251     const AdditiveAnimationBlendMode = 2501;
4252     const TrianglesDrawMode = 0;
4253     const LinearEncoding = 3000;
4254     const sRGBEncoding = 3001;
4255     const GammaEncoding = 3007;
4256     const RGBEEncoding = 3002;
4257     const LogLuvEncoding = 3003;
4258     const RGBM7Encoding = 3004;
4259     const RGBM16Encoding = 3005;
4260     const RGBDEncoding = 3006;
4261     const BasicDepthPacking = 3200;
4262     const RGBADepthPacking = 3201;
4263     const TangentSpaceNormalMap = 0;
4264     const ObjectSpaceNormalMap = 1;
4265     const KeepStencilOp = 7680;
4266     const AlwaysStencilFunc = 519;
4267
4268     const StaticDrawUsage = 35044;
4269     const DynamicDrawUsage = 35048;
4270     const GLSL3 = '300 es';
4271
4272     /**
4273      * https://github.com/mrdoob/eventdispatcher.js/
4274      */
4275
4276     function EventDispatcher() {}
4277
4278     Object.assign( EventDispatcher.prototype, {
4279
4280         addEventListener: function ( type, listener ) {
4281
4282                 if ( this._listeners === undefined ) this._listeners = {};
4283
4284                 const listeners = this._listeners;
4285
4286                 if ( listeners[ type ] === undefined ) {
4287
4288                         listeners[ type ] = [];
4289
4290                 }
4291
4292                 if ( listeners[ type ].indexOf( listener ) === - 1 ) {
4293
4294                         listeners[ type ].push( listener );
4295
4296                 }
4297
4298         },
4299
4300         hasEventListener: function ( type, listener ) {
4301
4302                 if ( this._listeners === undefined ) return false;
4303
4304                 const listeners = this._listeners;
4305
4306                 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
4307
4308         },
4309
4310         removeEventListener: function ( type, listener ) {
4311
4312                 if ( this._listeners === undefined ) return;
4313
4314                 const listeners = this._listeners;
4315                 const listenerArray = listeners[ type ];
4316
4317                 if ( listenerArray !== undefined ) {
4318
4319                         const index = listenerArray.indexOf( listener );
4320
4321                         if ( index !== - 1 ) {
4322
4323                                 listenerArray.splice( index, 1 );
4324
4325                         }
4326
4327                 }
4328
4329         },
4330
4331         dispatchEvent: function ( event ) {
4332
4333                 if ( this._listeners === undefined ) return;
4334
4335                 const listeners = this._listeners;
4336                 const listenerArray = listeners[ event.type ];
4337
4338                 if ( listenerArray !== undefined ) {
4339
4340                         event.target = this;
4341
4342                         // Make a copy, in case listeners are removed while iterating.
4343                         const array = listenerArray.slice( 0 );
4344
4345                         for ( let i = 0, l = array.length; i < l; i ++ ) {
4346
4347                                 array[ i ].call( this, event );
4348
4349                         }
4350
4351                 }
4352
4353         }
4354
4355     } );
4356
4357     const _lut = [];
4358
4359     for ( let i = 0; i < 256; i ++ ) {
4360
4361         _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
4362
4363     }
4364
4365     let _seed = 1234567;
4366
4367     const MathUtils = {
4368
4369         DEG2RAD: Math.PI / 180,
4370         RAD2DEG: 180 / Math.PI,
4371
4372         generateUUID: function () {
4373
4374                 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
4375
4376                 const d0 = Math.random() * 0xffffffff | 0;
4377                 const d1 = Math.random() * 0xffffffff | 0;
4378                 const d2 = Math.random() * 0xffffffff | 0;
4379                 const d3 = Math.random() * 0xffffffff | 0;
4380                 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
4381                         _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
4382                         _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
4383                         _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
4384
4385                 // .toUpperCase() here flattens concatenated strings to save heap memory space.
4386                 return uuid.toUpperCase();
4387
4388         },
4389
4390         clamp: function ( value, min, max ) {
4391
4392                 return Math.max( min, Math.min( max, value ) );
4393
4394         },
4395
4396         // compute euclidian modulo of m % n
4397         // https://en.wikipedia.org/wiki/Modulo_operation
4398
4399         euclideanModulo: function ( n, m ) {
4400
4401                 return ( ( n % m ) + m ) % m;
4402
4403         },
4404
4405         // Linear mapping from range <a1, a2> to range <b1, b2>
4406
4407         mapLinear: function ( x, a1, a2, b1, b2 ) {
4408
4409                 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
4410
4411         },
4412
4413         // https://en.wikipedia.org/wiki/Linear_interpolation
4414
4415         lerp: function ( x, y, t ) {
4416
4417                 return ( 1 - t ) * x + t * y;
4418
4419         },
4420
4421         // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
4422
4423         damp: function ( x, y, lambda, dt ) {
4424
4425                 return MathUtils.lerp( x, y, 1 - Math.exp( - lambda * dt ) );
4426
4427         },
4428
4429         // https://www.desmos.com/calculator/vcsjnyz7x4
4430
4431         pingpong: function ( x, length = 1 ) {
4432
4433                 return length - Math.abs( MathUtils.euclideanModulo( x, length * 2 ) - length );
4434
4435         },
4436
4437         // http://en.wikipedia.org/wiki/Smoothstep
4438
4439         smoothstep: function ( x, min, max ) {
4440
4441                 if ( x <= min ) return 0;
4442                 if ( x >= max ) return 1;
4443
4444                 x = ( x - min ) / ( max - min );
4445
4446                 return x * x * ( 3 - 2 * x );
4447
4448         },
4449
4450         smootherstep: function ( x, min, max ) {
4451
4452                 if ( x <= min ) return 0;
4453                 if ( x >= max ) return 1;
4454
4455                 x = ( x - min ) / ( max - min );
4456
4457                 return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
4458
4459         },
4460
4461         // Random integer from <low, high> interval
4462
4463         randInt: function ( low, high ) {
4464
4465                 return low + Math.floor( Math.random() * ( high - low + 1 ) );
4466
4467         },
4468
4469         // Random float from <low, high> interval
4470
4471         randFloat: function ( low, high ) {
4472
4473                 return low + Math.random() * ( high - low );
4474
4475         },
4476
4477         // Random float from <-range/2, range/2> interval
4478
4479         randFloatSpread: function ( range ) {
4480
4481                 return range * ( 0.5 - Math.random() );
4482
4483         },
4484
4485         // Deterministic pseudo-random float in the interval [ 0, 1 ]
4486
4487         seededRandom: function ( s ) {
4488
4489                 if ( s !== undefined ) _seed = s % 2147483647;
4490
4491                 // Park-Miller algorithm
4492
4493                 _seed = _seed * 16807 % 2147483647;
4494
4495                 return ( _seed - 1 ) / 2147483646;
4496
4497         },
4498
4499         degToRad: function ( degrees ) {
4500
4501                 return degrees * MathUtils.DEG2RAD;
4502
4503         },
4504
4505         radToDeg: function ( radians ) {
4506
4507                 return radians * MathUtils.RAD2DEG;
4508
4509         },
4510
4511         isPowerOfTwo: function ( value ) {
4512
4513                 return ( value & ( value - 1 ) ) === 0 && value !== 0;
4514
4515         },
4516
4517         ceilPowerOfTwo: function ( value ) {
4518
4519                 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
4520
4521         },
4522
4523         floorPowerOfTwo: function ( value ) {
4524
4525                 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
4526
4527         },
4528
4529         setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
4530
4531                 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
4532
4533                 // rotations are applied to the axes in the order specified by 'order'
4534                 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
4535                 // angles are in radians
4536
4537                 const cos = Math.cos;
4538                 const sin = Math.sin;
4539
4540                 const c2 = cos( b / 2 );
4541                 const s2 = sin( b / 2 );
4542
4543                 const c13 = cos( ( a + c ) / 2 );
4544                 const s13 = sin( ( a + c ) / 2 );
4545
4546                 const c1_3 = cos( ( a - c ) / 2 );
4547                 const s1_3 = sin( ( a - c ) / 2 );
4548
4549                 const c3_1 = cos( ( c - a ) / 2 );
4550                 const s3_1 = sin( ( c - a ) / 2 );
4551
4552                 switch ( order ) {
4553
4554                         case 'XYX':
4555                                 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
4556                                 break;
4557
4558                         case 'YZY':
4559                                 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
4560                                 break;
4561
4562                         case 'ZXZ':
4563                                 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
4564                                 break;
4565
4566                         case 'XZX':
4567                                 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
4568                                 break;
4569
4570                         case 'YXY':
4571                                 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
4572                                 break;
4573
4574                         case 'ZYZ':
4575                                 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
4576                                 break;
4577
4578                         default:
4579                                 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
4580
4581                 }
4582
4583         }
4584
4585     };
4586
4587     class Vector2 {
4588
4589         constructor( x = 0, y = 0 ) {
4590
4591                 Object.defineProperty( this, 'isVector2', { value: true } );
4592
4593                 this.x = x;
4594                 this.y = y;
4595
4596         }
4597
4598         get width() {
4599
4600                 return this.x;
4601
4602         }
4603
4604         set width( value ) {
4605
4606                 this.x = value;
4607
4608         }
4609
4610         get height() {
4611
4612                 return this.y;
4613
4614         }
4615
4616         set height( value ) {
4617
4618                 this.y = value;
4619
4620         }
4621
4622         set( x, y ) {
4623
4624                 this.x = x;
4625                 this.y = y;
4626
4627                 return this;
4628
4629         }
4630
4631         setScalar( scalar ) {
4632
4633                 this.x = scalar;
4634                 this.y = scalar;
4635
4636                 return this;
4637
4638         }
4639
4640         setX( x ) {
4641
4642                 this.x = x;
4643
4644                 return this;
4645
4646         }
4647
4648         setY( y ) {
4649
4650                 this.y = y;
4651
4652                 return this;
4653
4654         }
4655
4656         setComponent( index, value ) {
4657
4658                 switch ( index ) {
4659
4660                         case 0: this.x = value; break;
4661                         case 1: this.y = value; break;
4662                         default: throw new Error( 'index is out of range: ' + index );
4663
4664                 }
4665
4666                 return this;
4667
4668         }
4669
4670         getComponent( index ) {
4671
4672                 switch ( index ) {
4673
4674                         case 0: return this.x;
4675                         case 1: return this.y;
4676                         default: throw new Error( 'index is out of range: ' + index );
4677
4678                 }
4679
4680         }
4681
4682         clone() {
4683
4684                 return new this.constructor( this.x, this.y );
4685
4686         }
4687
4688         copy( v ) {
4689
4690                 this.x = v.x;
4691                 this.y = v.y;
4692
4693                 return this;
4694
4695         }
4696
4697         add( v, w ) {
4698
4699                 if ( w !== undefined ) {
4700
4701                         console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
4702                         return this.addVectors( v, w );
4703
4704                 }
4705
4706                 this.x += v.x;
4707                 this.y += v.y;
4708
4709                 return this;
4710
4711         }
4712
4713         addScalar( s ) {
4714
4715                 this.x += s;
4716                 this.y += s;
4717
4718                 return this;
4719
4720         }
4721
4722         addVectors( a, b ) {
4723
4724                 this.x = a.x + b.x;
4725                 this.y = a.y + b.y;
4726
4727                 return this;
4728
4729         }
4730
4731         addScaledVector( v, s ) {
4732
4733                 this.x += v.x * s;
4734                 this.y += v.y * s;
4735
4736                 return this;
4737
4738         }
4739
4740         sub( v, w ) {
4741
4742                 if ( w !== undefined ) {
4743
4744                         console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
4745                         return this.subVectors( v, w );
4746
4747                 }
4748
4749                 this.x -= v.x;
4750                 this.y -= v.y;
4751
4752                 return this;
4753
4754         }
4755
4756         subScalar( s ) {
4757
4758                 this.x -= s;
4759                 this.y -= s;
4760
4761                 return this;
4762
4763         }
4764
4765         subVectors( a, b ) {
4766
4767                 this.x = a.x - b.x;
4768                 this.y = a.y - b.y;
4769
4770                 return this;
4771
4772         }
4773
4774         multiply( v ) {
4775
4776                 this.x *= v.x;
4777                 this.y *= v.y;
4778
4779                 return this;
4780
4781         }
4782
4783         multiplyScalar( scalar ) {
4784
4785                 this.x *= scalar;
4786                 this.y *= scalar;
4787
4788                 return this;
4789
4790         }
4791
4792         divide( v ) {
4793
4794                 this.x /= v.x;
4795                 this.y /= v.y;
4796
4797                 return this;
4798
4799         }
4800
4801         divideScalar( scalar ) {
4802
4803                 return this.multiplyScalar( 1 / scalar );
4804
4805         }
4806
4807         applyMatrix3( m ) {
4808
4809                 const x = this.x, y = this.y;
4810                 const e = m.elements;
4811
4812                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
4813                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
4814
4815                 return this;
4816
4817         }
4818
4819         min( v ) {
4820
4821                 this.x = Math.min( this.x, v.x );
4822                 this.y = Math.min( this.y, v.y );
4823
4824                 return this;
4825
4826         }
4827
4828         max( v ) {
4829
4830                 this.x = Math.max( this.x, v.x );
4831                 this.y = Math.max( this.y, v.y );
4832
4833                 return this;
4834
4835         }
4836
4837         clamp( min, max ) {
4838
4839                 // assumes min < max, componentwise
4840
4841                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4842                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4843
4844                 return this;
4845
4846         }
4847
4848         clampScalar( minVal, maxVal ) {
4849
4850                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
4851                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
4852
4853                 return this;
4854
4855         }
4856
4857         clampLength( min, max ) {
4858
4859                 const length = this.length();
4860
4861                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4862
4863         }
4864
4865         floor() {
4866
4867                 this.x = Math.floor( this.x );
4868                 this.y = Math.floor( this.y );
4869
4870                 return this;
4871
4872         }
4873
4874         ceil() {
4875
4876                 this.x = Math.ceil( this.x );
4877                 this.y = Math.ceil( this.y );
4878
4879                 return this;
4880
4881         }
4882
4883         round() {
4884
4885                 this.x = Math.round( this.x );
4886                 this.y = Math.round( this.y );
4887
4888                 return this;
4889
4890         }
4891
4892         roundToZero() {
4893
4894                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
4895                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
4896
4897                 return this;
4898
4899         }
4900
4901         negate() {
4902
4903                 this.x = - this.x;
4904                 this.y = - this.y;
4905
4906                 return this;
4907
4908         }
4909
4910         dot( v ) {
4911
4912                 return this.x * v.x + this.y * v.y;
4913
4914         }
4915
4916         cross( v ) {
4917
4918                 return this.x * v.y - this.y * v.x;
4919
4920         }
4921
4922         lengthSq() {
4923
4924                 return this.x * this.x + this.y * this.y;
4925
4926         }
4927
4928         length() {
4929
4930                 return Math.sqrt( this.x * this.x + this.y * this.y );
4931
4932         }
4933
4934         manhattanLength() {
4935
4936                 return Math.abs( this.x ) + Math.abs( this.y );
4937
4938         }
4939
4940         normalize() {
4941
4942                 return this.divideScalar( this.length() || 1 );
4943
4944         }
4945
4946         angle() {
4947
4948                 // computes the angle in radians with respect to the positive x-axis
4949
4950                 const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
4951
4952                 return angle;
4953
4954         }
4955
4956         distanceTo( v ) {
4957
4958                 return Math.sqrt( this.distanceToSquared( v ) );
4959
4960         }
4961
4962         distanceToSquared( v ) {
4963
4964                 const dx = this.x - v.x, dy = this.y - v.y;
4965                 return dx * dx + dy * dy;
4966
4967         }
4968
4969         manhattanDistanceTo( v ) {
4970
4971                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
4972
4973         }
4974
4975         setLength( length ) {
4976
4977                 return this.normalize().multiplyScalar( length );
4978
4979         }
4980
4981         lerp( v, alpha ) {
4982
4983                 this.x += ( v.x - this.x ) * alpha;
4984                 this.y += ( v.y - this.y ) * alpha;
4985
4986                 return this;
4987
4988         }
4989
4990         lerpVectors( v1, v2, alpha ) {
4991
4992                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
4993                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
4994
4995                 return this;
4996
4997         }
4998
4999         equals( v ) {
5000
5001                 return ( ( v.x === this.x ) && ( v.y === this.y ) );
5002
5003         }
5004
5005         fromArray( array, offset = 0 ) {
5006
5007                 this.x = array[ offset ];
5008                 this.y = array[ offset + 1 ];
5009
5010                 return this;
5011
5012         }
5013
5014         toArray( array = [], offset = 0 ) {
5015
5016                 array[ offset ] = this.x;
5017                 array[ offset + 1 ] = this.y;
5018
5019                 return array;
5020
5021         }
5022
5023         fromBufferAttribute( attribute, index, offset ) {
5024
5025                 if ( offset !== undefined ) {
5026
5027                         console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
5028
5029                 }
5030
5031                 this.x = attribute.getX( index );
5032                 this.y = attribute.getY( index );
5033
5034                 return this;
5035
5036         }
5037
5038         rotateAround( center, angle ) {
5039
5040                 const c = Math.cos( angle ), s = Math.sin( angle );
5041
5042                 const x = this.x - center.x;
5043                 const y = this.y - center.y;
5044
5045                 this.x = x * c - y * s + center.x;
5046                 this.y = x * s + y * c + center.y;
5047
5048                 return this;
5049
5050         }
5051
5052         random() {
5053
5054                 this.x = Math.random();
5055                 this.y = Math.random();
5056
5057                 return this;
5058
5059         }
5060
5061     }
5062
5063     class Matrix3 {
5064
5065         constructor() {
5066
5067                 Object.defineProperty( this, 'isMatrix3', { value: true } );
5068
5069                 this.elements = [
5070
5071                         1, 0, 0,
5072                         0, 1, 0,
5073                         0, 0, 1
5074
5075                 ];
5076
5077                 if ( arguments.length > 0 ) {
5078
5079                         console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
5080
5081                 }
5082
5083         }
5084
5085         set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
5086
5087                 const te = this.elements;
5088
5089                 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
5090                 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
5091                 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
5092
5093                 return this;
5094
5095         }
5096
5097         identity() {
5098
5099                 this.set(
5100
5101                         1, 0, 0,
5102                         0, 1, 0,
5103                         0, 0, 1
5104
5105                 );
5106
5107                 return this;
5108
5109         }
5110
5111         clone() {
5112
5113                 return new this.constructor().fromArray( this.elements );
5114
5115         }
5116
5117         copy( m ) {
5118
5119                 const te = this.elements;
5120                 const me = m.elements;
5121
5122                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
5123                 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
5124                 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
5125
5126                 return this;
5127
5128         }
5129
5130         extractBasis( xAxis, yAxis, zAxis ) {
5131
5132                 xAxis.setFromMatrix3Column( this, 0 );
5133                 yAxis.setFromMatrix3Column( this, 1 );
5134                 zAxis.setFromMatrix3Column( this, 2 );
5135
5136                 return this;
5137
5138         }
5139
5140         setFromMatrix4( m ) {
5141
5142                 const me = m.elements;
5143
5144                 this.set(
5145
5146                         me[ 0 ], me[ 4 ], me[ 8 ],
5147                         me[ 1 ], me[ 5 ], me[ 9 ],
5148                         me[ 2 ], me[ 6 ], me[ 10 ]
5149
5150                 );
5151
5152                 return this;
5153
5154         }
5155
5156         multiply( m ) {
5157
5158                 return this.multiplyMatrices( this, m );
5159
5160         }
5161
5162         premultiply( m ) {
5163
5164                 return this.multiplyMatrices( m, this );
5165
5166         }
5167
5168         multiplyMatrices( a, b ) {
5169
5170                 const ae = a.elements;
5171                 const be = b.elements;
5172                 const te = this.elements;
5173
5174                 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
5175                 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
5176                 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
5177
5178                 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
5179                 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
5180                 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
5181
5182                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
5183                 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
5184                 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
5185
5186                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
5187                 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
5188                 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
5189
5190                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
5191                 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
5192                 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
5193
5194                 return this;
5195
5196         }
5197
5198         multiplyScalar( s ) {
5199
5200                 const te = this.elements;
5201
5202                 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
5203                 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
5204                 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
5205
5206                 return this;
5207
5208         }
5209
5210         determinant() {
5211
5212                 const te = this.elements;
5213
5214                 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
5215                         d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
5216                         g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
5217
5218                 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
5219
5220         }
5221
5222         invert() {
5223
5224                 const te = this.elements,
5225
5226                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
5227                         n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
5228                         n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
5229
5230                         t11 = n33 * n22 - n32 * n23,
5231                         t12 = n32 * n13 - n33 * n12,
5232                         t13 = n23 * n12 - n22 * n13,
5233
5234                         det = n11 * t11 + n21 * t12 + n31 * t13;
5235
5236                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
5237
5238                 const detInv = 1 / det;
5239
5240                 te[ 0 ] = t11 * detInv;
5241                 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
5242                 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
5243
5244                 te[ 3 ] = t12 * detInv;
5245                 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
5246                 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
5247
5248                 te[ 6 ] = t13 * detInv;
5249                 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
5250                 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
5251
5252                 return this;
5253
5254         }
5255
5256         transpose() {
5257
5258                 let tmp;
5259                 const m = this.elements;
5260
5261                 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
5262                 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
5263                 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
5264
5265                 return this;
5266
5267         }
5268
5269         getNormalMatrix( matrix4 ) {
5270
5271                 return this.setFromMatrix4( matrix4 ).copy( this ).invert().transpose();
5272
5273         }
5274
5275         transposeIntoArray( r ) {
5276
5277                 const m = this.elements;
5278
5279                 r[ 0 ] = m[ 0 ];
5280                 r[ 1 ] = m[ 3 ];
5281                 r[ 2 ] = m[ 6 ];
5282                 r[ 3 ] = m[ 1 ];
5283                 r[ 4 ] = m[ 4 ];
5284                 r[ 5 ] = m[ 7 ];
5285                 r[ 6 ] = m[ 2 ];
5286                 r[ 7 ] = m[ 5 ];
5287                 r[ 8 ] = m[ 8 ];
5288
5289                 return this;
5290
5291         }
5292
5293         setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
5294
5295                 const c = Math.cos( rotation );
5296                 const s = Math.sin( rotation );
5297
5298                 this.set(
5299                         sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
5300                         - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
5301                         0, 0, 1
5302                 );
5303
5304                 return this;
5305
5306         }
5307
5308         scale( sx, sy ) {
5309
5310                 const te = this.elements;
5311
5312                 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
5313                 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
5314
5315                 return this;
5316
5317         }
5318
5319         rotate( theta ) {
5320
5321                 const c = Math.cos( theta );
5322                 const s = Math.sin( theta );
5323
5324                 const te = this.elements;
5325
5326                 const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
5327                 const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
5328
5329                 te[ 0 ] = c * a11 + s * a21;
5330                 te[ 3 ] = c * a12 + s * a22;
5331                 te[ 6 ] = c * a13 + s * a23;
5332
5333                 te[ 1 ] = - s * a11 + c * a21;
5334                 te[ 4 ] = - s * a12 + c * a22;
5335                 te[ 7 ] = - s * a13 + c * a23;
5336
5337                 return this;
5338
5339         }
5340
5341         translate( tx, ty ) {
5342
5343                 const te = this.elements;
5344
5345                 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
5346                 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
5347
5348                 return this;
5349
5350         }
5351
5352         equals( matrix ) {
5353
5354                 const te = this.elements;
5355                 const me = matrix.elements;
5356
5357                 for ( let i = 0; i < 9; i ++ ) {
5358
5359                         if ( te[ i ] !== me[ i ] ) return false;
5360
5361                 }
5362
5363                 return true;
5364
5365         }
5366
5367         fromArray( array, offset = 0 ) {
5368
5369                 for ( let i = 0; i < 9; i ++ ) {
5370
5371                         this.elements[ i ] = array[ i + offset ];
5372
5373                 }
5374
5375                 return this;
5376
5377         }
5378
5379         toArray( array = [], offset = 0 ) {
5380
5381                 const te = this.elements;
5382
5383                 array[ offset ] = te[ 0 ];
5384                 array[ offset + 1 ] = te[ 1 ];
5385                 array[ offset + 2 ] = te[ 2 ];
5386
5387                 array[ offset + 3 ] = te[ 3 ];
5388                 array[ offset + 4 ] = te[ 4 ];
5389                 array[ offset + 5 ] = te[ 5 ];
5390
5391                 array[ offset + 6 ] = te[ 6 ];
5392                 array[ offset + 7 ] = te[ 7 ];
5393                 array[ offset + 8 ] = te[ 8 ];
5394
5395                 return array;
5396
5397         }
5398
5399     }
5400
5401     let _canvas;
5402
5403     const ImageUtils = {
5404
5405         getDataURL: function ( image ) {
5406
5407                 if ( /^data:/i.test( image.src ) ) {
5408
5409                         return image.src;
5410
5411                 }
5412
5413                 if ( typeof HTMLCanvasElement == 'undefined' ) {
5414
5415                         return image.src;
5416
5417                 }
5418
5419                 let canvas;
5420
5421                 if ( image instanceof HTMLCanvasElement ) {
5422
5423                         canvas = image;
5424
5425                 } else {
5426
5427                         if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
5428
5429                         _canvas.width = image.width;
5430                         _canvas.height = image.height;
5431
5432                         const context = _canvas.getContext( '2d' );
5433
5434                         if ( image instanceof ImageData ) {
5435
5436                                 context.putImageData( image, 0, 0 );
5437
5438                         } else {
5439
5440                                 context.drawImage( image, 0, 0, image.width, image.height );
5441
5442                         }
5443
5444                         canvas = _canvas;
5445
5446                 }
5447
5448                 if ( canvas.width > 2048 || canvas.height > 2048 ) {
5449
5450                         return canvas.toDataURL( 'image/jpeg', 0.6 );
5451
5452                 } else {
5453
5454                         return canvas.toDataURL( 'image/png' );
5455
5456                 }
5457
5458         }
5459
5460     };
5461
5462     let textureId = 0;
5463
5464     function Texture( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) {
5465
5466         Object.defineProperty( this, 'id', { value: textureId ++ } );
5467
5468         this.uuid = MathUtils.generateUUID();
5469
5470         this.name = '';
5471
5472         this.image = image;
5473         this.mipmaps = [];
5474
5475         this.mapping = mapping;
5476
5477         this.wrapS = wrapS;
5478         this.wrapT = wrapT;
5479
5480         this.magFilter = magFilter;
5481         this.minFilter = minFilter;
5482
5483         this.anisotropy = anisotropy;
5484
5485         this.format = format;
5486         this.internalFormat = null;
5487         this.type = type;
5488
5489         this.offset = new Vector2( 0, 0 );
5490         this.repeat = new Vector2( 1, 1 );
5491         this.center = new Vector2( 0, 0 );
5492         this.rotation = 0;
5493
5494         this.matrixAutoUpdate = true;
5495         this.matrix = new Matrix3();
5496
5497         this.generateMipmaps = true;
5498         this.premultiplyAlpha = false;
5499         this.flipY = true;
5500         this.unpackAlignment = 4;       // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
5501
5502         // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
5503         //
5504         // Also changing the encoding after already used by a Material will not automatically make the Material
5505         // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
5506         this.encoding = encoding;
5507
5508         this.version = 0;
5509         this.onUpdate = null;
5510
5511     }
5512
5513     Texture.DEFAULT_IMAGE = undefined;
5514     Texture.DEFAULT_MAPPING = UVMapping;
5515
5516     Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
5517
5518         constructor: Texture,
5519
5520         isTexture: true,
5521
5522         updateMatrix: function () {
5523
5524                 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
5525
5526         },
5527
5528         clone: function () {
5529
5530                 return new this.constructor().copy( this );
5531
5532         },
5533
5534         copy: function ( source ) {
5535
5536                 this.name = source.name;
5537
5538                 this.image = source.image;
5539                 this.mipmaps = source.mipmaps.slice( 0 );
5540
5541                 this.mapping = source.mapping;
5542
5543                 this.wrapS = source.wrapS;
5544                 this.wrapT = source.wrapT;
5545
5546                 this.magFilter = source.magFilter;
5547                 this.minFilter = source.minFilter;
5548
5549                 this.anisotropy = source.anisotropy;
5550
5551                 this.format = source.format;
5552                 this.internalFormat = source.internalFormat;
5553                 this.type = source.type;
5554
5555                 this.offset.copy( source.offset );
5556                 this.repeat.copy( source.repeat );
5557                 this.center.copy( source.center );
5558                 this.rotation = source.rotation;
5559
5560                 this.matrixAutoUpdate = source.matrixAutoUpdate;
5561                 this.matrix.copy( source.matrix );
5562
5563                 this.generateMipmaps = source.generateMipmaps;
5564                 this.premultiplyAlpha = source.premultiplyAlpha;
5565                 this.flipY = source.flipY;
5566                 this.unpackAlignment = source.unpackAlignment;
5567                 this.encoding = source.encoding;
5568
5569                 return this;
5570
5571         },
5572
5573         toJSON: function ( meta ) {
5574
5575                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
5576
5577                 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
5578
5579                         return meta.textures[ this.uuid ];
5580
5581                 }
5582
5583                 const output = {
5584
5585                         metadata: {
5586                                 version: 4.5,
5587                                 type: 'Texture',
5588                                 generator: 'Texture.toJSON'
5589                         },
5590
5591                         uuid: this.uuid,
5592                         name: this.name,
5593
5594                         mapping: this.mapping,
5595
5596                         repeat: [ this.repeat.x, this.repeat.y ],
5597                         offset: [ this.offset.x, this.offset.y ],
5598                         center: [ this.center.x, this.center.y ],
5599                         rotation: this.rotation,
5600
5601                         wrap: [ this.wrapS, this.wrapT ],
5602
5603                         format: this.format,
5604                         type: this.type,
5605                         encoding: this.encoding,
5606
5607                         minFilter: this.minFilter,
5608                         magFilter: this.magFilter,
5609                         anisotropy: this.anisotropy,
5610
5611                         flipY: this.flipY,
5612
5613                         premultiplyAlpha: this.premultiplyAlpha,
5614                         unpackAlignment: this.unpackAlignment
5615
5616                 };
5617
5618                 if ( this.image !== undefined ) {
5619
5620                         // TODO: Move to THREE.Image
5621
5622                         const image = this.image;
5623
5624                         if ( image.uuid === undefined ) {
5625
5626                                 image.uuid = MathUtils.generateUUID(); // UGH
5627
5628                         }
5629
5630                         if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
5631
5632                                 let url;
5633
5634                                 if ( Array.isArray( image ) ) {
5635
5636                                         // process array of images e.g. CubeTexture
5637
5638                                         url = [];
5639
5640                                         for ( let i = 0, l = image.length; i < l; i ++ ) {
5641
5642                                                 // check cube texture with data textures
5643
5644                                                 if ( image[ i ].isDataTexture ) {
5645
5646                                                         url.push( serializeImage( image[ i ].image ) );
5647
5648                                                 } else {
5649
5650                                                         url.push( serializeImage( image[ i ] ) );
5651
5652                                                 }
5653
5654                                         }
5655
5656                                 } else {
5657
5658                                         // process single image
5659
5660                                         url = serializeImage( image );
5661
5662                                 }
5663
5664                                 meta.images[ image.uuid ] = {
5665                                         uuid: image.uuid,
5666                                         url: url
5667                                 };
5668
5669                         }
5670
5671                         output.image = image.uuid;
5672
5673                 }
5674
5675                 if ( ! isRootObject ) {
5676
5677                         meta.textures[ this.uuid ] = output;
5678
5679                 }
5680
5681                 return output;
5682
5683         },
5684
5685         dispose: function () {
5686
5687                 this.dispatchEvent( { type: 'dispose' } );
5688
5689         },
5690
5691         transformUv: function ( uv ) {
5692
5693                 if ( this.mapping !== UVMapping ) return uv;
5694
5695                 uv.applyMatrix3( this.matrix );
5696
5697                 if ( uv.x < 0 || uv.x > 1 ) {
5698
5699                         switch ( this.wrapS ) {
5700
5701                                 case RepeatWrapping:
5702
5703                                         uv.x = uv.x - Math.floor( uv.x );
5704                                         break;
5705
5706                                 case ClampToEdgeWrapping:
5707
5708                                         uv.x = uv.x < 0 ? 0 : 1;
5709                                         break;
5710
5711                                 case MirroredRepeatWrapping:
5712
5713                                         if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
5714
5715                                                 uv.x = Math.ceil( uv.x ) - uv.x;
5716
5717                                         } else {
5718
5719                                                 uv.x = uv.x - Math.floor( uv.x );
5720
5721                                         }
5722
5723                                         break;
5724
5725                         }
5726
5727                 }
5728
5729                 if ( uv.y < 0 || uv.y > 1 ) {
5730
5731                         switch ( this.wrapT ) {
5732
5733                                 case RepeatWrapping:
5734
5735                                         uv.y = uv.y - Math.floor( uv.y );
5736                                         break;
5737
5738                                 case ClampToEdgeWrapping:
5739
5740                                         uv.y = uv.y < 0 ? 0 : 1;
5741                                         break;
5742
5743                                 case MirroredRepeatWrapping:
5744
5745                                         if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
5746
5747                                                 uv.y = Math.ceil( uv.y ) - uv.y;
5748
5749                                         } else {
5750
5751                                                 uv.y = uv.y - Math.floor( uv.y );
5752
5753                                         }
5754
5755                                         break;
5756
5757                         }
5758
5759                 }
5760
5761                 if ( this.flipY ) {
5762
5763                         uv.y = 1 - uv.y;
5764
5765                 }
5766
5767                 return uv;
5768
5769         }
5770
5771     } );
5772
5773     Object.defineProperty( Texture.prototype, 'needsUpdate', {
5774
5775         set: function ( value ) {
5776
5777                 if ( value === true ) this.version ++;
5778
5779         }
5780
5781     } );
5782
5783     function serializeImage( image ) {
5784
5785         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
5786                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
5787                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
5788
5789                 // default images
5790
5791                 return ImageUtils.getDataURL( image );
5792
5793         } else {
5794
5795                 if ( image.data ) {
5796
5797                         // images of DataTexture
5798
5799                         return {
5800                                 data: Array.prototype.slice.call( image.data ),
5801                                 width: image.width,
5802                                 height: image.height,
5803                                 type: image.data.constructor.name
5804                         };
5805
5806                 } else {
5807
5808                         console.warn( 'THREE.Texture: Unable to serialize Texture.' );
5809                         return {};
5810
5811                 }
5812
5813         }
5814
5815     }
5816
5817     class Vector4 {
5818
5819         constructor( x = 0, y = 0, z = 0, w = 1 ) {
5820
5821                 Object.defineProperty( this, 'isVector4', { value: true } );
5822
5823                 this.x = x;
5824                 this.y = y;
5825                 this.z = z;
5826                 this.w = w;
5827
5828         }
5829
5830         get width() {
5831
5832                 return this.z;
5833
5834         }
5835
5836         set width( value ) {
5837
5838                 this.z = value;
5839
5840         }
5841
5842         get height() {
5843
5844                 return this.w;
5845
5846         }
5847
5848         set height( value ) {
5849
5850                 this.w = value;
5851
5852         }
5853
5854         set( x, y, z, w ) {
5855
5856                 this.x = x;
5857                 this.y = y;
5858                 this.z = z;
5859                 this.w = w;
5860
5861                 return this;
5862
5863         }
5864
5865         setScalar( scalar ) {
5866
5867                 this.x = scalar;
5868                 this.y = scalar;
5869                 this.z = scalar;
5870                 this.w = scalar;
5871
5872                 return this;
5873
5874         }
5875
5876         setX( x ) {
5877
5878                 this.x = x;
5879
5880                 return this;
5881
5882         }
5883
5884         setY( y ) {
5885
5886                 this.y = y;
5887
5888                 return this;
5889
5890         }
5891
5892         setZ( z ) {
5893
5894                 this.z = z;
5895
5896                 return this;
5897
5898         }
5899
5900         setW( w ) {
5901
5902                 this.w = w;
5903
5904                 return this;
5905
5906         }
5907
5908         setComponent( index, value ) {
5909
5910                 switch ( index ) {
5911
5912                         case 0: this.x = value; break;
5913                         case 1: this.y = value; break;
5914                         case 2: this.z = value; break;
5915                         case 3: this.w = value; break;
5916                         default: throw new Error( 'index is out of range: ' + index );
5917
5918                 }
5919
5920                 return this;
5921
5922         }
5923
5924         getComponent( index ) {
5925
5926                 switch ( index ) {
5927
5928                         case 0: return this.x;
5929                         case 1: return this.y;
5930                         case 2: return this.z;
5931                         case 3: return this.w;
5932                         default: throw new Error( 'index is out of range: ' + index );
5933
5934                 }
5935
5936         }
5937
5938         clone() {
5939
5940                 return new this.constructor( this.x, this.y, this.z, this.w );
5941
5942         }
5943
5944         copy( v ) {
5945
5946                 this.x = v.x;
5947                 this.y = v.y;
5948                 this.z = v.z;
5949                 this.w = ( v.w !== undefined ) ? v.w : 1;
5950
5951                 return this;
5952
5953         }
5954
5955         add( v, w ) {
5956
5957                 if ( w !== undefined ) {
5958
5959                         console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
5960                         return this.addVectors( v, w );
5961
5962                 }
5963
5964                 this.x += v.x;
5965                 this.y += v.y;
5966                 this.z += v.z;
5967                 this.w += v.w;
5968
5969                 return this;
5970
5971         }
5972
5973         addScalar( s ) {
5974
5975                 this.x += s;
5976                 this.y += s;
5977                 this.z += s;
5978                 this.w += s;
5979
5980                 return this;
5981
5982         }
5983
5984         addVectors( a, b ) {
5985
5986                 this.x = a.x + b.x;
5987                 this.y = a.y + b.y;
5988                 this.z = a.z + b.z;
5989                 this.w = a.w + b.w;
5990
5991                 return this;
5992
5993         }
5994
5995         addScaledVector( v, s ) {
5996
5997                 this.x += v.x * s;
5998                 this.y += v.y * s;
5999                 this.z += v.z * s;
6000                 this.w += v.w * s;
6001
6002                 return this;
6003
6004         }
6005
6006         sub( v, w ) {
6007
6008                 if ( w !== undefined ) {
6009
6010                         console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
6011                         return this.subVectors( v, w );
6012
6013                 }
6014
6015                 this.x -= v.x;
6016                 this.y -= v.y;
6017                 this.z -= v.z;
6018                 this.w -= v.w;
6019
6020                 return this;
6021
6022         }
6023
6024         subScalar( s ) {
6025
6026                 this.x -= s;
6027                 this.y -= s;
6028                 this.z -= s;
6029                 this.w -= s;
6030
6031                 return this;
6032
6033         }
6034
6035         subVectors( a, b ) {
6036
6037                 this.x = a.x - b.x;
6038                 this.y = a.y - b.y;
6039                 this.z = a.z - b.z;
6040                 this.w = a.w - b.w;
6041
6042                 return this;
6043
6044         }
6045
6046         multiply( v ) {
6047
6048                 this.x *= v.x;
6049                 this.y *= v.y;
6050                 this.z *= v.z;
6051                 this.w *= v.w;
6052
6053                 return this;
6054
6055         }
6056
6057         multiplyScalar( scalar ) {
6058
6059                 this.x *= scalar;
6060                 this.y *= scalar;
6061                 this.z *= scalar;
6062                 this.w *= scalar;
6063
6064                 return this;
6065
6066         }
6067
6068         applyMatrix4( m ) {
6069
6070                 const x = this.x, y = this.y, z = this.z, w = this.w;
6071                 const e = m.elements;
6072
6073                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
6074                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
6075                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
6076                 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
6077
6078                 return this;
6079
6080         }
6081
6082         divideScalar( scalar ) {
6083
6084                 return this.multiplyScalar( 1 / scalar );
6085
6086         }
6087
6088         setAxisAngleFromQuaternion( q ) {
6089
6090                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
6091
6092                 // q is assumed to be normalized
6093
6094                 this.w = 2 * Math.acos( q.w );
6095
6096                 const s = Math.sqrt( 1 - q.w * q.w );
6097
6098                 if ( s < 0.0001 ) {
6099
6100                         this.x = 1;
6101                         this.y = 0;
6102                         this.z = 0;
6103
6104                 } else {
6105
6106                         this.x = q.x / s;
6107                         this.y = q.y / s;
6108                         this.z = q.z / s;
6109
6110                 }
6111
6112                 return this;
6113
6114         }
6115
6116         setAxisAngleFromRotationMatrix( m ) {
6117
6118                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
6119
6120                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6121
6122                 let angle, x, y, z; // variables for result
6123                 const epsilon = 0.01,           // margin to allow for rounding errors
6124                         epsilon2 = 0.1,         // margin to distinguish between 0 and 180 degrees
6125
6126                         te = m.elements,
6127
6128                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
6129                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
6130                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6131
6132                 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
6133                      ( Math.abs( m13 - m31 ) < epsilon ) &&
6134                      ( Math.abs( m23 - m32 ) < epsilon ) ) {
6135
6136                         // singularity found
6137                         // first check for identity matrix which must have +1 for all terms
6138                         // in leading diagonal and zero in other terms
6139
6140                         if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
6141                              ( Math.abs( m13 + m31 ) < epsilon2 ) &&
6142                              ( Math.abs( m23 + m32 ) < epsilon2 ) &&
6143                              ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
6144
6145                                 // this singularity is identity matrix so angle = 0
6146
6147                                 this.set( 1, 0, 0, 0 );
6148
6149                                 return this; // zero angle, arbitrary axis
6150
6151                         }
6152
6153                         // otherwise this singularity is angle = 180
6154
6155                         angle = Math.PI;
6156
6157                         const xx = ( m11 + 1 ) / 2;
6158                         const yy = ( m22 + 1 ) / 2;
6159                         const zz = ( m33 + 1 ) / 2;
6160                         const xy = ( m12 + m21 ) / 4;
6161                         const xz = ( m13 + m31 ) / 4;
6162                         const yz = ( m23 + m32 ) / 4;
6163
6164                         if ( ( xx > yy ) && ( xx > zz ) ) {
6165
6166                                 // m11 is the largest diagonal term
6167
6168                                 if ( xx < epsilon ) {
6169
6170                                         x = 0;
6171                                         y = 0.707106781;
6172                                         z = 0.707106781;
6173
6174                                 } else {
6175
6176                                         x = Math.sqrt( xx );
6177                                         y = xy / x;
6178                                         z = xz / x;
6179
6180                                 }
6181
6182                         } else if ( yy > zz ) {
6183
6184                                 // m22 is the largest diagonal term
6185
6186                                 if ( yy < epsilon ) {
6187
6188                                         x = 0.707106781;
6189                                         y = 0;
6190                                         z = 0.707106781;
6191
6192                                 } else {
6193
6194                                         y = Math.sqrt( yy );
6195                                         x = xy / y;
6196                                         z = yz / y;
6197
6198                                 }
6199
6200                         } else {
6201
6202                                 // m33 is the largest diagonal term so base result on this
6203
6204                                 if ( zz < epsilon ) {
6205
6206                                         x = 0.707106781;
6207                                         y = 0.707106781;
6208                                         z = 0;
6209
6210                                 } else {
6211
6212                                         z = Math.sqrt( zz );
6213                                         x = xz / z;
6214                                         y = yz / z;
6215
6216                                 }
6217
6218                         }
6219
6220                         this.set( x, y, z, angle );
6221
6222                         return this; // return 180 deg rotation
6223
6224                 }
6225
6226                 // as we have reached here there are no singularities so we can handle normally
6227
6228                 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
6229                         ( m13 - m31 ) * ( m13 - m31 ) +
6230                         ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
6231
6232                 if ( Math.abs( s ) < 0.001 ) s = 1;
6233
6234                 // prevent divide by zero, should not happen if matrix is orthogonal and should be
6235                 // caught by singularity test above, but I've left it in just in case
6236
6237                 this.x = ( m32 - m23 ) / s;
6238                 this.y = ( m13 - m31 ) / s;
6239                 this.z = ( m21 - m12 ) / s;
6240                 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
6241
6242                 return this;
6243
6244         }
6245
6246         min( v ) {
6247
6248                 this.x = Math.min( this.x, v.x );
6249                 this.y = Math.min( this.y, v.y );
6250                 this.z = Math.min( this.z, v.z );
6251                 this.w = Math.min( this.w, v.w );
6252
6253                 return this;
6254
6255         }
6256
6257         max( v ) {
6258
6259                 this.x = Math.max( this.x, v.x );
6260                 this.y = Math.max( this.y, v.y );
6261                 this.z = Math.max( this.z, v.z );
6262                 this.w = Math.max( this.w, v.w );
6263
6264                 return this;
6265
6266         }
6267
6268         clamp( min, max ) {
6269
6270                 // assumes min < max, componentwise
6271
6272                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
6273                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
6274                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
6275                 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
6276
6277                 return this;
6278
6279         }
6280
6281         clampScalar( minVal, maxVal ) {
6282
6283                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
6284                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
6285                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
6286                 this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
6287
6288                 return this;
6289
6290         }
6291
6292         clampLength( min, max ) {
6293
6294                 const length = this.length();
6295
6296                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
6297
6298         }
6299
6300         floor() {
6301
6302                 this.x = Math.floor( this.x );
6303                 this.y = Math.floor( this.y );
6304                 this.z = Math.floor( this.z );
6305                 this.w = Math.floor( this.w );
6306
6307                 return this;
6308
6309         }
6310
6311         ceil() {
6312
6313                 this.x = Math.ceil( this.x );
6314                 this.y = Math.ceil( this.y );
6315                 this.z = Math.ceil( this.z );
6316                 this.w = Math.ceil( this.w );
6317
6318                 return this;
6319
6320         }
6321
6322         round() {
6323
6324                 this.x = Math.round( this.x );
6325                 this.y = Math.round( this.y );
6326                 this.z = Math.round( this.z );
6327                 this.w = Math.round( this.w );
6328
6329                 return this;
6330
6331         }
6332
6333         roundToZero() {
6334
6335                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
6336                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
6337                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
6338                 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
6339
6340                 return this;
6341
6342         }
6343
6344         negate() {
6345
6346                 this.x = - this.x;
6347                 this.y = - this.y;
6348                 this.z = - this.z;
6349                 this.w = - this.w;
6350
6351                 return this;
6352
6353         }
6354
6355         dot( v ) {
6356
6357                 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
6358
6359         }
6360
6361         lengthSq() {
6362
6363                 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
6364
6365         }
6366
6367         length() {
6368
6369                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
6370
6371         }
6372
6373         manhattanLength() {
6374
6375                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
6376
6377         }
6378
6379         normalize() {
6380
6381                 return this.divideScalar( this.length() || 1 );
6382
6383         }
6384
6385         setLength( length ) {
6386
6387                 return this.normalize().multiplyScalar( length );
6388
6389         }
6390
6391         lerp( v, alpha ) {
6392
6393                 this.x += ( v.x - this.x ) * alpha;
6394                 this.y += ( v.y - this.y ) * alpha;
6395                 this.z += ( v.z - this.z ) * alpha;
6396                 this.w += ( v.w - this.w ) * alpha;
6397
6398                 return this;
6399
6400         }
6401
6402         lerpVectors( v1, v2, alpha ) {
6403
6404                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
6405                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
6406                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
6407                 this.w = v1.w + ( v2.w - v1.w ) * alpha;
6408
6409                 return this;
6410
6411         }
6412
6413         equals( v ) {
6414
6415                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
6416
6417         }
6418
6419         fromArray( array, offset = 0 ) {
6420
6421                 this.x = array[ offset ];
6422                 this.y = array[ offset + 1 ];
6423                 this.z = array[ offset + 2 ];
6424                 this.w = array[ offset + 3 ];
6425
6426                 return this;
6427
6428         }
6429
6430         toArray( array = [], offset = 0 ) {
6431
6432                 array[ offset ] = this.x;
6433                 array[ offset + 1 ] = this.y;
6434                 array[ offset + 2 ] = this.z;
6435                 array[ offset + 3 ] = this.w;
6436
6437                 return array;
6438
6439         }
6440
6441         fromBufferAttribute( attribute, index, offset ) {
6442
6443                 if ( offset !== undefined ) {
6444
6445                         console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
6446
6447                 }
6448
6449                 this.x = attribute.getX( index );
6450                 this.y = attribute.getY( index );
6451                 this.z = attribute.getZ( index );
6452                 this.w = attribute.getW( index );
6453
6454                 return this;
6455
6456         }
6457
6458         random() {
6459
6460                 this.x = Math.random();
6461                 this.y = Math.random();
6462                 this.z = Math.random();
6463                 this.w = Math.random();
6464
6465                 return this;
6466
6467         }
6468
6469     }
6470
6471     /*
6472      In options, we can specify:
6473      * Texture parameters for an auto-generated target texture
6474      * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
6475     */
6476     class WebGLRenderTarget extends EventDispatcher {
6477
6478         constructor( width, height, options ) {
6479
6480                 super();
6481
6482                 Object.defineProperty( this, 'isWebGLRenderTarget', { value: true } );
6483
6484                 this.width = width;
6485                 this.height = height;
6486
6487                 this.scissor = new Vector4( 0, 0, width, height );
6488                 this.scissorTest = false;
6489
6490                 this.viewport = new Vector4( 0, 0, width, height );
6491
6492                 options = options || {};
6493
6494                 this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
6495
6496                 this.texture.image = {};
6497                 this.texture.image.width = width;
6498                 this.texture.image.height = height;
6499
6500                 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
6501                 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
6502
6503                 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
6504                 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
6505                 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
6506
6507         }
6508
6509         setSize( width, height ) {
6510
6511                 if ( this.width !== width || this.height !== height ) {
6512
6513                         this.width = width;
6514                         this.height = height;
6515
6516                         this.texture.image.width = width;
6517                         this.texture.image.height = height;
6518
6519                         this.dispose();
6520
6521                 }
6522
6523                 this.viewport.set( 0, 0, width, height );
6524                 this.scissor.set( 0, 0, width, height );
6525
6526         }
6527
6528         clone() {
6529
6530                 return new this.constructor().copy( this );
6531
6532         }
6533
6534         copy( source ) {
6535
6536                 this.width = source.width;
6537                 this.height = source.height;
6538
6539                 this.viewport.copy( source.viewport );
6540
6541                 this.texture = source.texture.clone();
6542
6543                 this.depthBuffer = source.depthBuffer;
6544                 this.stencilBuffer = source.stencilBuffer;
6545                 this.depthTexture = source.depthTexture;
6546
6547                 return this;
6548
6549         }
6550
6551         dispose() {
6552
6553                 this.dispatchEvent( { type: 'dispose' } );
6554
6555         }
6556
6557     }
6558
6559     class Quaternion {
6560
6561         constructor( x = 0, y = 0, z = 0, w = 1 ) {
6562
6563                 Object.defineProperty( this, 'isQuaternion', { value: true } );
6564
6565                 this._x = x;
6566                 this._y = y;
6567                 this._z = z;
6568                 this._w = w;
6569
6570         }
6571
6572         static slerp( qa, qb, qm, t ) {
6573
6574                 return qm.copy( qa ).slerp( qb, t );
6575
6576         }
6577
6578         static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
6579
6580                 // fuzz-free, array-based Quaternion SLERP operation
6581
6582                 let x0 = src0[ srcOffset0 + 0 ],
6583                         y0 = src0[ srcOffset0 + 1 ],
6584                         z0 = src0[ srcOffset0 + 2 ],
6585                         w0 = src0[ srcOffset0 + 3 ];
6586
6587                 const x1 = src1[ srcOffset1 + 0 ],
6588                         y1 = src1[ srcOffset1 + 1 ],
6589                         z1 = src1[ srcOffset1 + 2 ],
6590                         w1 = src1[ srcOffset1 + 3 ];
6591
6592                 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
6593
6594                         let s = 1 - t;
6595                         const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
6596                                 dir = ( cos >= 0 ? 1 : - 1 ),
6597                                 sqrSin = 1 - cos * cos;
6598
6599                         // Skip the Slerp for tiny steps to avoid numeric problems:
6600                         if ( sqrSin > Number.EPSILON ) {
6601
6602                                 const sin = Math.sqrt( sqrSin ),
6603                                         len = Math.atan2( sin, cos * dir );
6604
6605                                 s = Math.sin( s * len ) / sin;
6606                                 t = Math.sin( t * len ) / sin;
6607
6608                         }
6609
6610                         const tDir = t * dir;
6611
6612                         x0 = x0 * s + x1 * tDir;
6613                         y0 = y0 * s + y1 * tDir;
6614                         z0 = z0 * s + z1 * tDir;
6615                         w0 = w0 * s + w1 * tDir;
6616
6617                         // Normalize in case we just did a lerp:
6618                         if ( s === 1 - t ) {
6619
6620                                 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
6621
6622                                 x0 *= f;
6623                                 y0 *= f;
6624                                 z0 *= f;
6625                                 w0 *= f;
6626
6627                         }
6628
6629                 }
6630
6631                 dst[ dstOffset ] = x0;
6632                 dst[ dstOffset + 1 ] = y0;
6633                 dst[ dstOffset + 2 ] = z0;
6634                 dst[ dstOffset + 3 ] = w0;
6635
6636         }
6637
6638         static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
6639
6640                 const x0 = src0[ srcOffset0 ];
6641                 const y0 = src0[ srcOffset0 + 1 ];
6642                 const z0 = src0[ srcOffset0 + 2 ];
6643                 const w0 = src0[ srcOffset0 + 3 ];
6644
6645                 const x1 = src1[ srcOffset1 ];
6646                 const y1 = src1[ srcOffset1 + 1 ];
6647                 const z1 = src1[ srcOffset1 + 2 ];
6648                 const w1 = src1[ srcOffset1 + 3 ];
6649
6650                 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
6651                 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
6652                 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
6653                 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
6654
6655                 return dst;
6656
6657         }
6658
6659         get x() {
6660
6661                 return this._x;
6662
6663         }
6664
6665         set x( value ) {
6666
6667                 this._x = value;
6668                 this._onChangeCallback();
6669
6670         }
6671
6672         get y() {
6673
6674                 return this._y;
6675
6676         }
6677
6678         set y( value ) {
6679
6680                 this._y = value;
6681                 this._onChangeCallback();
6682
6683         }
6684
6685         get z() {
6686
6687                 return this._z;
6688
6689         }
6690
6691         set z( value ) {
6692
6693                 this._z = value;
6694                 this._onChangeCallback();
6695
6696         }
6697
6698         get w() {
6699
6700                 return this._w;
6701
6702         }
6703
6704         set w( value ) {
6705
6706                 this._w = value;
6707                 this._onChangeCallback();
6708
6709         }
6710
6711         set( x, y, z, w ) {
6712
6713                 this._x = x;
6714                 this._y = y;
6715                 this._z = z;
6716                 this._w = w;
6717
6718                 this._onChangeCallback();
6719
6720                 return this;
6721
6722         }
6723
6724         clone() {
6725
6726                 return new this.constructor( this._x, this._y, this._z, this._w );
6727
6728         }
6729
6730         copy( quaternion ) {
6731
6732                 this._x = quaternion.x;
6733                 this._y = quaternion.y;
6734                 this._z = quaternion.z;
6735                 this._w = quaternion.w;
6736
6737                 this._onChangeCallback();
6738
6739                 return this;
6740
6741         }
6742
6743         setFromEuler( euler, update ) {
6744
6745                 if ( ! ( euler && euler.isEuler ) ) {
6746
6747                         throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
6748
6749                 }
6750
6751                 const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
6752
6753                 // http://www.mathworks.com/matlabcentral/fileexchange/
6754                 //      20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
6755                 //      content/SpinCalc.m
6756
6757                 const cos = Math.cos;
6758                 const sin = Math.sin;
6759
6760                 const c1 = cos( x / 2 );
6761                 const c2 = cos( y / 2 );
6762                 const c3 = cos( z / 2 );
6763
6764                 const s1 = sin( x / 2 );
6765                 const s2 = sin( y / 2 );
6766                 const s3 = sin( z / 2 );
6767
6768                 switch ( order ) {
6769
6770                         case 'XYZ':
6771                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
6772                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
6773                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
6774                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
6775                                 break;
6776
6777                         case 'YXZ':
6778                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
6779                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
6780                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
6781                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
6782                                 break;
6783
6784                         case 'ZXY':
6785                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
6786                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
6787                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
6788                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
6789                                 break;
6790
6791                         case 'ZYX':
6792                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
6793                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
6794                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
6795                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
6796                                 break;
6797
6798                         case 'YZX':
6799                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
6800                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
6801                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
6802                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
6803                                 break;
6804
6805                         case 'XZY':
6806                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
6807                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
6808                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
6809                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
6810                                 break;
6811
6812                         default:
6813                                 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
6814
6815                 }
6816
6817                 if ( update !== false ) this._onChangeCallback();
6818
6819                 return this;
6820
6821         }
6822
6823         setFromAxisAngle( axis, angle ) {
6824
6825                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
6826
6827                 // assumes axis is normalized
6828
6829                 const halfAngle = angle / 2, s = Math.sin( halfAngle );
6830
6831                 this._x = axis.x * s;
6832                 this._y = axis.y * s;
6833                 this._z = axis.z * s;
6834                 this._w = Math.cos( halfAngle );
6835
6836                 this._onChangeCallback();
6837
6838                 return this;
6839
6840         }
6841
6842         setFromRotationMatrix( m ) {
6843
6844                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
6845
6846                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6847
6848                 const te = m.elements,
6849
6850                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
6851                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
6852                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
6853
6854                         trace = m11 + m22 + m33;
6855
6856                 if ( trace > 0 ) {
6857
6858                         const s = 0.5 / Math.sqrt( trace + 1.0 );
6859
6860                         this._w = 0.25 / s;
6861                         this._x = ( m32 - m23 ) * s;
6862                         this._y = ( m13 - m31 ) * s;
6863                         this._z = ( m21 - m12 ) * s;
6864
6865                 } else if ( m11 > m22 && m11 > m33 ) {
6866
6867                         const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
6868
6869                         this._w = ( m32 - m23 ) / s;
6870                         this._x = 0.25 * s;
6871                         this._y = ( m12 + m21 ) / s;
6872                         this._z = ( m13 + m31 ) / s;
6873
6874                 } else if ( m22 > m33 ) {
6875
6876                         const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
6877
6878                         this._w = ( m13 - m31 ) / s;
6879                         this._x = ( m12 + m21 ) / s;
6880                         this._y = 0.25 * s;
6881                         this._z = ( m23 + m32 ) / s;
6882
6883                 } else {
6884
6885                         const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
6886
6887                         this._w = ( m21 - m12 ) / s;
6888                         this._x = ( m13 + m31 ) / s;
6889                         this._y = ( m23 + m32 ) / s;
6890                         this._z = 0.25 * s;
6891
6892                 }
6893
6894                 this._onChangeCallback();
6895
6896                 return this;
6897
6898         }
6899
6900         setFromUnitVectors( vFrom, vTo ) {
6901
6902                 // assumes direction vectors vFrom and vTo are normalized
6903
6904                 const EPS = 0.000001;
6905
6906                 let r = vFrom.dot( vTo ) + 1;
6907
6908                 if ( r < EPS ) {
6909
6910                         r = 0;
6911
6912                         if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
6913
6914                                 this._x = - vFrom.y;
6915                                 this._y = vFrom.x;
6916                                 this._z = 0;
6917                                 this._w = r;
6918
6919                         } else {
6920
6921                                 this._x = 0;
6922                                 this._y = - vFrom.z;
6923                                 this._z = vFrom.y;
6924                                 this._w = r;
6925
6926                         }
6927
6928                 } else {
6929
6930                         // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
6931
6932                         this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
6933                         this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
6934                         this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
6935                         this._w = r;
6936
6937                 }
6938
6939                 return this.normalize();
6940
6941         }
6942
6943         angleTo( q ) {
6944
6945                 return 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );
6946
6947         }
6948
6949         rotateTowards( q, step ) {
6950
6951                 const angle = this.angleTo( q );
6952
6953                 if ( angle === 0 ) return this;
6954
6955                 const t = Math.min( 1, step / angle );
6956
6957                 this.slerp( q, t );
6958
6959                 return this;
6960
6961         }
6962
6963         identity() {
6964
6965                 return this.set( 0, 0, 0, 1 );
6966
6967         }
6968
6969         invert() {
6970
6971                 // quaternion is assumed to have unit length
6972
6973                 return this.conjugate();
6974
6975         }
6976
6977         conjugate() {
6978
6979                 this._x *= - 1;
6980                 this._y *= - 1;
6981                 this._z *= - 1;
6982
6983                 this._onChangeCallback();
6984
6985                 return this;
6986
6987         }
6988
6989         dot( v ) {
6990
6991                 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
6992
6993         }
6994
6995         lengthSq() {
6996
6997                 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
6998
6999         }
7000
7001         length() {
7002
7003                 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
7004
7005         }
7006
7007         normalize() {
7008
7009                 let l = this.length();
7010
7011                 if ( l === 0 ) {
7012
7013                         this._x = 0;
7014                         this._y = 0;
7015                         this._z = 0;
7016                         this._w = 1;
7017
7018                 } else {
7019
7020                         l = 1 / l;
7021
7022                         this._x = this._x * l;
7023                         this._y = this._y * l;
7024                         this._z = this._z * l;
7025                         this._w = this._w * l;
7026
7027                 }
7028
7029                 this._onChangeCallback();
7030
7031                 return this;
7032
7033         }
7034
7035         multiply( q, p ) {
7036
7037                 if ( p !== undefined ) {
7038
7039                         console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
7040                         return this.multiplyQuaternions( q, p );
7041
7042                 }
7043
7044                 return this.multiplyQuaternions( this, q );
7045
7046         }
7047
7048         premultiply( q ) {
7049
7050                 return this.multiplyQuaternions( q, this );
7051
7052         }
7053
7054         multiplyQuaternions( a, b ) {
7055
7056                 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
7057
7058                 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
7059                 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
7060
7061                 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
7062                 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
7063                 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
7064                 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
7065
7066                 this._onChangeCallback();
7067
7068                 return this;
7069
7070         }
7071
7072         slerp( qb, t ) {
7073
7074                 if ( t === 0 ) return this;
7075                 if ( t === 1 ) return this.copy( qb );
7076
7077                 const x = this._x, y = this._y, z = this._z, w = this._w;
7078
7079                 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
7080
7081                 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
7082
7083                 if ( cosHalfTheta < 0 ) {
7084
7085                         this._w = - qb._w;
7086                         this._x = - qb._x;
7087                         this._y = - qb._y;
7088                         this._z = - qb._z;
7089
7090                         cosHalfTheta = - cosHalfTheta;
7091
7092                 } else {
7093
7094                         this.copy( qb );
7095
7096                 }
7097
7098                 if ( cosHalfTheta >= 1.0 ) {
7099
7100                         this._w = w;
7101                         this._x = x;
7102                         this._y = y;
7103                         this._z = z;
7104
7105                         return this;
7106
7107                 }
7108
7109                 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
7110
7111                 if ( sqrSinHalfTheta <= Number.EPSILON ) {
7112
7113                         const s = 1 - t;
7114                         this._w = s * w + t * this._w;
7115                         this._x = s * x + t * this._x;
7116                         this._y = s * y + t * this._y;
7117                         this._z = s * z + t * this._z;
7118
7119                         this.normalize();
7120                         this._onChangeCallback();
7121
7122                         return this;
7123
7124                 }
7125
7126                 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
7127                 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
7128                 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
7129                         ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
7130
7131                 this._w = ( w * ratioA + this._w * ratioB );
7132                 this._x = ( x * ratioA + this._x * ratioB );
7133                 this._y = ( y * ratioA + this._y * ratioB );
7134                 this._z = ( z * ratioA + this._z * ratioB );
7135
7136                 this._onChangeCallback();
7137
7138                 return this;
7139
7140         }
7141
7142         equals( quaternion ) {
7143
7144                 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
7145
7146         }
7147
7148         fromArray( array, offset = 0 ) {
7149
7150                 this._x = array[ offset ];
7151                 this._y = array[ offset + 1 ];
7152                 this._z = array[ offset + 2 ];
7153                 this._w = array[ offset + 3 ];
7154
7155                 this._onChangeCallback();
7156
7157                 return this;
7158
7159         }
7160
7161         toArray( array = [], offset = 0 ) {
7162
7163                 array[ offset ] = this._x;
7164                 array[ offset + 1 ] = this._y;
7165                 array[ offset + 2 ] = this._z;
7166                 array[ offset + 3 ] = this._w;
7167
7168                 return array;
7169
7170         }
7171
7172         fromBufferAttribute( attribute, index ) {
7173
7174                 this._x = attribute.getX( index );
7175                 this._y = attribute.getY( index );
7176                 this._z = attribute.getZ( index );
7177                 this._w = attribute.getW( index );
7178
7179                 return this;
7180
7181         }
7182
7183         _onChange( callback ) {
7184
7185                 this._onChangeCallback = callback;
7186
7187                 return this;
7188
7189         }
7190
7191         _onChangeCallback() {}
7192
7193     }
7194
7195     class Vector3 {
7196
7197         constructor( x = 0, y = 0, z = 0 ) {
7198
7199                 Object.defineProperty( this, 'isVector3', { value: true } );
7200
7201                 this.x = x;
7202                 this.y = y;
7203                 this.z = z;
7204
7205         }
7206
7207         set( x, y, z ) {
7208
7209                 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
7210
7211                 this.x = x;
7212                 this.y = y;
7213                 this.z = z;
7214
7215                 return this;
7216
7217         }
7218
7219         setScalar( scalar ) {
7220
7221                 this.x = scalar;
7222                 this.y = scalar;
7223                 this.z = scalar;
7224
7225                 return this;
7226
7227         }
7228
7229         setX( x ) {
7230
7231                 this.x = x;
7232
7233                 return this;
7234
7235         }
7236
7237         setY( y ) {
7238
7239                 this.y = y;
7240
7241                 return this;
7242
7243         }
7244
7245         setZ( z ) {
7246
7247                 this.z = z;
7248
7249                 return this;
7250
7251         }
7252
7253         setComponent( index, value ) {
7254
7255                 switch ( index ) {
7256
7257                         case 0: this.x = value; break;
7258                         case 1: this.y = value; break;
7259                         case 2: this.z = value; break;
7260                         default: throw new Error( 'index is out of range: ' + index );
7261
7262                 }
7263
7264                 return this;
7265
7266         }
7267
7268         getComponent( index ) {
7269
7270                 switch ( index ) {
7271
7272                         case 0: return this.x;
7273                         case 1: return this.y;
7274                         case 2: return this.z;
7275                         default: throw new Error( 'index is out of range: ' + index );
7276
7277                 }
7278
7279         }
7280
7281         clone() {
7282
7283                 return new this.constructor( this.x, this.y, this.z );
7284
7285         }
7286
7287         copy( v ) {
7288
7289                 this.x = v.x;
7290                 this.y = v.y;
7291                 this.z = v.z;
7292
7293                 return this;
7294
7295         }
7296
7297         add( v, w ) {
7298
7299                 if ( w !== undefined ) {
7300
7301                         console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
7302                         return this.addVectors( v, w );
7303
7304                 }
7305
7306                 this.x += v.x;
7307                 this.y += v.y;
7308                 this.z += v.z;
7309
7310                 return this;
7311
7312         }
7313
7314         addScalar( s ) {
7315
7316                 this.x += s;
7317                 this.y += s;
7318                 this.z += s;
7319
7320                 return this;
7321
7322         }
7323
7324         addVectors( a, b ) {
7325
7326                 this.x = a.x + b.x;
7327                 this.y = a.y + b.y;
7328                 this.z = a.z + b.z;
7329
7330                 return this;
7331
7332         }
7333
7334         addScaledVector( v, s ) {
7335
7336                 this.x += v.x * s;
7337                 this.y += v.y * s;
7338                 this.z += v.z * s;
7339
7340                 return this;
7341
7342         }
7343
7344         sub( v, w ) {
7345
7346                 if ( w !== undefined ) {
7347
7348                         console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
7349                         return this.subVectors( v, w );
7350
7351                 }
7352
7353                 this.x -= v.x;
7354                 this.y -= v.y;
7355                 this.z -= v.z;
7356
7357                 return this;
7358
7359         }
7360
7361         subScalar( s ) {
7362
7363                 this.x -= s;
7364                 this.y -= s;
7365                 this.z -= s;
7366
7367                 return this;
7368
7369         }
7370
7371         subVectors( a, b ) {
7372
7373                 this.x = a.x - b.x;
7374                 this.y = a.y - b.y;
7375                 this.z = a.z - b.z;
7376
7377                 return this;
7378
7379         }
7380
7381         multiply( v, w ) {
7382
7383                 if ( w !== undefined ) {
7384
7385                         console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
7386                         return this.multiplyVectors( v, w );
7387
7388                 }
7389
7390                 this.x *= v.x;
7391                 this.y *= v.y;
7392                 this.z *= v.z;
7393
7394                 return this;
7395
7396         }
7397
7398         multiplyScalar( scalar ) {
7399
7400                 this.x *= scalar;
7401                 this.y *= scalar;
7402                 this.z *= scalar;
7403
7404                 return this;
7405
7406         }
7407
7408         multiplyVectors( a, b ) {
7409
7410                 this.x = a.x * b.x;
7411                 this.y = a.y * b.y;
7412                 this.z = a.z * b.z;
7413
7414                 return this;
7415
7416         }
7417
7418         applyEuler( euler ) {
7419
7420                 if ( ! ( euler && euler.isEuler ) ) {
7421
7422                         console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
7423
7424                 }
7425
7426                 return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
7427
7428         }
7429
7430         applyAxisAngle( axis, angle ) {
7431
7432                 return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
7433
7434         }
7435
7436         applyMatrix3( m ) {
7437
7438                 const x = this.x, y = this.y, z = this.z;
7439                 const e = m.elements;
7440
7441                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
7442                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
7443                 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
7444
7445                 return this;
7446
7447         }
7448
7449         applyNormalMatrix( m ) {
7450
7451                 return this.applyMatrix3( m ).normalize();
7452
7453         }
7454
7455         applyMatrix4( m ) {
7456
7457                 const x = this.x, y = this.y, z = this.z;
7458                 const e = m.elements;
7459
7460                 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
7461
7462                 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
7463                 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
7464                 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
7465
7466                 return this;
7467
7468         }
7469
7470         applyQuaternion( q ) {
7471
7472                 const x = this.x, y = this.y, z = this.z;
7473                 const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
7474
7475                 // calculate quat * vector
7476
7477                 const ix = qw * x + qy * z - qz * y;
7478                 const iy = qw * y + qz * x - qx * z;
7479                 const iz = qw * z + qx * y - qy * x;
7480                 const iw = - qx * x - qy * y - qz * z;
7481
7482                 // calculate result * inverse quat
7483
7484                 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
7485                 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
7486                 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
7487
7488                 return this;
7489
7490         }
7491
7492         project( camera ) {
7493
7494                 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
7495
7496         }
7497
7498         unproject( camera ) {
7499
7500                 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
7501
7502         }
7503
7504         transformDirection( m ) {
7505
7506                 // input: THREE.Matrix4 affine matrix
7507                 // vector interpreted as a direction
7508
7509                 const x = this.x, y = this.y, z = this.z;
7510                 const e = m.elements;
7511
7512                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
7513                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
7514                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
7515
7516                 return this.normalize();
7517
7518         }
7519
7520         divide( v ) {
7521
7522                 this.x /= v.x;
7523                 this.y /= v.y;
7524                 this.z /= v.z;
7525
7526                 return this;
7527
7528         }
7529
7530         divideScalar( scalar ) {
7531
7532                 return this.multiplyScalar( 1 / scalar );
7533
7534         }
7535
7536         min( v ) {
7537
7538                 this.x = Math.min( this.x, v.x );
7539                 this.y = Math.min( this.y, v.y );
7540                 this.z = Math.min( this.z, v.z );
7541
7542                 return this;
7543
7544         }
7545
7546         max( v ) {
7547
7548                 this.x = Math.max( this.x, v.x );
7549                 this.y = Math.max( this.y, v.y );
7550                 this.z = Math.max( this.z, v.z );
7551
7552                 return this;
7553
7554         }
7555
7556         clamp( min, max ) {
7557
7558                 // assumes min < max, componentwise
7559
7560                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
7561                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
7562                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
7563
7564                 return this;
7565
7566         }
7567
7568         clampScalar( minVal, maxVal ) {
7569
7570                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
7571                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
7572                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
7573
7574                 return this;
7575
7576         }
7577
7578         clampLength( min, max ) {
7579
7580                 const length = this.length();
7581
7582                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
7583
7584         }
7585
7586         floor() {
7587
7588                 this.x = Math.floor( this.x );
7589                 this.y = Math.floor( this.y );
7590                 this.z = Math.floor( this.z );
7591
7592                 return this;
7593
7594         }
7595
7596         ceil() {
7597
7598                 this.x = Math.ceil( this.x );
7599                 this.y = Math.ceil( this.y );
7600                 this.z = Math.ceil( this.z );
7601
7602                 return this;
7603
7604         }
7605
7606         round() {
7607
7608                 this.x = Math.round( this.x );
7609                 this.y = Math.round( this.y );
7610                 this.z = Math.round( this.z );
7611
7612                 return this;
7613
7614         }
7615
7616         roundToZero() {
7617
7618                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
7619                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
7620                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
7621
7622                 return this;
7623
7624         }
7625
7626         negate() {
7627
7628                 this.x = - this.x;
7629                 this.y = - this.y;
7630                 this.z = - this.z;
7631
7632                 return this;
7633
7634         }
7635
7636         dot( v ) {
7637
7638                 return this.x * v.x + this.y * v.y + this.z * v.z;
7639
7640         }
7641
7642         // TODO lengthSquared?
7643
7644         lengthSq() {
7645
7646                 return this.x * this.x + this.y * this.y + this.z * this.z;
7647
7648         }
7649
7650         length() {
7651
7652                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
7653
7654         }
7655
7656         manhattanLength() {
7657
7658                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
7659
7660         }
7661
7662         normalize() {
7663
7664                 return this.divideScalar( this.length() || 1 );
7665
7666         }
7667
7668         setLength( length ) {
7669
7670                 return this.normalize().multiplyScalar( length );
7671
7672         }
7673
7674         lerp( v, alpha ) {
7675
7676                 this.x += ( v.x - this.x ) * alpha;
7677                 this.y += ( v.y - this.y ) * alpha;
7678                 this.z += ( v.z - this.z ) * alpha;
7679
7680                 return this;
7681
7682         }
7683
7684         lerpVectors( v1, v2, alpha ) {
7685
7686                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
7687                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
7688                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
7689
7690                 return this;
7691
7692         }
7693
7694         cross( v, w ) {
7695
7696                 if ( w !== undefined ) {
7697
7698                         console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
7699                         return this.crossVectors( v, w );
7700
7701                 }
7702
7703                 return this.crossVectors( this, v );
7704
7705         }
7706
7707         crossVectors( a, b ) {
7708
7709                 const ax = a.x, ay = a.y, az = a.z;
7710                 const bx = b.x, by = b.y, bz = b.z;
7711
7712                 this.x = ay * bz - az * by;
7713                 this.y = az * bx - ax * bz;
7714                 this.z = ax * by - ay * bx;
7715
7716                 return this;
7717
7718         }
7719
7720         projectOnVector( v ) {
7721
7722                 const denominator = v.lengthSq();
7723
7724                 if ( denominator === 0 ) return this.set( 0, 0, 0 );
7725
7726                 const scalar = v.dot( this ) / denominator;
7727
7728                 return this.copy( v ).multiplyScalar( scalar );
7729
7730         }
7731
7732         projectOnPlane( planeNormal ) {
7733
7734                 _vector.copy( this ).projectOnVector( planeNormal );
7735
7736                 return this.sub( _vector );
7737
7738         }
7739
7740         reflect( normal ) {
7741
7742                 // reflect incident vector off plane orthogonal to normal
7743                 // normal is assumed to have unit length
7744
7745                 return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
7746
7747         }
7748
7749         angleTo( v ) {
7750
7751                 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
7752
7753                 if ( denominator === 0 ) return Math.PI / 2;
7754
7755                 const theta = this.dot( v ) / denominator;
7756
7757                 // clamp, to handle numerical problems
7758
7759                 return Math.acos( MathUtils.clamp( theta, - 1, 1 ) );
7760
7761         }
7762
7763         distanceTo( v ) {
7764
7765                 return Math.sqrt( this.distanceToSquared( v ) );
7766
7767         }
7768
7769         distanceToSquared( v ) {
7770
7771                 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
7772
7773                 return dx * dx + dy * dy + dz * dz;
7774
7775         }
7776
7777         manhattanDistanceTo( v ) {
7778
7779                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
7780
7781         }
7782
7783         setFromSpherical( s ) {
7784
7785                 return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
7786
7787         }
7788
7789         setFromSphericalCoords( radius, phi, theta ) {
7790
7791                 const sinPhiRadius = Math.sin( phi ) * radius;
7792
7793                 this.x = sinPhiRadius * Math.sin( theta );
7794                 this.y = Math.cos( phi ) * radius;
7795                 this.z = sinPhiRadius * Math.cos( theta );
7796
7797                 return this;
7798
7799         }
7800
7801         setFromCylindrical( c ) {
7802
7803                 return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
7804
7805         }
7806
7807         setFromCylindricalCoords( radius, theta, y ) {
7808
7809                 this.x = radius * Math.sin( theta );
7810                 this.y = y;
7811                 this.z = radius * Math.cos( theta );
7812
7813                 return this;
7814
7815         }
7816
7817         setFromMatrixPosition( m ) {
7818
7819                 const e = m.elements;
7820
7821                 this.x = e[ 12 ];
7822                 this.y = e[ 13 ];
7823                 this.z = e[ 14 ];
7824
7825                 return this;
7826
7827         }
7828
7829         setFromMatrixScale( m ) {
7830
7831                 const sx = this.setFromMatrixColumn( m, 0 ).length();
7832                 const sy = this.setFromMatrixColumn( m, 1 ).length();
7833                 const sz = this.setFromMatrixColumn( m, 2 ).length();
7834
7835                 this.x = sx;
7836                 this.y = sy;
7837                 this.z = sz;
7838
7839                 return this;
7840
7841         }
7842
7843         setFromMatrixColumn( m, index ) {
7844
7845                 return this.fromArray( m.elements, index * 4 );
7846
7847         }
7848
7849         setFromMatrix3Column( m, index ) {
7850
7851                 return this.fromArray( m.elements, index * 3 );
7852
7853         }
7854
7855         equals( v ) {
7856
7857                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
7858
7859         }
7860
7861         fromArray( array, offset = 0 ) {
7862
7863                 this.x = array[ offset ];
7864                 this.y = array[ offset + 1 ];
7865                 this.z = array[ offset + 2 ];
7866
7867                 return this;
7868
7869         }
7870
7871         toArray( array = [], offset = 0 ) {
7872
7873                 array[ offset ] = this.x;
7874                 array[ offset + 1 ] = this.y;
7875                 array[ offset + 2 ] = this.z;
7876
7877                 return array;
7878
7879         }
7880
7881         fromBufferAttribute( attribute, index, offset ) {
7882
7883                 if ( offset !== undefined ) {
7884
7885                         console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
7886
7887                 }
7888
7889                 this.x = attribute.getX( index );
7890                 this.y = attribute.getY( index );
7891                 this.z = attribute.getZ( index );
7892
7893                 return this;
7894
7895         }
7896
7897         random() {
7898
7899                 this.x = Math.random();
7900                 this.y = Math.random();
7901                 this.z = Math.random();
7902
7903                 return this;
7904
7905         }
7906
7907     }
7908
7909     const _vector = /*@__PURE__*/ new Vector3();
7910     const _quaternion = /*@__PURE__*/ new Quaternion();
7911
7912     class Box3 {
7913
7914         constructor( min, max ) {
7915
7916                 Object.defineProperty( this, 'isBox3', { value: true } );
7917
7918                 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
7919                 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
7920
7921         }
7922
7923         set( min, max ) {
7924
7925                 this.min.copy( min );
7926                 this.max.copy( max );
7927
7928                 return this;
7929
7930         }
7931
7932         setFromArray( array ) {
7933
7934                 let minX = + Infinity;
7935                 let minY = + Infinity;
7936                 let minZ = + Infinity;
7937
7938                 let maxX = - Infinity;
7939                 let maxY = - Infinity;
7940                 let maxZ = - Infinity;
7941
7942                 for ( let i = 0, l = array.length; i < l; i += 3 ) {
7943
7944                         const x = array[ i ];
7945                         const y = array[ i + 1 ];
7946                         const z = array[ i + 2 ];
7947
7948                         if ( x < minX ) minX = x;
7949                         if ( y < minY ) minY = y;
7950                         if ( z < minZ ) minZ = z;
7951
7952                         if ( x > maxX ) maxX = x;
7953                         if ( y > maxY ) maxY = y;
7954                         if ( z > maxZ ) maxZ = z;
7955
7956                 }
7957
7958                 this.min.set( minX, minY, minZ );
7959                 this.max.set( maxX, maxY, maxZ );
7960
7961                 return this;
7962
7963         }
7964
7965         setFromBufferAttribute( attribute ) {
7966
7967                 let minX = + Infinity;
7968                 let minY = + Infinity;
7969                 let minZ = + Infinity;
7970
7971                 let maxX = - Infinity;
7972                 let maxY = - Infinity;
7973                 let maxZ = - Infinity;
7974
7975                 for ( let i = 0, l = attribute.count; i < l; i ++ ) {
7976
7977                         const x = attribute.getX( i );
7978                         const y = attribute.getY( i );
7979                         const z = attribute.getZ( i );
7980
7981                         if ( x < minX ) minX = x;
7982                         if ( y < minY ) minY = y;
7983                         if ( z < minZ ) minZ = z;
7984
7985                         if ( x > maxX ) maxX = x;
7986                         if ( y > maxY ) maxY = y;
7987                         if ( z > maxZ ) maxZ = z;
7988
7989                 }
7990
7991                 this.min.set( minX, minY, minZ );
7992                 this.max.set( maxX, maxY, maxZ );
7993
7994                 return this;
7995
7996         }
7997
7998         setFromPoints( points ) {
7999
8000                 this.makeEmpty();
8001
8002                 for ( let i = 0, il = points.length; i < il; i ++ ) {
8003
8004                         this.expandByPoint( points[ i ] );
8005
8006                 }
8007
8008                 return this;
8009
8010         }
8011
8012         setFromCenterAndSize( center, size ) {
8013
8014                 const halfSize = _vector$1.copy( size ).multiplyScalar( 0.5 );
8015
8016                 this.min.copy( center ).sub( halfSize );
8017                 this.max.copy( center ).add( halfSize );
8018
8019                 return this;
8020
8021         }
8022
8023         setFromObject( object ) {
8024
8025                 this.makeEmpty();
8026
8027                 return this.expandByObject( object );
8028
8029         }
8030
8031         clone() {
8032
8033                 return new this.constructor().copy( this );
8034
8035         }
8036
8037         copy( box ) {
8038
8039                 this.min.copy( box.min );
8040                 this.max.copy( box.max );
8041
8042                 return this;
8043
8044         }
8045
8046         makeEmpty() {
8047
8048                 this.min.x = this.min.y = this.min.z = + Infinity;
8049                 this.max.x = this.max.y = this.max.z = - Infinity;
8050
8051                 return this;
8052
8053         }
8054
8055         isEmpty() {
8056
8057                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
8058
8059                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
8060
8061         }
8062
8063         getCenter( target ) {
8064
8065                 if ( target === undefined ) {
8066
8067                         console.warn( 'THREE.Box3: .getCenter() target is now required' );
8068                         target = new Vector3();
8069
8070                 }
8071
8072                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
8073
8074         }
8075
8076         getSize( target ) {
8077
8078                 if ( target === undefined ) {
8079
8080                         console.warn( 'THREE.Box3: .getSize() target is now required' );
8081                         target = new Vector3();
8082
8083                 }
8084
8085                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
8086
8087         }
8088
8089         expandByPoint( point ) {
8090
8091                 this.min.min( point );
8092                 this.max.max( point );
8093
8094                 return this;
8095
8096         }
8097
8098         expandByVector( vector ) {
8099
8100                 this.min.sub( vector );
8101                 this.max.add( vector );
8102
8103                 return this;
8104
8105         }
8106
8107         expandByScalar( scalar ) {
8108
8109                 this.min.addScalar( - scalar );
8110                 this.max.addScalar( scalar );
8111
8112                 return this;
8113
8114         }
8115
8116         expandByObject( object ) {
8117
8118                 // Computes the world-axis-aligned bounding box of an object (including its children),
8119                 // accounting for both the object's, and children's, world transforms
8120
8121                 object.updateWorldMatrix( false, false );
8122
8123                 const geometry = object.geometry;
8124
8125                 if ( geometry !== undefined ) {
8126
8127                         if ( geometry.boundingBox === null ) {
8128
8129                                 geometry.computeBoundingBox();
8130
8131                         }
8132
8133                         _box.copy( geometry.boundingBox );
8134                         _box.applyMatrix4( object.matrixWorld );
8135
8136                         this.union( _box );
8137
8138                 }
8139
8140                 const children = object.children;
8141
8142                 for ( let i = 0, l = children.length; i < l; i ++ ) {
8143
8144                         this.expandByObject( children[ i ] );
8145
8146                 }
8147
8148                 return this;
8149
8150         }
8151
8152         containsPoint( point ) {
8153
8154                 return point.x < this.min.x || point.x > this.max.x ||
8155                         point.y < this.min.y || point.y > this.max.y ||
8156                         point.z < this.min.z || point.z > this.max.z ? false : true;
8157
8158         }
8159
8160         containsBox( box ) {
8161
8162                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
8163                         this.min.y <= box.min.y && box.max.y <= this.max.y &&
8164                         this.min.z <= box.min.z && box.max.z <= this.max.z;
8165
8166         }
8167
8168         getParameter( point, target ) {
8169
8170                 // This can potentially have a divide by zero if the box
8171                 // has a size dimension of 0.
8172
8173                 if ( target === undefined ) {
8174
8175                         console.warn( 'THREE.Box3: .getParameter() target is now required' );
8176                         target = new Vector3();
8177
8178                 }
8179
8180                 return target.set(
8181                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
8182                         ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
8183                         ( point.z - this.min.z ) / ( this.max.z - this.min.z )
8184                 );
8185
8186         }
8187
8188         intersectsBox( box ) {
8189
8190                 // using 6 splitting planes to rule out intersections.
8191                 return box.max.x < this.min.x || box.min.x > this.max.x ||
8192                         box.max.y < this.min.y || box.min.y > this.max.y ||
8193                         box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
8194
8195         }
8196
8197         intersectsSphere( sphere ) {
8198
8199                 // Find the point on the AABB closest to the sphere center.
8200                 this.clampPoint( sphere.center, _vector$1 );
8201
8202                 // If that point is inside the sphere, the AABB and sphere intersect.
8203                 return _vector$1.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
8204
8205         }
8206
8207         intersectsPlane( plane ) {
8208
8209                 // We compute the minimum and maximum dot product values. If those values
8210                 // are on the same side (back or front) of the plane, then there is no intersection.
8211
8212                 let min, max;
8213
8214                 if ( plane.normal.x > 0 ) {
8215
8216                         min = plane.normal.x * this.min.x;
8217                         max = plane.normal.x * this.max.x;
8218
8219                 } else {
8220
8221                         min = plane.normal.x * this.max.x;
8222                         max = plane.normal.x * this.min.x;
8223
8224                 }
8225
8226                 if ( plane.normal.y > 0 ) {
8227
8228                         min += plane.normal.y * this.min.y;
8229                         max += plane.normal.y * this.max.y;
8230
8231                 } else {
8232
8233                         min += plane.normal.y * this.max.y;
8234                         max += plane.normal.y * this.min.y;
8235
8236                 }
8237
8238                 if ( plane.normal.z > 0 ) {
8239
8240                         min += plane.normal.z * this.min.z;
8241                         max += plane.normal.z * this.max.z;
8242
8243                 } else {
8244
8245                         min += plane.normal.z * this.max.z;
8246                         max += plane.normal.z * this.min.z;
8247
8248                 }
8249
8250                 return ( min <= - plane.constant && max >= - plane.constant );
8251
8252         }
8253
8254         intersectsTriangle( triangle ) {
8255
8256                 if ( this.isEmpty() ) {
8257
8258                         return false;
8259
8260                 }
8261
8262                 // compute box center and extents
8263                 this.getCenter( _center );
8264                 _extents.subVectors( this.max, _center );
8265
8266                 // translate triangle to aabb origin
8267                 _v0.subVectors( triangle.a, _center );
8268                 _v1.subVectors( triangle.b, _center );
8269                 _v2.subVectors( triangle.c, _center );
8270
8271                 // compute edge vectors for triangle
8272                 _f0.subVectors( _v1, _v0 );
8273                 _f1.subVectors( _v2, _v1 );
8274                 _f2.subVectors( _v0, _v2 );
8275
8276                 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
8277                 // 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
8278                 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
8279                 let axes = [
8280                         0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
8281                         _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
8282                         - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
8283                 ];
8284                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
8285
8286                         return false;
8287
8288                 }
8289
8290                 // test 3 face normals from the aabb
8291                 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
8292                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
8293
8294                         return false;
8295
8296                 }
8297
8298                 // finally testing the face normal of the triangle
8299                 // use already existing triangle edge vectors here
8300                 _triangleNormal.crossVectors( _f0, _f1 );
8301                 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
8302
8303                 return satForAxes( axes, _v0, _v1, _v2, _extents );
8304
8305         }
8306
8307         clampPoint( point, target ) {
8308
8309                 if ( target === undefined ) {
8310
8311                         console.warn( 'THREE.Box3: .clampPoint() target is now required' );
8312                         target = new Vector3();
8313
8314                 }
8315
8316                 return target.copy( point ).clamp( this.min, this.max );
8317
8318         }
8319
8320         distanceToPoint( point ) {
8321
8322                 const clampedPoint = _vector$1.copy( point ).clamp( this.min, this.max );
8323
8324                 return clampedPoint.sub( point ).length();
8325
8326         }
8327
8328         getBoundingSphere( target ) {
8329
8330                 if ( target === undefined ) {
8331
8332                         console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
8333                         //target = new Sphere(); // removed to avoid cyclic dependency
8334
8335                 }
8336
8337                 this.getCenter( target.center );
8338
8339                 target.radius = this.getSize( _vector$1 ).length() * 0.5;
8340
8341                 return target;
8342
8343         }
8344
8345         intersect( box ) {
8346
8347                 this.min.max( box.min );
8348                 this.max.min( box.max );
8349
8350                 // 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.
8351                 if ( this.isEmpty() ) this.makeEmpty();
8352
8353                 return this;
8354
8355         }
8356
8357         union( box ) {
8358
8359                 this.min.min( box.min );
8360                 this.max.max( box.max );
8361
8362                 return this;
8363
8364         }
8365
8366         applyMatrix4( matrix ) {
8367
8368                 // transform of empty box is an empty box.
8369                 if ( this.isEmpty() ) return this;
8370
8371                 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
8372                 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
8373                 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
8374                 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
8375                 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
8376                 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
8377                 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
8378                 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
8379                 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
8380
8381                 this.setFromPoints( _points );
8382
8383                 return this;
8384
8385         }
8386
8387         translate( offset ) {
8388
8389                 this.min.add( offset );
8390                 this.max.add( offset );
8391
8392                 return this;
8393
8394         }
8395
8396         equals( box ) {
8397
8398                 return box.min.equals( this.min ) && box.max.equals( this.max );
8399
8400         }
8401
8402     }
8403
8404     function satForAxes( axes, v0, v1, v2, extents ) {
8405
8406         for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
8407
8408                 _testAxis.fromArray( axes, i );
8409                 // project the aabb onto the seperating axis
8410                 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
8411                 // project all 3 vertices of the triangle onto the seperating axis
8412                 const p0 = v0.dot( _testAxis );
8413                 const p1 = v1.dot( _testAxis );
8414                 const p2 = v2.dot( _testAxis );
8415                 // actual test, basically see if either of the most extreme of the triangle points intersects r
8416                 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
8417
8418                         // points of the projected triangle are outside the projected half-length of the aabb
8419                         // the axis is seperating and we can exit
8420                         return false;
8421
8422                 }
8423
8424         }
8425
8426         return true;
8427
8428     }
8429
8430     const _points = [
8431         /*@__PURE__*/ new Vector3(),
8432         /*@__PURE__*/ new Vector3(),
8433         /*@__PURE__*/ new Vector3(),
8434         /*@__PURE__*/ new Vector3(),
8435         /*@__PURE__*/ new Vector3(),
8436         /*@__PURE__*/ new Vector3(),
8437         /*@__PURE__*/ new Vector3(),
8438         /*@__PURE__*/ new Vector3()
8439     ];
8440
8441     const _vector$1 = /*@__PURE__*/ new Vector3();
8442
8443     const _box = /*@__PURE__*/ new Box3();
8444
8445     // triangle centered vertices
8446
8447     const _v0 = /*@__PURE__*/ new Vector3();
8448     const _v1 = /*@__PURE__*/ new Vector3();
8449     const _v2 = /*@__PURE__*/ new Vector3();
8450
8451     // triangle edge vectors
8452
8453     const _f0 = /*@__PURE__*/ new Vector3();
8454     const _f1 = /*@__PURE__*/ new Vector3();
8455     const _f2 = /*@__PURE__*/ new Vector3();
8456
8457     const _center = /*@__PURE__*/ new Vector3();
8458     const _extents = /*@__PURE__*/ new Vector3();
8459     const _triangleNormal = /*@__PURE__*/ new Vector3();
8460     const _testAxis = /*@__PURE__*/ new Vector3();
8461
8462     const _box$1 = /*@__PURE__*/ new Box3();
8463
8464     class Sphere {
8465
8466         constructor( center, radius ) {
8467
8468                 this.center = ( center !== undefined ) ? center : new Vector3();
8469                 this.radius = ( radius !== undefined ) ? radius : - 1;
8470
8471         }
8472
8473         set( center, radius ) {
8474
8475                 this.center.copy( center );
8476                 this.radius = radius;
8477
8478                 return this;
8479
8480         }
8481
8482         setFromPoints( points, optionalCenter ) {
8483
8484                 const center = this.center;
8485
8486                 if ( optionalCenter !== undefined ) {
8487
8488                         center.copy( optionalCenter );
8489
8490                 } else {
8491
8492                         _box$1.setFromPoints( points ).getCenter( center );
8493
8494                 }
8495
8496                 let maxRadiusSq = 0;
8497
8498                 for ( let i = 0, il = points.length; i < il; i ++ ) {
8499
8500                         maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
8501
8502                 }
8503
8504                 this.radius = Math.sqrt( maxRadiusSq );
8505
8506                 return this;
8507
8508         }
8509
8510         clone() {
8511
8512                 return new this.constructor().copy( this );
8513
8514         }
8515
8516         copy( sphere ) {
8517
8518                 this.center.copy( sphere.center );
8519                 this.radius = sphere.radius;
8520
8521                 return this;
8522
8523         }
8524
8525         isEmpty() {
8526
8527                 return ( this.radius < 0 );
8528
8529         }
8530
8531         makeEmpty() {
8532
8533                 this.center.set( 0, 0, 0 );
8534                 this.radius = - 1;
8535
8536                 return this;
8537
8538         }
8539
8540         containsPoint( point ) {
8541
8542                 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
8543
8544         }
8545
8546         distanceToPoint( point ) {
8547
8548                 return ( point.distanceTo( this.center ) - this.radius );
8549
8550         }
8551
8552         intersectsSphere( sphere ) {
8553
8554                 const radiusSum = this.radius + sphere.radius;
8555
8556                 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
8557
8558         }
8559
8560         intersectsBox( box ) {
8561
8562                 return box.intersectsSphere( this );
8563
8564         }
8565
8566         intersectsPlane( plane ) {
8567
8568                 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
8569
8570         }
8571
8572         clampPoint( point, target ) {
8573
8574                 const deltaLengthSq = this.center.distanceToSquared( point );
8575
8576                 if ( target === undefined ) {
8577
8578                         console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
8579                         target = new Vector3();
8580
8581                 }
8582
8583                 target.copy( point );
8584
8585                 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
8586
8587                         target.sub( this.center ).normalize();
8588                         target.multiplyScalar( this.radius ).add( this.center );
8589
8590                 }
8591
8592                 return target;
8593
8594         }
8595
8596         getBoundingBox( target ) {
8597
8598                 if ( target === undefined ) {
8599
8600                         console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
8601                         target = new Box3();
8602
8603                 }
8604
8605                 if ( this.isEmpty() ) {
8606
8607                         // Empty sphere produces empty bounding box
8608                         target.makeEmpty();
8609                         return target;
8610
8611                 }
8612
8613                 target.set( this.center, this.center );
8614                 target.expandByScalar( this.radius );
8615
8616                 return target;
8617
8618         }
8619
8620         applyMatrix4( matrix ) {
8621
8622                 this.center.applyMatrix4( matrix );
8623                 this.radius = this.radius * matrix.getMaxScaleOnAxis();
8624
8625                 return this;
8626
8627         }
8628
8629         translate( offset ) {
8630
8631                 this.center.add( offset );
8632
8633                 return this;
8634
8635         }
8636
8637         equals( sphere ) {
8638
8639                 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
8640
8641         }
8642
8643     }
8644
8645     const _vector$2 = /*@__PURE__*/ new Vector3();
8646     const _segCenter = /*@__PURE__*/ new Vector3();
8647     const _segDir = /*@__PURE__*/ new Vector3();
8648     const _diff = /*@__PURE__*/ new Vector3();
8649
8650     const _edge1 = /*@__PURE__*/ new Vector3();
8651     const _edge2 = /*@__PURE__*/ new Vector3();
8652     const _normal = /*@__PURE__*/ new Vector3();
8653
8654     class Ray {
8655
8656         constructor( origin, direction ) {
8657
8658                 this.origin = ( origin !== undefined ) ? origin : new Vector3();
8659                 this.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );
8660
8661         }
8662
8663         set( origin, direction ) {
8664
8665                 this.origin.copy( origin );
8666                 this.direction.copy( direction );
8667
8668                 return this;
8669
8670         }
8671
8672         clone() {
8673
8674                 return new this.constructor().copy( this );
8675
8676         }
8677
8678         copy( ray ) {
8679
8680                 this.origin.copy( ray.origin );
8681                 this.direction.copy( ray.direction );
8682
8683                 return this;
8684
8685         }
8686
8687         at( t, target ) {
8688
8689                 if ( target === undefined ) {
8690
8691                         console.warn( 'THREE.Ray: .at() target is now required' );
8692                         target = new Vector3();
8693
8694                 }
8695
8696                 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
8697
8698         }
8699
8700         lookAt( v ) {
8701
8702                 this.direction.copy( v ).sub( this.origin ).normalize();
8703
8704                 return this;
8705
8706         }
8707
8708         recast( t ) {
8709
8710                 this.origin.copy( this.at( t, _vector$2 ) );
8711
8712                 return this;
8713
8714         }
8715
8716         closestPointToPoint( point, target ) {
8717
8718                 if ( target === undefined ) {
8719
8720                         console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
8721                         target = new Vector3();
8722
8723                 }
8724
8725                 target.subVectors( point, this.origin );
8726
8727                 const directionDistance = target.dot( this.direction );
8728
8729                 if ( directionDistance < 0 ) {
8730
8731                         return target.copy( this.origin );
8732
8733                 }
8734
8735                 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
8736
8737         }
8738
8739         distanceToPoint( point ) {
8740
8741                 return Math.sqrt( this.distanceSqToPoint( point ) );
8742
8743         }
8744
8745         distanceSqToPoint( point ) {
8746
8747                 const directionDistance = _vector$2.subVectors( point, this.origin ).dot( this.direction );
8748
8749                 // point behind the ray
8750
8751                 if ( directionDistance < 0 ) {
8752
8753                         return this.origin.distanceToSquared( point );
8754
8755                 }
8756
8757                 _vector$2.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
8758
8759                 return _vector$2.distanceToSquared( point );
8760
8761         }
8762
8763         distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
8764
8765                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
8766                 // It returns the min distance between the ray and the segment
8767                 // defined by v0 and v1
8768                 // It can also set two optional targets :
8769                 // - The closest point on the ray
8770                 // - The closest point on the segment
8771
8772                 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
8773                 _segDir.copy( v1 ).sub( v0 ).normalize();
8774                 _diff.copy( this.origin ).sub( _segCenter );
8775
8776                 const segExtent = v0.distanceTo( v1 ) * 0.5;
8777                 const a01 = - this.direction.dot( _segDir );
8778                 const b0 = _diff.dot( this.direction );
8779                 const b1 = - _diff.dot( _segDir );
8780                 const c = _diff.lengthSq();
8781                 const det = Math.abs( 1 - a01 * a01 );
8782                 let s0, s1, sqrDist, extDet;
8783
8784                 if ( det > 0 ) {
8785
8786                         // The ray and segment are not parallel.
8787
8788                         s0 = a01 * b1 - b0;
8789                         s1 = a01 * b0 - b1;
8790                         extDet = segExtent * det;
8791
8792                         if ( s0 >= 0 ) {
8793
8794                                 if ( s1 >= - extDet ) {
8795
8796                                         if ( s1 <= extDet ) {
8797
8798                                                 // region 0
8799                                                 // Minimum at interior points of ray and segment.
8800
8801                                                 const invDet = 1 / det;
8802                                                 s0 *= invDet;
8803                                                 s1 *= invDet;
8804                                                 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
8805
8806                                         } else {
8807
8808                                                 // region 1
8809
8810                                                 s1 = segExtent;
8811                                                 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
8812                                                 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
8813
8814                                         }
8815
8816                                 } else {
8817
8818                                         // region 5
8819
8820                                         s1 = - segExtent;
8821                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
8822                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
8823
8824                                 }
8825
8826                         } else {
8827
8828                                 if ( s1 <= - extDet ) {
8829
8830                                         // region 4
8831
8832                                         s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
8833                                         s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
8834                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
8835
8836                                 } else if ( s1 <= extDet ) {
8837
8838                                         // region 3
8839
8840                                         s0 = 0;
8841                                         s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
8842                                         sqrDist = s1 * ( s1 + 2 * b1 ) + c;
8843
8844                                 } else {
8845
8846                                         // region 2
8847
8848                                         s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
8849                                         s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
8850                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
8851
8852                                 }
8853
8854                         }
8855
8856                 } else {
8857
8858                         // Ray and segment are parallel.
8859
8860                         s1 = ( a01 > 0 ) ? - segExtent : segExtent;
8861                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
8862                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
8863
8864                 }
8865
8866                 if ( optionalPointOnRay ) {
8867
8868                         optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
8869
8870                 }
8871
8872                 if ( optionalPointOnSegment ) {
8873
8874                         optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
8875
8876                 }
8877
8878                 return sqrDist;
8879
8880         }
8881
8882         intersectSphere( sphere, target ) {
8883
8884                 _vector$2.subVectors( sphere.center, this.origin );
8885                 const tca = _vector$2.dot( this.direction );
8886                 const d2 = _vector$2.dot( _vector$2 ) - tca * tca;
8887                 const radius2 = sphere.radius * sphere.radius;
8888
8889                 if ( d2 > radius2 ) return null;
8890
8891                 const thc = Math.sqrt( radius2 - d2 );
8892
8893                 // t0 = first intersect point - entrance on front of sphere
8894                 const t0 = tca - thc;
8895
8896                 // t1 = second intersect point - exit point on back of sphere
8897                 const t1 = tca + thc;
8898
8899                 // test to see if both t0 and t1 are behind the ray - if so, return null
8900                 if ( t0 < 0 && t1 < 0 ) return null;
8901
8902                 // test to see if t0 is behind the ray:
8903                 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
8904                 // in order to always return an intersect point that is in front of the ray.
8905                 if ( t0 < 0 ) return this.at( t1, target );
8906
8907                 // else t0 is in front of the ray, so return the first collision point scaled by t0
8908                 return this.at( t0, target );
8909
8910         }
8911
8912         intersectsSphere( sphere ) {
8913
8914                 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
8915
8916         }
8917
8918         distanceToPlane( plane ) {
8919
8920                 const denominator = plane.normal.dot( this.direction );
8921
8922                 if ( denominator === 0 ) {
8923
8924                         // line is coplanar, return origin
8925                         if ( plane.distanceToPoint( this.origin ) === 0 ) {
8926
8927                                 return 0;
8928
8929                         }
8930
8931                         // Null is preferable to undefined since undefined means.... it is undefined
8932
8933                         return null;
8934
8935                 }
8936
8937                 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
8938
8939                 // Return if the ray never intersects the plane
8940
8941                 return t >= 0 ? t : null;
8942
8943         }
8944
8945         intersectPlane( plane, target ) {
8946
8947                 const t = this.distanceToPlane( plane );
8948
8949                 if ( t === null ) {
8950
8951                         return null;
8952
8953                 }
8954
8955                 return this.at( t, target );
8956
8957         }
8958
8959         intersectsPlane( plane ) {
8960
8961                 // check if the ray lies on the plane first
8962
8963                 const distToPoint = plane.distanceToPoint( this.origin );
8964
8965                 if ( distToPoint === 0 ) {
8966
8967                         return true;
8968
8969                 }
8970
8971                 const denominator = plane.normal.dot( this.direction );
8972
8973                 if ( denominator * distToPoint < 0 ) {
8974
8975                         return true;
8976
8977                 }
8978
8979                 // ray origin is behind the plane (and is pointing behind it)
8980
8981                 return false;
8982
8983         }
8984
8985         intersectBox( box, target ) {
8986
8987                 let tmin, tmax, tymin, tymax, tzmin, tzmax;
8988
8989                 const invdirx = 1 / this.direction.x,
8990                         invdiry = 1 / this.direction.y,
8991                         invdirz = 1 / this.direction.z;
8992
8993                 const origin = this.origin;
8994
8995                 if ( invdirx >= 0 ) {
8996
8997                         tmin = ( box.min.x - origin.x ) * invdirx;
8998                         tmax = ( box.max.x - origin.x ) * invdirx;
8999
9000                 } else {
9001
9002                         tmin = ( box.max.x - origin.x ) * invdirx;
9003                         tmax = ( box.min.x - origin.x ) * invdirx;
9004
9005                 }
9006
9007                 if ( invdiry >= 0 ) {
9008
9009                         tymin = ( box.min.y - origin.y ) * invdiry;
9010                         tymax = ( box.max.y - origin.y ) * invdiry;
9011
9012                 } else {
9013
9014                         tymin = ( box.max.y - origin.y ) * invdiry;
9015                         tymax = ( box.min.y - origin.y ) * invdiry;
9016
9017                 }
9018
9019                 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
9020
9021                 // These lines also handle the case where tmin or tmax is NaN
9022                 // (result of 0 * Infinity). x !== x returns true if x is NaN
9023
9024                 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
9025
9026                 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
9027
9028                 if ( invdirz >= 0 ) {
9029
9030                         tzmin = ( box.min.z - origin.z ) * invdirz;
9031                         tzmax = ( box.max.z - origin.z ) * invdirz;
9032
9033                 } else {
9034
9035                         tzmin = ( box.max.z - origin.z ) * invdirz;
9036                         tzmax = ( box.min.z - origin.z ) * invdirz;
9037
9038                 }
9039
9040                 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
9041
9042                 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
9043
9044                 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
9045
9046                 //return point closest to the ray (positive side)
9047
9048                 if ( tmax < 0 ) return null;
9049
9050                 return this.at( tmin >= 0 ? tmin : tmax, target );
9051
9052         }
9053
9054         intersectsBox( box ) {
9055
9056                 return this.intersectBox( box, _vector$2 ) !== null;
9057
9058         }
9059
9060         intersectTriangle( a, b, c, backfaceCulling, target ) {
9061
9062                 // Compute the offset origin, edges, and normal.
9063
9064                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
9065
9066                 _edge1.subVectors( b, a );
9067                 _edge2.subVectors( c, a );
9068                 _normal.crossVectors( _edge1, _edge2 );
9069
9070                 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
9071                 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
9072                 //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
9073                 //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
9074                 //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
9075                 let DdN = this.direction.dot( _normal );
9076                 let sign;
9077
9078                 if ( DdN > 0 ) {
9079
9080                         if ( backfaceCulling ) return null;
9081                         sign = 1;
9082
9083                 } else if ( DdN < 0 ) {
9084
9085                         sign = - 1;
9086                         DdN = - DdN;
9087
9088                 } else {
9089
9090                         return null;
9091
9092                 }
9093
9094                 _diff.subVectors( this.origin, a );
9095                 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
9096
9097                 // b1 < 0, no intersection
9098                 if ( DdQxE2 < 0 ) {
9099
9100                         return null;
9101
9102                 }
9103
9104                 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
9105
9106                 // b2 < 0, no intersection
9107                 if ( DdE1xQ < 0 ) {
9108
9109                         return null;
9110
9111                 }
9112
9113                 // b1+b2 > 1, no intersection
9114                 if ( DdQxE2 + DdE1xQ > DdN ) {
9115
9116                         return null;
9117
9118                 }
9119
9120                 // Line intersects triangle, check if ray does.
9121                 const QdN = - sign * _diff.dot( _normal );
9122
9123                 // t < 0, no intersection
9124                 if ( QdN < 0 ) {
9125
9126                         return null;
9127
9128                 }
9129
9130                 // Ray intersects triangle.
9131                 return this.at( QdN / DdN, target );
9132
9133         }
9134
9135         applyMatrix4( matrix4 ) {
9136
9137                 this.origin.applyMatrix4( matrix4 );
9138                 this.direction.transformDirection( matrix4 );
9139
9140                 return this;
9141
9142         }
9143
9144         equals( ray ) {
9145
9146                 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
9147
9148         }
9149
9150     }
9151
9152     class Matrix4 {
9153
9154         constructor() {
9155
9156                 Object.defineProperty( this, 'isMatrix4', { value: true } );
9157
9158                 this.elements = [
9159
9160                         1, 0, 0, 0,
9161                         0, 1, 0, 0,
9162                         0, 0, 1, 0,
9163                         0, 0, 0, 1
9164
9165                 ];
9166
9167                 if ( arguments.length > 0 ) {
9168
9169                         console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
9170
9171                 }
9172
9173         }
9174
9175         set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
9176
9177                 const te = this.elements;
9178
9179                 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
9180                 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
9181                 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
9182                 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
9183
9184                 return this;
9185
9186         }
9187
9188         identity() {
9189
9190                 this.set(
9191
9192                         1, 0, 0, 0,
9193                         0, 1, 0, 0,
9194                         0, 0, 1, 0,
9195                         0, 0, 0, 1
9196
9197                 );
9198
9199                 return this;
9200
9201         }
9202
9203         clone() {
9204
9205                 return new Matrix4().fromArray( this.elements );
9206
9207         }
9208
9209         copy( m ) {
9210
9211                 const te = this.elements;
9212                 const me = m.elements;
9213
9214                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
9215                 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
9216                 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
9217                 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
9218
9219                 return this;
9220
9221         }
9222
9223         copyPosition( m ) {
9224
9225                 const te = this.elements, me = m.elements;
9226
9227                 te[ 12 ] = me[ 12 ];
9228                 te[ 13 ] = me[ 13 ];
9229                 te[ 14 ] = me[ 14 ];
9230
9231                 return this;
9232
9233         }
9234
9235         setFromMatrix3( m ) {
9236
9237                 const me = m.elements;
9238
9239                 this.set(
9240
9241                         me[ 0 ], me[ 3 ], me[ 6 ], 0,
9242                         me[ 1 ], me[ 4 ], me[ 7 ], 0,
9243                         me[ 2 ], me[ 5 ], me[ 8 ], 0,
9244                         0, 0, 0, 1
9245
9246                 );
9247
9248                 return this;
9249
9250         }
9251
9252         extractBasis( xAxis, yAxis, zAxis ) {
9253
9254                 xAxis.setFromMatrixColumn( this, 0 );
9255                 yAxis.setFromMatrixColumn( this, 1 );
9256                 zAxis.setFromMatrixColumn( this, 2 );
9257
9258                 return this;
9259
9260         }
9261
9262         makeBasis( xAxis, yAxis, zAxis ) {
9263
9264                 this.set(
9265                         xAxis.x, yAxis.x, zAxis.x, 0,
9266                         xAxis.y, yAxis.y, zAxis.y, 0,
9267                         xAxis.z, yAxis.z, zAxis.z, 0,
9268                         0, 0, 0, 1
9269                 );
9270
9271                 return this;
9272
9273         }
9274
9275         extractRotation( m ) {
9276
9277                 // this method does not support reflection matrices
9278
9279                 const te = this.elements;
9280                 const me = m.elements;
9281
9282                 const scaleX = 1 / _v1$1.setFromMatrixColumn( m, 0 ).length();
9283                 const scaleY = 1 / _v1$1.setFromMatrixColumn( m, 1 ).length();
9284                 const scaleZ = 1 / _v1$1.setFromMatrixColumn( m, 2 ).length();
9285
9286                 te[ 0 ] = me[ 0 ] * scaleX;
9287                 te[ 1 ] = me[ 1 ] * scaleX;
9288                 te[ 2 ] = me[ 2 ] * scaleX;
9289                 te[ 3 ] = 0;
9290
9291                 te[ 4 ] = me[ 4 ] * scaleY;
9292                 te[ 5 ] = me[ 5 ] * scaleY;
9293                 te[ 6 ] = me[ 6 ] * scaleY;
9294                 te[ 7 ] = 0;
9295
9296                 te[ 8 ] = me[ 8 ] * scaleZ;
9297                 te[ 9 ] = me[ 9 ] * scaleZ;
9298                 te[ 10 ] = me[ 10 ] * scaleZ;
9299                 te[ 11 ] = 0;
9300
9301                 te[ 12 ] = 0;
9302                 te[ 13 ] = 0;
9303                 te[ 14 ] = 0;
9304                 te[ 15 ] = 1;
9305
9306                 return this;
9307
9308         }
9309
9310         makeRotationFromEuler( euler ) {
9311
9312                 if ( ! ( euler && euler.isEuler ) ) {
9313
9314                         console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
9315
9316                 }
9317
9318                 const te = this.elements;
9319
9320                 const x = euler.x, y = euler.y, z = euler.z;
9321                 const a = Math.cos( x ), b = Math.sin( x );
9322                 const c = Math.cos( y ), d = Math.sin( y );
9323                 const e = Math.cos( z ), f = Math.sin( z );
9324
9325                 if ( euler.order === 'XYZ' ) {
9326
9327                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
9328
9329                         te[ 0 ] = c * e;
9330                         te[ 4 ] = - c * f;
9331                         te[ 8 ] = d;
9332
9333                         te[ 1 ] = af + be * d;
9334                         te[ 5 ] = ae - bf * d;
9335                         te[ 9 ] = - b * c;
9336
9337                         te[ 2 ] = bf - ae * d;
9338                         te[ 6 ] = be + af * d;
9339                         te[ 10 ] = a * c;
9340
9341                 } else if ( euler.order === 'YXZ' ) {
9342
9343                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
9344
9345                         te[ 0 ] = ce + df * b;
9346                         te[ 4 ] = de * b - cf;
9347                         te[ 8 ] = a * d;
9348
9349                         te[ 1 ] = a * f;
9350                         te[ 5 ] = a * e;
9351                         te[ 9 ] = - b;
9352
9353                         te[ 2 ] = cf * b - de;
9354                         te[ 6 ] = df + ce * b;
9355                         te[ 10 ] = a * c;
9356
9357                 } else if ( euler.order === 'ZXY' ) {
9358
9359                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
9360
9361                         te[ 0 ] = ce - df * b;
9362                         te[ 4 ] = - a * f;
9363                         te[ 8 ] = de + cf * b;
9364
9365                         te[ 1 ] = cf + de * b;
9366                         te[ 5 ] = a * e;
9367                         te[ 9 ] = df - ce * b;
9368
9369                         te[ 2 ] = - a * d;
9370                         te[ 6 ] = b;
9371                         te[ 10 ] = a * c;
9372
9373                 } else if ( euler.order === 'ZYX' ) {
9374
9375                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
9376
9377                         te[ 0 ] = c * e;
9378                         te[ 4 ] = be * d - af;
9379                         te[ 8 ] = ae * d + bf;
9380
9381                         te[ 1 ] = c * f;
9382                         te[ 5 ] = bf * d + ae;
9383                         te[ 9 ] = af * d - be;
9384
9385                         te[ 2 ] = - d;
9386                         te[ 6 ] = b * c;
9387                         te[ 10 ] = a * c;
9388
9389                 } else if ( euler.order === 'YZX' ) {
9390
9391                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
9392
9393                         te[ 0 ] = c * e;
9394                         te[ 4 ] = bd - ac * f;
9395                         te[ 8 ] = bc * f + ad;
9396
9397                         te[ 1 ] = f;
9398                         te[ 5 ] = a * e;
9399                         te[ 9 ] = - b * e;
9400
9401                         te[ 2 ] = - d * e;
9402                         te[ 6 ] = ad * f + bc;
9403                         te[ 10 ] = ac - bd * f;
9404
9405                 } else if ( euler.order === 'XZY' ) {
9406
9407                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
9408
9409                         te[ 0 ] = c * e;
9410                         te[ 4 ] = - f;
9411                         te[ 8 ] = d * e;
9412
9413                         te[ 1 ] = ac * f + bd;
9414                         te[ 5 ] = a * e;
9415                         te[ 9 ] = ad * f - bc;
9416
9417                         te[ 2 ] = bc * f - ad;
9418                         te[ 6 ] = b * e;
9419                         te[ 10 ] = bd * f + ac;
9420
9421                 }
9422
9423                 // bottom row
9424                 te[ 3 ] = 0;
9425                 te[ 7 ] = 0;
9426                 te[ 11 ] = 0;
9427
9428                 // last column
9429                 te[ 12 ] = 0;
9430                 te[ 13 ] = 0;
9431                 te[ 14 ] = 0;
9432                 te[ 15 ] = 1;
9433
9434                 return this;
9435
9436         }
9437
9438         makeRotationFromQuaternion( q ) {
9439
9440                 return this.compose( _zero, q, _one );
9441
9442         }
9443
9444         lookAt( eye, target, up ) {
9445
9446                 const te = this.elements;
9447
9448                 _z.subVectors( eye, target );
9449
9450                 if ( _z.lengthSq() === 0 ) {
9451
9452                         // eye and target are in the same position
9453
9454                         _z.z = 1;
9455
9456                 }
9457
9458                 _z.normalize();
9459                 _x.crossVectors( up, _z );
9460
9461                 if ( _x.lengthSq() === 0 ) {
9462
9463                         // up and z are parallel
9464
9465                         if ( Math.abs( up.z ) === 1 ) {
9466
9467                                 _z.x += 0.0001;
9468
9469                         } else {
9470
9471                                 _z.z += 0.0001;
9472
9473                         }
9474
9475                         _z.normalize();
9476                         _x.crossVectors( up, _z );
9477
9478                 }
9479
9480                 _x.normalize();
9481                 _y.crossVectors( _z, _x );
9482
9483                 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
9484                 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
9485                 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
9486
9487                 return this;
9488
9489         }
9490
9491         multiply( m, n ) {
9492
9493                 if ( n !== undefined ) {
9494
9495                         console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
9496                         return this.multiplyMatrices( m, n );
9497
9498                 }
9499
9500                 return this.multiplyMatrices( this, m );
9501
9502         }
9503
9504         premultiply( m ) {
9505
9506                 return this.multiplyMatrices( m, this );
9507
9508         }
9509
9510         multiplyMatrices( a, b ) {
9511
9512                 const ae = a.elements;
9513                 const be = b.elements;
9514                 const te = this.elements;
9515
9516                 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
9517                 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
9518                 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
9519                 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
9520
9521                 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
9522                 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
9523                 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
9524                 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
9525
9526                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
9527                 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
9528                 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
9529                 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
9530
9531                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
9532                 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
9533                 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
9534                 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
9535
9536                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
9537                 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
9538                 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
9539                 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
9540
9541                 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
9542                 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
9543                 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
9544                 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
9545
9546                 return this;
9547
9548         }
9549
9550         multiplyScalar( s ) {
9551
9552                 const te = this.elements;
9553
9554                 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
9555                 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
9556                 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
9557                 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
9558
9559                 return this;
9560
9561         }
9562
9563         determinant() {
9564
9565                 const te = this.elements;
9566
9567                 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
9568                 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
9569                 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
9570                 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
9571
9572                 //TODO: make this more efficient
9573                 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
9574
9575                 return (
9576                         n41 * (
9577                                 + n14 * n23 * n32
9578                                  - n13 * n24 * n32
9579                                  - n14 * n22 * n33
9580                                  + n12 * n24 * n33
9581                                  + n13 * n22 * n34
9582                                  - n12 * n23 * n34
9583                         ) +
9584                         n42 * (
9585                                 + n11 * n23 * n34
9586                                  - n11 * n24 * n33
9587                                  + n14 * n21 * n33
9588                                  - n13 * n21 * n34
9589                                  + n13 * n24 * n31
9590                                  - n14 * n23 * n31
9591                         ) +
9592                         n43 * (
9593                                 + n11 * n24 * n32
9594                                  - n11 * n22 * n34
9595                                  - n14 * n21 * n32
9596                                  + n12 * n21 * n34
9597                                  + n14 * n22 * n31
9598                                  - n12 * n24 * n31
9599                         ) +
9600                         n44 * (
9601                                 - n13 * n22 * n31
9602                                  - n11 * n23 * n32
9603                                  + n11 * n22 * n33
9604                                  + n13 * n21 * n32
9605                                  - n12 * n21 * n33
9606                                  + n12 * n23 * n31
9607                         )
9608
9609                 );
9610
9611         }
9612
9613         transpose() {
9614
9615                 const te = this.elements;
9616                 let tmp;
9617
9618                 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
9619                 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
9620                 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
9621
9622                 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
9623                 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
9624                 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
9625
9626                 return this;
9627
9628         }
9629
9630         setPosition( x, y, z ) {
9631
9632                 const te = this.elements;
9633
9634                 if ( x.isVector3 ) {
9635
9636                         te[ 12 ] = x.x;
9637                         te[ 13 ] = x.y;
9638                         te[ 14 ] = x.z;
9639
9640                 } else {
9641
9642                         te[ 12 ] = x;
9643                         te[ 13 ] = y;
9644                         te[ 14 ] = z;
9645
9646                 }
9647
9648                 return this;
9649
9650         }
9651
9652         invert() {
9653
9654                 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
9655                 const te = this.elements,
9656
9657                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
9658                         n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
9659                         n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
9660                         n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
9661
9662                         t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
9663                         t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
9664                         t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
9665                         t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
9666
9667                 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
9668
9669                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
9670
9671                 const detInv = 1 / det;
9672
9673                 te[ 0 ] = t11 * detInv;
9674                 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
9675                 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
9676                 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
9677
9678                 te[ 4 ] = t12 * detInv;
9679                 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
9680                 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
9681                 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
9682
9683                 te[ 8 ] = t13 * detInv;
9684                 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
9685                 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
9686                 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
9687
9688                 te[ 12 ] = t14 * detInv;
9689                 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
9690                 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
9691                 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
9692
9693                 return this;
9694
9695         }
9696
9697         scale( v ) {
9698
9699                 const te = this.elements;
9700                 const x = v.x, y = v.y, z = v.z;
9701
9702                 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
9703                 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
9704                 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
9705                 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
9706
9707                 return this;
9708
9709         }
9710
9711         getMaxScaleOnAxis() {
9712
9713                 const te = this.elements;
9714
9715                 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
9716                 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
9717                 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
9718
9719                 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
9720
9721         }
9722
9723         makeTranslation( x, y, z ) {
9724
9725                 this.set(
9726
9727                         1, 0, 0, x,
9728                         0, 1, 0, y,
9729                         0, 0, 1, z,
9730                         0, 0, 0, 1
9731
9732                 );
9733
9734                 return this;
9735
9736         }
9737
9738         makeRotationX( theta ) {
9739
9740                 const c = Math.cos( theta ), s = Math.sin( theta );
9741
9742                 this.set(
9743
9744                         1, 0, 0, 0,
9745                         0, c, - s, 0,
9746                         0, s, c, 0,
9747                         0, 0, 0, 1
9748
9749                 );
9750
9751                 return this;
9752
9753         }
9754
9755         makeRotationY( theta ) {
9756
9757                 const c = Math.cos( theta ), s = Math.sin( theta );
9758
9759                 this.set(
9760
9761                          c, 0, s, 0,
9762                          0, 1, 0, 0,
9763                         - s, 0, c, 0,
9764                          0, 0, 0, 1
9765
9766                 );
9767
9768                 return this;
9769
9770         }
9771
9772         makeRotationZ( theta ) {
9773
9774                 const c = Math.cos( theta ), s = Math.sin( theta );
9775
9776                 this.set(
9777
9778                         c, - s, 0, 0,
9779                         s, c, 0, 0,
9780                         0, 0, 1, 0,
9781                         0, 0, 0, 1
9782
9783                 );
9784
9785                 return this;
9786
9787         }
9788
9789         makeRotationAxis( axis, angle ) {
9790
9791                 // Based on http://www.gamedev.net/reference/articles/article1199.asp
9792
9793                 const c = Math.cos( angle );
9794                 const s = Math.sin( angle );
9795                 const t = 1 - c;
9796                 const x = axis.x, y = axis.y, z = axis.z;
9797                 const tx = t * x, ty = t * y;
9798
9799                 this.set(
9800
9801                         tx * x + c, tx * y - s * z, tx * z + s * y, 0,
9802                         tx * y + s * z, ty * y + c, ty * z - s * x, 0,
9803                         tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
9804                         0, 0, 0, 1
9805
9806                 );
9807
9808                 return this;
9809
9810         }
9811
9812         makeScale( x, y, z ) {
9813
9814                 this.set(
9815
9816                         x, 0, 0, 0,
9817                         0, y, 0, 0,
9818                         0, 0, z, 0,
9819                         0, 0, 0, 1
9820
9821                 );
9822
9823                 return this;
9824
9825         }
9826
9827         makeShear( x, y, z ) {
9828
9829                 this.set(
9830
9831                         1, y, z, 0,
9832                         x, 1, z, 0,
9833                         x, y, 1, 0,
9834                         0, 0, 0, 1
9835
9836                 );
9837
9838                 return this;
9839
9840         }
9841
9842         compose( position, quaternion, scale ) {
9843
9844                 const te = this.elements;
9845
9846                 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
9847                 const x2 = x + x,       y2 = y + y, z2 = z + z;
9848                 const xx = x * x2, xy = x * y2, xz = x * z2;
9849                 const yy = y * y2, yz = y * z2, zz = z * z2;
9850                 const wx = w * x2, wy = w * y2, wz = w * z2;
9851
9852                 const sx = scale.x, sy = scale.y, sz = scale.z;
9853
9854                 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
9855                 te[ 1 ] = ( xy + wz ) * sx;
9856                 te[ 2 ] = ( xz - wy ) * sx;
9857                 te[ 3 ] = 0;
9858
9859                 te[ 4 ] = ( xy - wz ) * sy;
9860                 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
9861                 te[ 6 ] = ( yz + wx ) * sy;
9862                 te[ 7 ] = 0;
9863
9864                 te[ 8 ] = ( xz + wy ) * sz;
9865                 te[ 9 ] = ( yz - wx ) * sz;
9866                 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
9867                 te[ 11 ] = 0;
9868
9869                 te[ 12 ] = position.x;
9870                 te[ 13 ] = position.y;
9871                 te[ 14 ] = position.z;
9872                 te[ 15 ] = 1;
9873
9874                 return this;
9875
9876         }
9877
9878         decompose( position, quaternion, scale ) {
9879
9880                 const te = this.elements;
9881
9882                 let sx = _v1$1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
9883                 const sy = _v1$1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
9884                 const sz = _v1$1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
9885
9886                 // if determine is negative, we need to invert one scale
9887                 const det = this.determinant();
9888                 if ( det < 0 ) sx = - sx;
9889
9890                 position.x = te[ 12 ];
9891                 position.y = te[ 13 ];
9892                 position.z = te[ 14 ];
9893
9894                 // scale the rotation part
9895                 _m1.copy( this );
9896
9897                 const invSX = 1 / sx;
9898                 const invSY = 1 / sy;
9899                 const invSZ = 1 / sz;
9900
9901                 _m1.elements[ 0 ] *= invSX;
9902                 _m1.elements[ 1 ] *= invSX;
9903                 _m1.elements[ 2 ] *= invSX;
9904
9905                 _m1.elements[ 4 ] *= invSY;
9906                 _m1.elements[ 5 ] *= invSY;
9907                 _m1.elements[ 6 ] *= invSY;
9908
9909                 _m1.elements[ 8 ] *= invSZ;
9910                 _m1.elements[ 9 ] *= invSZ;
9911                 _m1.elements[ 10 ] *= invSZ;
9912
9913                 quaternion.setFromRotationMatrix( _m1 );
9914
9915                 scale.x = sx;
9916                 scale.y = sy;
9917                 scale.z = sz;
9918
9919                 return this;
9920
9921         }
9922
9923         makePerspective( left, right, top, bottom, near, far ) {
9924
9925                 if ( far === undefined ) {
9926
9927                         console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
9928
9929                 }
9930
9931                 const te = this.elements;
9932                 const x = 2 * near / ( right - left );
9933                 const y = 2 * near / ( top - bottom );
9934
9935                 const a = ( right + left ) / ( right - left );
9936                 const b = ( top + bottom ) / ( top - bottom );
9937                 const c = - ( far + near ) / ( far - near );
9938                 const d = - 2 * far * near / ( far - near );
9939
9940                 te[ 0 ] = x;    te[ 4 ] = 0;    te[ 8 ] = a;    te[ 12 ] = 0;
9941                 te[ 1 ] = 0;    te[ 5 ] = y;    te[ 9 ] = b;    te[ 13 ] = 0;
9942                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = c;   te[ 14 ] = d;
9943                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = - 1; te[ 15 ] = 0;
9944
9945                 return this;
9946
9947         }
9948
9949         makeOrthographic( left, right, top, bottom, near, far ) {
9950
9951                 const te = this.elements;
9952                 const w = 1.0 / ( right - left );
9953                 const h = 1.0 / ( top - bottom );
9954                 const p = 1.0 / ( far - near );
9955
9956                 const x = ( right + left ) * w;
9957                 const y = ( top + bottom ) * h;
9958                 const z = ( far + near ) * p;
9959
9960                 te[ 0 ] = 2 * w;        te[ 4 ] = 0;    te[ 8 ] = 0;    te[ 12 ] = - x;
9961                 te[ 1 ] = 0;    te[ 5 ] = 2 * h;        te[ 9 ] = 0;    te[ 13 ] = - y;
9962                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = - 2 * p;     te[ 14 ] = - z;
9963                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = 0;   te[ 15 ] = 1;
9964
9965                 return this;
9966
9967         }
9968
9969         equals( matrix ) {
9970
9971                 const te = this.elements;
9972                 const me = matrix.elements;
9973
9974                 for ( let i = 0; i < 16; i ++ ) {
9975
9976                         if ( te[ i ] !== me[ i ] ) return false;
9977
9978                 }
9979
9980                 return true;
9981
9982         }
9983
9984         fromArray( array, offset = 0 ) {
9985
9986                 for ( let i = 0; i < 16; i ++ ) {
9987
9988                         this.elements[ i ] = array[ i + offset ];
9989
9990                 }
9991
9992                 return this;
9993
9994         }
9995
9996         toArray( array = [], offset = 0 ) {
9997
9998                 const te = this.elements;
9999
10000                 array[ offset ] = te[ 0 ];
10001                 array[ offset + 1 ] = te[ 1 ];
10002                 array[ offset + 2 ] = te[ 2 ];
10003                 array[ offset + 3 ] = te[ 3 ];
10004
10005                 array[ offset + 4 ] = te[ 4 ];
10006                 array[ offset + 5 ] = te[ 5 ];
10007                 array[ offset + 6 ] = te[ 6 ];
10008                 array[ offset + 7 ] = te[ 7 ];
10009
10010                 array[ offset + 8 ] = te[ 8 ];
10011                 array[ offset + 9 ] = te[ 9 ];
10012                 array[ offset + 10 ] = te[ 10 ];
10013                 array[ offset + 11 ] = te[ 11 ];
10014
10015                 array[ offset + 12 ] = te[ 12 ];
10016                 array[ offset + 13 ] = te[ 13 ];
10017                 array[ offset + 14 ] = te[ 14 ];
10018                 array[ offset + 15 ] = te[ 15 ];
10019
10020                 return array;
10021
10022         }
10023
10024     }
10025
10026     const _v1$1 = /*@__PURE__*/ new Vector3();
10027     const _m1 = /*@__PURE__*/ new Matrix4();
10028     const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
10029     const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
10030     const _x = /*@__PURE__*/ new Vector3();
10031     const _y = /*@__PURE__*/ new Vector3();
10032     const _z = /*@__PURE__*/ new Vector3();
10033
10034     class Euler {
10035
10036         constructor( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
10037
10038                 Object.defineProperty( this, 'isEuler', { value: true } );
10039
10040                 this._x = x;
10041                 this._y = y;
10042                 this._z = z;
10043                 this._order = order;
10044
10045         }
10046
10047         get x() {
10048
10049                 return this._x;
10050
10051         }
10052
10053         set x( value ) {
10054
10055                 this._x = value;
10056                 this._onChangeCallback();
10057
10058         }
10059
10060         get y() {
10061
10062                 return this._y;
10063
10064         }
10065
10066         set y( value ) {
10067
10068                 this._y = value;
10069                 this._onChangeCallback();
10070
10071         }
10072
10073         get z() {
10074
10075                 return this._z;
10076
10077         }
10078
10079         set z( value ) {
10080
10081                 this._z = value;
10082                 this._onChangeCallback();
10083
10084         }
10085
10086         get order() {
10087
10088                 return this._order;
10089
10090         }
10091
10092         set order( value ) {
10093
10094                 this._order = value;
10095                 this._onChangeCallback();
10096
10097         }
10098
10099         set( x, y, z, order ) {
10100
10101                 this._x = x;
10102                 this._y = y;
10103                 this._z = z;
10104                 this._order = order || this._order;
10105
10106                 this._onChangeCallback();
10107
10108                 return this;
10109
10110         }
10111
10112         clone() {
10113
10114                 return new this.constructor( this._x, this._y, this._z, this._order );
10115
10116         }
10117
10118         copy( euler ) {
10119
10120                 this._x = euler._x;
10121                 this._y = euler._y;
10122                 this._z = euler._z;
10123                 this._order = euler._order;
10124
10125                 this._onChangeCallback();
10126
10127                 return this;
10128
10129         }
10130
10131         setFromRotationMatrix( m, order, update ) {
10132
10133                 const clamp = MathUtils.clamp;
10134
10135                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
10136
10137                 const te = m.elements;
10138                 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
10139                 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
10140                 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
10141
10142                 order = order || this._order;
10143
10144                 switch ( order ) {
10145
10146                         case 'XYZ':
10147
10148                                 this._y = Math.asin( clamp( m13, - 1, 1 ) );
10149
10150                                 if ( Math.abs( m13 ) < 0.9999999 ) {
10151
10152                                         this._x = Math.atan2( - m23, m33 );
10153                                         this._z = Math.atan2( - m12, m11 );
10154
10155                                 } else {
10156
10157                                         this._x = Math.atan2( m32, m22 );
10158                                         this._z = 0;
10159
10160                                 }
10161
10162                                 break;
10163
10164                         case 'YXZ':
10165
10166                                 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
10167
10168                                 if ( Math.abs( m23 ) < 0.9999999 ) {
10169
10170                                         this._y = Math.atan2( m13, m33 );
10171                                         this._z = Math.atan2( m21, m22 );
10172
10173                                 } else {
10174
10175                                         this._y = Math.atan2( - m31, m11 );
10176                                         this._z = 0;
10177
10178                                 }
10179
10180                                 break;
10181
10182                         case 'ZXY':
10183
10184                                 this._x = Math.asin( clamp( m32, - 1, 1 ) );
10185
10186                                 if ( Math.abs( m32 ) < 0.9999999 ) {
10187
10188                                         this._y = Math.atan2( - m31, m33 );
10189                                         this._z = Math.atan2( - m12, m22 );
10190
10191                                 } else {
10192
10193                                         this._y = 0;
10194                                         this._z = Math.atan2( m21, m11 );
10195
10196                                 }
10197
10198                                 break;
10199
10200                         case 'ZYX':
10201
10202                                 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
10203
10204                                 if ( Math.abs( m31 ) < 0.9999999 ) {
10205
10206                                         this._x = Math.atan2( m32, m33 );
10207                                         this._z = Math.atan2( m21, m11 );
10208
10209                                 } else {
10210
10211                                         this._x = 0;
10212                                         this._z = Math.atan2( - m12, m22 );
10213
10214                                 }
10215
10216                                 break;
10217
10218                         case 'YZX':
10219
10220                                 this._z = Math.asin( clamp( m21, - 1, 1 ) );
10221
10222                                 if ( Math.abs( m21 ) < 0.9999999 ) {
10223
10224                                         this._x = Math.atan2( - m23, m22 );
10225                                         this._y = Math.atan2( - m31, m11 );
10226
10227                                 } else {
10228
10229                                         this._x = 0;
10230                                         this._y = Math.atan2( m13, m33 );
10231
10232                                 }
10233
10234                                 break;
10235
10236                         case 'XZY':
10237
10238                                 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
10239
10240                                 if ( Math.abs( m12 ) < 0.9999999 ) {
10241
10242                                         this._x = Math.atan2( m32, m22 );
10243                                         this._y = Math.atan2( m13, m11 );
10244
10245                                 } else {
10246
10247                                         this._x = Math.atan2( - m23, m33 );
10248                                         this._y = 0;
10249
10250                                 }
10251
10252                                 break;
10253
10254                         default:
10255
10256                                 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
10257
10258                 }
10259
10260                 this._order = order;
10261
10262                 if ( update !== false ) this._onChangeCallback();
10263
10264                 return this;
10265
10266         }
10267
10268         setFromQuaternion( q, order, update ) {
10269
10270                 _matrix.makeRotationFromQuaternion( q );
10271
10272                 return this.setFromRotationMatrix( _matrix, order, update );
10273
10274         }
10275
10276         setFromVector3( v, order ) {
10277
10278                 return this.set( v.x, v.y, v.z, order || this._order );
10279
10280         }
10281
10282         reorder( newOrder ) {
10283
10284                 // WARNING: this discards revolution information -bhouston
10285
10286                 _quaternion$1.setFromEuler( this );
10287
10288                 return this.setFromQuaternion( _quaternion$1, newOrder );
10289
10290         }
10291
10292         equals( euler ) {
10293
10294                 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
10295
10296         }
10297
10298         fromArray( array ) {
10299
10300                 this._x = array[ 0 ];
10301                 this._y = array[ 1 ];
10302                 this._z = array[ 2 ];
10303                 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
10304
10305                 this._onChangeCallback();
10306
10307                 return this;
10308
10309         }
10310
10311         toArray( array = [], offset = 0 ) {
10312
10313                 array[ offset ] = this._x;
10314                 array[ offset + 1 ] = this._y;
10315                 array[ offset + 2 ] = this._z;
10316                 array[ offset + 3 ] = this._order;
10317
10318                 return array;
10319
10320         }
10321
10322         toVector3( optionalResult ) {
10323
10324                 if ( optionalResult ) {
10325
10326                         return optionalResult.set( this._x, this._y, this._z );
10327
10328                 } else {
10329
10330                         return new Vector3( this._x, this._y, this._z );
10331
10332                 }
10333
10334         }
10335
10336         _onChange( callback ) {
10337
10338                 this._onChangeCallback = callback;
10339
10340                 return this;
10341
10342         }
10343
10344         _onChangeCallback() {}
10345
10346     }
10347
10348     Euler.DefaultOrder = 'XYZ';
10349     Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
10350
10351     const _matrix = /*@__PURE__*/ new Matrix4();
10352     const _quaternion$1 = /*@__PURE__*/ new Quaternion();
10353
10354     class Layers {
10355
10356         constructor() {
10357
10358                 this.mask = 1 | 0;
10359
10360         }
10361
10362         set( channel ) {
10363
10364                 this.mask = 1 << channel | 0;
10365
10366         }
10367
10368         enable( channel ) {
10369
10370                 this.mask |= 1 << channel | 0;
10371
10372         }
10373
10374         enableAll() {
10375
10376                 this.mask = 0xffffffff | 0;
10377
10378         }
10379
10380         toggle( channel ) {
10381
10382                 this.mask ^= 1 << channel | 0;
10383
10384         }
10385
10386         disable( channel ) {
10387
10388                 this.mask &= ~ ( 1 << channel | 0 );
10389
10390         }
10391
10392         disableAll() {
10393
10394                 this.mask = 0;
10395
10396         }
10397
10398         test( layers ) {
10399
10400                 return ( this.mask & layers.mask ) !== 0;
10401
10402         }
10403
10404     }
10405
10406     let _object3DId = 0;
10407
10408     const _v1$2 = new Vector3();
10409     const _q1 = new Quaternion();
10410     const _m1$1 = new Matrix4();
10411     const _target = new Vector3();
10412
10413     const _position = new Vector3();
10414     const _scale = new Vector3();
10415     const _quaternion$2 = new Quaternion();
10416
10417     const _xAxis = new Vector3( 1, 0, 0 );
10418     const _yAxis = new Vector3( 0, 1, 0 );
10419     const _zAxis = new Vector3( 0, 0, 1 );
10420
10421     const _addedEvent = { type: 'added' };
10422     const _removedEvent = { type: 'removed' };
10423
10424     function Object3D() {
10425
10426         Object.defineProperty( this, 'id', { value: _object3DId ++ } );
10427
10428         this.uuid = MathUtils.generateUUID();
10429
10430         this.name = '';
10431         this.type = 'Object3D';
10432
10433         this.parent = null;
10434         this.children = [];
10435
10436         this.up = Object3D.DefaultUp.clone();
10437
10438         const position = new Vector3();
10439         const rotation = new Euler();
10440         const quaternion = new Quaternion();
10441         const scale = new Vector3( 1, 1, 1 );
10442
10443         function onRotationChange() {
10444
10445                 quaternion.setFromEuler( rotation, false );
10446
10447         }
10448
10449         function onQuaternionChange() {
10450
10451                 rotation.setFromQuaternion( quaternion, undefined, false );
10452
10453         }
10454
10455         rotation._onChange( onRotationChange );
10456         quaternion._onChange( onQuaternionChange );
10457
10458         Object.defineProperties( this, {
10459                 position: {
10460                         configurable: true,
10461                         enumerable: true,
10462                         value: position
10463                 },
10464                 rotation: {
10465                         configurable: true,
10466                         enumerable: true,
10467                         value: rotation
10468                 },
10469                 quaternion: {
10470                         configurable: true,
10471                         enumerable: true,
10472                         value: quaternion
10473                 },
10474                 scale: {
10475                         configurable: true,
10476                         enumerable: true,
10477                         value: scale
10478                 },
10479                 modelViewMatrix: {
10480                         value: new Matrix4()
10481                 },
10482                 normalMatrix: {
10483                         value: new Matrix3()
10484                 }
10485         } );
10486
10487         this.matrix = new Matrix4();
10488         this.matrixWorld = new Matrix4();
10489
10490         this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
10491         this.matrixWorldNeedsUpdate = false;
10492
10493         this.layers = new Layers();
10494         this.visible = true;
10495
10496         this.castShadow = false;
10497         this.receiveShadow = false;
10498
10499         this.frustumCulled = true;
10500         this.renderOrder = 0;
10501
10502         this.animations = [];
10503
10504         this.userData = {};
10505
10506     }
10507
10508     Object3D.DefaultUp = new Vector3( 0, 1, 0 );
10509     Object3D.DefaultMatrixAutoUpdate = true;
10510
10511     Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
10512
10513         constructor: Object3D,
10514
10515         isObject3D: true,
10516
10517         onBeforeRender: function () {},
10518         onAfterRender: function () {},
10519
10520         applyMatrix4: function ( matrix ) {
10521
10522                 if ( this.matrixAutoUpdate ) this.updateMatrix();
10523
10524                 this.matrix.premultiply( matrix );
10525
10526                 this.matrix.decompose( this.position, this.quaternion, this.scale );
10527
10528         },
10529
10530         applyQuaternion: function ( q ) {
10531
10532                 this.quaternion.premultiply( q );
10533
10534                 return this;
10535
10536         },
10537
10538         setRotationFromAxisAngle: function ( axis, angle ) {
10539
10540                 // assumes axis is normalized
10541
10542                 this.quaternion.setFromAxisAngle( axis, angle );
10543
10544         },
10545
10546         setRotationFromEuler: function ( euler ) {
10547
10548                 this.quaternion.setFromEuler( euler, true );
10549
10550         },
10551
10552         setRotationFromMatrix: function ( m ) {
10553
10554                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
10555
10556                 this.quaternion.setFromRotationMatrix( m );
10557
10558         },
10559
10560         setRotationFromQuaternion: function ( q ) {
10561
10562                 // assumes q is normalized
10563
10564                 this.quaternion.copy( q );
10565
10566         },
10567
10568         rotateOnAxis: function ( axis, angle ) {
10569
10570                 // rotate object on axis in object space
10571                 // axis is assumed to be normalized
10572
10573                 _q1.setFromAxisAngle( axis, angle );
10574
10575                 this.quaternion.multiply( _q1 );
10576
10577                 return this;
10578
10579         },
10580
10581         rotateOnWorldAxis: function ( axis, angle ) {
10582
10583                 // rotate object on axis in world space
10584                 // axis is assumed to be normalized
10585                 // method assumes no rotated parent
10586
10587                 _q1.setFromAxisAngle( axis, angle );
10588
10589                 this.quaternion.premultiply( _q1 );
10590
10591                 return this;
10592
10593         },
10594
10595         rotateX: function ( angle ) {
10596
10597                 return this.rotateOnAxis( _xAxis, angle );
10598
10599         },
10600
10601         rotateY: function ( angle ) {
10602
10603                 return this.rotateOnAxis( _yAxis, angle );
10604
10605         },
10606
10607         rotateZ: function ( angle ) {
10608
10609                 return this.rotateOnAxis( _zAxis, angle );
10610
10611         },
10612
10613         translateOnAxis: function ( axis, distance ) {
10614
10615                 // translate object by distance along axis in object space
10616                 // axis is assumed to be normalized
10617
10618                 _v1$2.copy( axis ).applyQuaternion( this.quaternion );
10619
10620                 this.position.add( _v1$2.multiplyScalar( distance ) );
10621
10622                 return this;
10623
10624         },
10625
10626         translateX: function ( distance ) {
10627
10628                 return this.translateOnAxis( _xAxis, distance );
10629
10630         },
10631
10632         translateY: function ( distance ) {
10633
10634                 return this.translateOnAxis( _yAxis, distance );
10635
10636         },
10637
10638         translateZ: function ( distance ) {
10639
10640                 return this.translateOnAxis( _zAxis, distance );
10641
10642         },
10643
10644         localToWorld: function ( vector ) {
10645
10646                 return vector.applyMatrix4( this.matrixWorld );
10647
10648         },
10649
10650         worldToLocal: function ( vector ) {
10651
10652                 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
10653
10654         },
10655
10656         lookAt: function ( x, y, z ) {
10657
10658                 // This method does not support objects having non-uniformly-scaled parent(s)
10659
10660                 if ( x.isVector3 ) {
10661
10662                         _target.copy( x );
10663
10664                 } else {
10665
10666                         _target.set( x, y, z );
10667
10668                 }
10669
10670                 const parent = this.parent;
10671
10672                 this.updateWorldMatrix( true, false );
10673
10674                 _position.setFromMatrixPosition( this.matrixWorld );
10675
10676                 if ( this.isCamera || this.isLight ) {
10677
10678                         _m1$1.lookAt( _position, _target, this.up );
10679
10680                 } else {
10681
10682                         _m1$1.lookAt( _target, _position, this.up );
10683
10684                 }
10685
10686                 this.quaternion.setFromRotationMatrix( _m1$1 );
10687
10688                 if ( parent ) {
10689
10690                         _m1$1.extractRotation( parent.matrixWorld );
10691                         _q1.setFromRotationMatrix( _m1$1 );
10692                         this.quaternion.premultiply( _q1.invert() );
10693
10694                 }
10695
10696         },
10697
10698         add: function ( object ) {
10699
10700                 if ( arguments.length > 1 ) {
10701
10702                         for ( let i = 0; i < arguments.length; i ++ ) {
10703
10704                                 this.add( arguments[ i ] );
10705
10706                         }
10707
10708                         return this;
10709
10710                 }
10711
10712                 if ( object === this ) {
10713
10714                         console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
10715                         return this;
10716
10717                 }
10718
10719                 if ( object && object.isObject3D ) {
10720
10721                         if ( object.parent !== null ) {
10722
10723                                 object.parent.remove( object );
10724
10725                         }
10726
10727                         object.parent = this;
10728                         this.children.push( object );
10729
10730                         object.dispatchEvent( _addedEvent );
10731
10732                 } else {
10733
10734                         console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
10735
10736                 }
10737
10738                 return this;
10739
10740         },
10741
10742         remove: function ( object ) {
10743
10744                 if ( arguments.length > 1 ) {
10745
10746                         for ( let i = 0; i < arguments.length; i ++ ) {
10747
10748                                 this.remove( arguments[ i ] );
10749
10750                         }
10751
10752                         return this;
10753
10754                 }
10755
10756                 const index = this.children.indexOf( object );
10757
10758                 if ( index !== - 1 ) {
10759
10760                         object.parent = null;
10761                         this.children.splice( index, 1 );
10762
10763                         object.dispatchEvent( _removedEvent );
10764
10765                 }
10766
10767                 return this;
10768
10769         },
10770
10771         clear: function () {
10772
10773                 for ( let i = 0; i < this.children.length; i ++ ) {
10774
10775                         const object = this.children[ i ];
10776
10777                         object.parent = null;
10778
10779                         object.dispatchEvent( _removedEvent );
10780
10781                 }
10782
10783                 this.children.length = 0;
10784
10785                 return this;
10786
10787
10788         },
10789
10790         attach: function ( object ) {
10791
10792                 // adds object as a child of this, while maintaining the object's world transform
10793
10794                 this.updateWorldMatrix( true, false );
10795
10796                 _m1$1.copy( this.matrixWorld ).invert();
10797
10798                 if ( object.parent !== null ) {
10799
10800                         object.parent.updateWorldMatrix( true, false );
10801
10802                         _m1$1.multiply( object.parent.matrixWorld );
10803
10804                 }
10805
10806                 object.applyMatrix4( _m1$1 );
10807
10808                 object.updateWorldMatrix( false, false );
10809
10810                 this.add( object );
10811
10812                 return this;
10813
10814         },
10815
10816         getObjectById: function ( id ) {
10817
10818                 return this.getObjectByProperty( 'id', id );
10819
10820         },
10821
10822         getObjectByName: function ( name ) {
10823
10824                 return this.getObjectByProperty( 'name', name );
10825
10826         },
10827
10828         getObjectByProperty: function ( name, value ) {
10829
10830                 if ( this[ name ] === value ) return this;
10831
10832                 for ( let i = 0, l = this.children.length; i < l; i ++ ) {
10833
10834                         const child = this.children[ i ];
10835                         const object = child.getObjectByProperty( name, value );
10836
10837                         if ( object !== undefined ) {
10838
10839                                 return object;
10840
10841                         }
10842
10843                 }
10844
10845                 return undefined;
10846
10847         },
10848
10849         getWorldPosition: function ( target ) {
10850
10851                 if ( target === undefined ) {
10852
10853                         console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
10854                         target = new Vector3();
10855
10856                 }
10857
10858                 this.updateWorldMatrix( true, false );
10859
10860                 return target.setFromMatrixPosition( this.matrixWorld );
10861
10862         },
10863
10864         getWorldQuaternion: function ( target ) {
10865
10866                 if ( target === undefined ) {
10867
10868                         console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
10869                         target = new Quaternion();
10870
10871                 }
10872
10873                 this.updateWorldMatrix( true, false );
10874
10875                 this.matrixWorld.decompose( _position, target, _scale );
10876
10877                 return target;
10878
10879         },
10880
10881         getWorldScale: function ( target ) {
10882
10883                 if ( target === undefined ) {
10884
10885                         console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
10886                         target = new Vector3();
10887
10888                 }
10889
10890                 this.updateWorldMatrix( true, false );
10891
10892                 this.matrixWorld.decompose( _position, _quaternion$2, target );
10893
10894                 return target;
10895
10896         },
10897
10898         getWorldDirection: function ( target ) {
10899
10900                 if ( target === undefined ) {
10901
10902                         console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
10903                         target = new Vector3();
10904
10905                 }
10906
10907                 this.updateWorldMatrix( true, false );
10908
10909                 const e = this.matrixWorld.elements;
10910
10911                 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
10912
10913         },
10914
10915         raycast: function () {},
10916
10917         traverse: function ( callback ) {
10918
10919                 callback( this );
10920
10921                 const children = this.children;
10922
10923                 for ( let i = 0, l = children.length; i < l; i ++ ) {
10924
10925                         children[ i ].traverse( callback );
10926
10927                 }
10928
10929         },
10930
10931         traverseVisible: function ( callback ) {
10932
10933                 if ( this.visible === false ) return;
10934
10935                 callback( this );
10936
10937                 const children = this.children;
10938
10939                 for ( let i = 0, l = children.length; i < l; i ++ ) {
10940
10941                         children[ i ].traverseVisible( callback );
10942
10943                 }
10944
10945         },
10946
10947         traverseAncestors: function ( callback ) {
10948
10949                 const parent = this.parent;
10950
10951                 if ( parent !== null ) {
10952
10953                         callback( parent );
10954
10955                         parent.traverseAncestors( callback );
10956
10957                 }
10958
10959         },
10960
10961         updateMatrix: function () {
10962
10963                 this.matrix.compose( this.position, this.quaternion, this.scale );
10964
10965                 this.matrixWorldNeedsUpdate = true;
10966
10967         },
10968
10969         updateMatrixWorld: function ( force ) {
10970
10971                 if ( this.matrixAutoUpdate ) this.updateMatrix();
10972
10973                 if ( this.matrixWorldNeedsUpdate || force ) {
10974
10975                         if ( this.parent === null ) {
10976
10977                                 this.matrixWorld.copy( this.matrix );
10978
10979                         } else {
10980
10981                                 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
10982
10983                         }
10984
10985                         this.matrixWorldNeedsUpdate = false;
10986
10987                         force = true;
10988
10989                 }
10990
10991                 // update children
10992
10993                 const children = this.children;
10994
10995                 for ( let i = 0, l = children.length; i < l; i ++ ) {
10996
10997                         children[ i ].updateMatrixWorld( force );
10998
10999                 }
11000
11001         },
11002
11003         updateWorldMatrix: function ( updateParents, updateChildren ) {
11004
11005                 const parent = this.parent;
11006
11007                 if ( updateParents === true && parent !== null ) {
11008
11009                         parent.updateWorldMatrix( true, false );
11010
11011                 }
11012
11013                 if ( this.matrixAutoUpdate ) this.updateMatrix();
11014
11015                 if ( this.parent === null ) {
11016
11017                         this.matrixWorld.copy( this.matrix );
11018
11019                 } else {
11020
11021                         this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
11022
11023                 }
11024
11025                 // update children
11026
11027                 if ( updateChildren === true ) {
11028
11029                         const children = this.children;
11030
11031                         for ( let i = 0, l = children.length; i < l; i ++ ) {
11032
11033                                 children[ i ].updateWorldMatrix( false, true );
11034
11035                         }
11036
11037                 }
11038
11039         },
11040
11041         toJSON: function ( meta ) {
11042
11043                 // meta is a string when called from JSON.stringify
11044                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
11045
11046                 const output = {};
11047
11048                 // meta is a hash used to collect geometries, materials.
11049                 // not providing it implies that this is the root object
11050                 // being serialized.
11051                 if ( isRootObject ) {
11052
11053                         // initialize meta obj
11054                         meta = {
11055                                 geometries: {},
11056                                 materials: {},
11057                                 textures: {},
11058                                 images: {},
11059                                 shapes: {},
11060                                 skeletons: {},
11061                                 animations: {}
11062                         };
11063
11064                         output.metadata = {
11065                                 version: 4.5,
11066                                 type: 'Object',
11067                                 generator: 'Object3D.toJSON'
11068                         };
11069
11070                 }
11071
11072                 // standard Object3D serialization
11073
11074                 const object = {};
11075
11076                 object.uuid = this.uuid;
11077                 object.type = this.type;
11078
11079                 if ( this.name !== '' ) object.name = this.name;
11080                 if ( this.castShadow === true ) object.castShadow = true;
11081                 if ( this.receiveShadow === true ) object.receiveShadow = true;
11082                 if ( this.visible === false ) object.visible = false;
11083                 if ( this.frustumCulled === false ) object.frustumCulled = false;
11084                 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
11085                 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
11086
11087                 object.layers = this.layers.mask;
11088                 object.matrix = this.matrix.toArray();
11089
11090                 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
11091
11092                 // object specific properties
11093
11094                 if ( this.isInstancedMesh ) {
11095
11096                         object.type = 'InstancedMesh';
11097                         object.count = this.count;
11098                         object.instanceMatrix = this.instanceMatrix.toJSON();
11099
11100                 }
11101
11102                 //
11103
11104                 function serialize( library, element ) {
11105
11106                         if ( library[ element.uuid ] === undefined ) {
11107
11108                                 library[ element.uuid ] = element.toJSON( meta );
11109
11110                         }
11111
11112                         return element.uuid;
11113
11114                 }
11115
11116                 if ( this.isMesh || this.isLine || this.isPoints ) {
11117
11118                         object.geometry = serialize( meta.geometries, this.geometry );
11119
11120                         const parameters = this.geometry.parameters;
11121
11122                         if ( parameters !== undefined && parameters.shapes !== undefined ) {
11123
11124                                 const shapes = parameters.shapes;
11125
11126                                 if ( Array.isArray( shapes ) ) {
11127
11128                                         for ( let i = 0, l = shapes.length; i < l; i ++ ) {
11129
11130                                                 const shape = shapes[ i ];
11131
11132                                                 serialize( meta.shapes, shape );
11133
11134                                         }
11135
11136                                 } else {
11137
11138                                         serialize( meta.shapes, shapes );
11139
11140                                 }
11141
11142                         }
11143
11144                 }
11145
11146                 if ( this.isSkinnedMesh ) {
11147
11148                         object.bindMode = this.bindMode;
11149                         object.bindMatrix = this.bindMatrix.toArray();
11150
11151                         if ( this.skeleton !== undefined ) {
11152
11153                                 serialize( meta.skeletons, this.skeleton );
11154
11155                                 object.skeleton = this.skeleton.uuid;
11156
11157                         }
11158
11159                 }
11160
11161                 if ( this.material !== undefined ) {
11162
11163                         if ( Array.isArray( this.material ) ) {
11164
11165                                 const uuids = [];
11166
11167                                 for ( let i = 0, l = this.material.length; i < l; i ++ ) {
11168
11169                                         uuids.push( serialize( meta.materials, this.material[ i ] ) );
11170
11171                                 }
11172
11173                                 object.material = uuids;
11174
11175                         } else {
11176
11177                                 object.material = serialize( meta.materials, this.material );
11178
11179                         }
11180
11181                 }
11182
11183                 //
11184
11185                 if ( this.children.length > 0 ) {
11186
11187                         object.children = [];
11188
11189                         for ( let i = 0; i < this.children.length; i ++ ) {
11190
11191                                 object.children.push( this.children[ i ].toJSON( meta ).object );
11192
11193                         }
11194
11195                 }
11196
11197                 //
11198
11199                 if ( this.animations.length > 0 ) {
11200
11201                         object.animations = [];
11202
11203                         for ( let i = 0; i < this.animations.length; i ++ ) {
11204
11205                                 const animation = this.animations[ i ];
11206
11207                                 object.animations.push( serialize( meta.animations, animation ) );
11208
11209                         }
11210
11211                 }
11212
11213                 if ( isRootObject ) {
11214
11215                         const geometries = extractFromCache( meta.geometries );
11216                         const materials = extractFromCache( meta.materials );
11217                         const textures = extractFromCache( meta.textures );
11218                         const images = extractFromCache( meta.images );
11219                         const shapes = extractFromCache( meta.shapes );
11220                         const skeletons = extractFromCache( meta.skeletons );
11221                         const animations = extractFromCache( meta.animations );
11222
11223                         if ( geometries.length > 0 ) output.geometries = geometries;
11224                         if ( materials.length > 0 ) output.materials = materials;
11225                         if ( textures.length > 0 ) output.textures = textures;
11226                         if ( images.length > 0 ) output.images = images;
11227                         if ( shapes.length > 0 ) output.shapes = shapes;
11228                         if ( skeletons.length > 0 ) output.skeletons = skeletons;
11229                         if ( animations.length > 0 ) output.animations = animations;
11230
11231                 }
11232
11233                 output.object = object;
11234
11235                 return output;
11236
11237                 // extract data from the cache hash
11238                 // remove metadata on each item
11239                 // and return as array
11240                 function extractFromCache( cache ) {
11241
11242                         const values = [];
11243                         for ( const key in cache ) {
11244
11245                                 const data = cache[ key ];
11246                                 delete data.metadata;
11247                                 values.push( data );
11248
11249                         }
11250
11251                         return values;
11252
11253                 }
11254
11255         },
11256
11257         clone: function ( recursive ) {
11258
11259                 return new this.constructor().copy( this, recursive );
11260
11261         },
11262
11263         copy: function ( source, recursive = true ) {
11264
11265                 this.name = source.name;
11266
11267                 this.up.copy( source.up );
11268
11269                 this.position.copy( source.position );
11270                 this.rotation.order = source.rotation.order;
11271                 this.quaternion.copy( source.quaternion );
11272                 this.scale.copy( source.scale );
11273
11274                 this.matrix.copy( source.matrix );
11275                 this.matrixWorld.copy( source.matrixWorld );
11276
11277                 this.matrixAutoUpdate = source.matrixAutoUpdate;
11278                 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
11279
11280                 this.layers.mask = source.layers.mask;
11281                 this.visible = source.visible;
11282
11283                 this.castShadow = source.castShadow;
11284                 this.receiveShadow = source.receiveShadow;
11285
11286                 this.frustumCulled = source.frustumCulled;
11287                 this.renderOrder = source.renderOrder;
11288
11289                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
11290
11291                 if ( recursive === true ) {
11292
11293                         for ( let i = 0; i < source.children.length; i ++ ) {
11294
11295                                 const child = source.children[ i ];
11296                                 this.add( child.clone() );
11297
11298                         }
11299
11300                 }
11301
11302                 return this;
11303
11304         }
11305
11306     } );
11307
11308     const _vector1 = /*@__PURE__*/ new Vector3();
11309     const _vector2 = /*@__PURE__*/ new Vector3();
11310     const _normalMatrix = /*@__PURE__*/ new Matrix3();
11311
11312     class Plane {
11313
11314         constructor( normal, constant ) {
11315
11316                 Object.defineProperty( this, 'isPlane', { value: true } );
11317
11318                 // normal is assumed to be normalized
11319
11320                 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
11321                 this.constant = ( constant !== undefined ) ? constant : 0;
11322
11323         }
11324
11325         set( normal, constant ) {
11326
11327                 this.normal.copy( normal );
11328                 this.constant = constant;
11329
11330                 return this;
11331
11332         }
11333
11334         setComponents( x, y, z, w ) {
11335
11336                 this.normal.set( x, y, z );
11337                 this.constant = w;
11338
11339                 return this;
11340
11341         }
11342
11343         setFromNormalAndCoplanarPoint( normal, point ) {
11344
11345                 this.normal.copy( normal );
11346                 this.constant = - point.dot( this.normal );
11347
11348                 return this;
11349
11350         }
11351
11352         setFromCoplanarPoints( a, b, c ) {
11353
11354                 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
11355
11356                 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
11357
11358                 this.setFromNormalAndCoplanarPoint( normal, a );
11359
11360                 return this;
11361
11362         }
11363
11364         clone() {
11365
11366                 return new this.constructor().copy( this );
11367
11368         }
11369
11370         copy( plane ) {
11371
11372                 this.normal.copy( plane.normal );
11373                 this.constant = plane.constant;
11374
11375                 return this;
11376
11377         }
11378
11379         normalize() {
11380
11381                 // Note: will lead to a divide by zero if the plane is invalid.
11382
11383                 const inverseNormalLength = 1.0 / this.normal.length();
11384                 this.normal.multiplyScalar( inverseNormalLength );
11385                 this.constant *= inverseNormalLength;
11386
11387                 return this;
11388
11389         }
11390
11391         negate() {
11392
11393                 this.constant *= - 1;
11394                 this.normal.negate();
11395
11396                 return this;
11397
11398         }
11399
11400         distanceToPoint( point ) {
11401
11402                 return this.normal.dot( point ) + this.constant;
11403
11404         }
11405
11406         distanceToSphere( sphere ) {
11407
11408                 return this.distanceToPoint( sphere.center ) - sphere.radius;
11409
11410         }
11411
11412         projectPoint( point, target ) {
11413
11414                 if ( target === undefined ) {
11415
11416                         console.warn( 'THREE.Plane: .projectPoint() target is now required' );
11417                         target = new Vector3();
11418
11419                 }
11420
11421                 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
11422
11423         }
11424
11425         intersectLine( line, target ) {
11426
11427                 if ( target === undefined ) {
11428
11429                         console.warn( 'THREE.Plane: .intersectLine() target is now required' );
11430                         target = new Vector3();
11431
11432                 }
11433
11434                 const direction = line.delta( _vector1 );
11435
11436                 const denominator = this.normal.dot( direction );
11437
11438                 if ( denominator === 0 ) {
11439
11440                         // line is coplanar, return origin
11441                         if ( this.distanceToPoint( line.start ) === 0 ) {
11442
11443                                 return target.copy( line.start );
11444
11445                         }
11446
11447                         // Unsure if this is the correct method to handle this case.
11448                         return undefined;
11449
11450                 }
11451
11452                 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
11453
11454                 if ( t < 0 || t > 1 ) {
11455
11456                         return undefined;
11457
11458                 }
11459
11460                 return target.copy( direction ).multiplyScalar( t ).add( line.start );
11461
11462         }
11463
11464         intersectsLine( line ) {
11465
11466                 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
11467
11468                 const startSign = this.distanceToPoint( line.start );
11469                 const endSign = this.distanceToPoint( line.end );
11470
11471                 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
11472
11473         }
11474
11475         intersectsBox( box ) {
11476
11477                 return box.intersectsPlane( this );
11478
11479         }
11480
11481         intersectsSphere( sphere ) {
11482
11483                 return sphere.intersectsPlane( this );
11484
11485         }
11486
11487         coplanarPoint( target ) {
11488
11489                 if ( target === undefined ) {
11490
11491                         console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
11492                         target = new Vector3();
11493
11494                 }
11495
11496                 return target.copy( this.normal ).multiplyScalar( - this.constant );
11497
11498         }
11499
11500         applyMatrix4( matrix, optionalNormalMatrix ) {
11501
11502                 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
11503
11504                 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
11505
11506                 const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
11507
11508                 this.constant = - referencePoint.dot( normal );
11509
11510                 return this;
11511
11512         }
11513
11514         translate( offset ) {
11515
11516                 this.constant -= offset.dot( this.normal );
11517
11518                 return this;
11519
11520         }
11521
11522         equals( plane ) {
11523
11524                 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
11525
11526         }
11527
11528     }
11529
11530     const _v0$1 = /*@__PURE__*/ new Vector3();
11531     const _v1$3 = /*@__PURE__*/ new Vector3();
11532     const _v2$1 = /*@__PURE__*/ new Vector3();
11533     const _v3 = /*@__PURE__*/ new Vector3();
11534
11535     const _vab = /*@__PURE__*/ new Vector3();
11536     const _vac = /*@__PURE__*/ new Vector3();
11537     const _vbc = /*@__PURE__*/ new Vector3();
11538     const _vap = /*@__PURE__*/ new Vector3();
11539     const _vbp = /*@__PURE__*/ new Vector3();
11540     const _vcp = /*@__PURE__*/ new Vector3();
11541
11542     class Triangle {
11543
11544         constructor( a, b, c ) {
11545
11546                 this.a = ( a !== undefined ) ? a : new Vector3();
11547                 this.b = ( b !== undefined ) ? b : new Vector3();
11548                 this.c = ( c !== undefined ) ? c : new Vector3();
11549
11550         }
11551
11552         static getNormal( a, b, c, target ) {
11553
11554                 if ( target === undefined ) {
11555
11556                         console.warn( 'THREE.Triangle: .getNormal() target is now required' );
11557                         target = new Vector3();
11558
11559                 }
11560
11561                 target.subVectors( c, b );
11562                 _v0$1.subVectors( a, b );
11563                 target.cross( _v0$1 );
11564
11565                 const targetLengthSq = target.lengthSq();
11566                 if ( targetLengthSq > 0 ) {
11567
11568                         return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
11569
11570                 }
11571
11572                 return target.set( 0, 0, 0 );
11573
11574         }
11575
11576         // static/instance method to calculate barycentric coordinates
11577         // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
11578         static getBarycoord( point, a, b, c, target ) {
11579
11580                 _v0$1.subVectors( c, a );
11581                 _v1$3.subVectors( b, a );
11582                 _v2$1.subVectors( point, a );
11583
11584                 const dot00 = _v0$1.dot( _v0$1 );
11585                 const dot01 = _v0$1.dot( _v1$3 );
11586                 const dot02 = _v0$1.dot( _v2$1 );
11587                 const dot11 = _v1$3.dot( _v1$3 );
11588                 const dot12 = _v1$3.dot( _v2$1 );
11589
11590                 const denom = ( dot00 * dot11 - dot01 * dot01 );
11591
11592                 if ( target === undefined ) {
11593
11594                         console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
11595                         target = new Vector3();
11596
11597                 }
11598
11599                 // collinear or singular triangle
11600                 if ( denom === 0 ) {
11601
11602                         // arbitrary location outside of triangle?
11603                         // not sure if this is the best idea, maybe should be returning undefined
11604                         return target.set( - 2, - 1, - 1 );
11605
11606                 }
11607
11608                 const invDenom = 1 / denom;
11609                 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
11610                 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
11611
11612                 // barycentric coordinates must always sum to 1
11613                 return target.set( 1 - u - v, v, u );
11614
11615         }
11616
11617         static containsPoint( point, a, b, c ) {
11618
11619                 this.getBarycoord( point, a, b, c, _v3 );
11620
11621                 return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
11622
11623         }
11624
11625         static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
11626
11627                 this.getBarycoord( point, p1, p2, p3, _v3 );
11628
11629                 target.set( 0, 0 );
11630                 target.addScaledVector( uv1, _v3.x );
11631                 target.addScaledVector( uv2, _v3.y );
11632                 target.addScaledVector( uv3, _v3.z );
11633
11634                 return target;
11635
11636         }
11637
11638         static isFrontFacing( a, b, c, direction ) {
11639
11640                 _v0$1.subVectors( c, b );
11641                 _v1$3.subVectors( a, b );
11642
11643                 // strictly front facing
11644                 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
11645
11646         }
11647
11648         set( a, b, c ) {
11649
11650                 this.a.copy( a );
11651                 this.b.copy( b );
11652                 this.c.copy( c );
11653
11654                 return this;
11655
11656         }
11657
11658         setFromPointsAndIndices( points, i0, i1, i2 ) {
11659
11660                 this.a.copy( points[ i0 ] );
11661                 this.b.copy( points[ i1 ] );
11662                 this.c.copy( points[ i2 ] );
11663
11664                 return this;
11665
11666         }
11667
11668         clone() {
11669
11670                 return new this.constructor().copy( this );
11671
11672         }
11673
11674         copy( triangle ) {
11675
11676                 this.a.copy( triangle.a );
11677                 this.b.copy( triangle.b );
11678                 this.c.copy( triangle.c );
11679
11680                 return this;
11681
11682         }
11683
11684         getArea() {
11685
11686                 _v0$1.subVectors( this.c, this.b );
11687                 _v1$3.subVectors( this.a, this.b );
11688
11689                 return _v0$1.cross( _v1$3 ).length() * 0.5;
11690
11691         }
11692
11693         getMidpoint( target ) {
11694
11695                 if ( target === undefined ) {
11696
11697                         console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
11698                         target = new Vector3();
11699
11700                 }
11701
11702                 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
11703
11704         }
11705
11706         getNormal( target ) {
11707
11708                 return Triangle.getNormal( this.a, this.b, this.c, target );
11709
11710         }
11711
11712         getPlane( target ) {
11713
11714                 if ( target === undefined ) {
11715
11716                         console.warn( 'THREE.Triangle: .getPlane() target is now required' );
11717                         target = new Plane();
11718
11719                 }
11720
11721                 return target.setFromCoplanarPoints( this.a, this.b, this.c );
11722
11723         }
11724
11725         getBarycoord( point, target ) {
11726
11727                 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
11728
11729         }
11730
11731         getUV( point, uv1, uv2, uv3, target ) {
11732
11733                 return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
11734
11735         }
11736
11737         containsPoint( point ) {
11738
11739                 return Triangle.containsPoint( point, this.a, this.b, this.c );
11740
11741         }
11742
11743         isFrontFacing( direction ) {
11744
11745                 return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
11746
11747         }
11748
11749         intersectsBox( box ) {
11750
11751                 return box.intersectsTriangle( this );
11752
11753         }
11754
11755         closestPointToPoint( p, target ) {
11756
11757                 if ( target === undefined ) {
11758
11759                         console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
11760                         target = new Vector3();
11761
11762                 }
11763
11764                 const a = this.a, b = this.b, c = this.c;
11765                 let v, w;
11766
11767                 // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
11768                 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
11769                 // under the accompanying license; see chapter 5.1.5 for detailed explanation.
11770                 // basically, we're distinguishing which of the voronoi regions of the triangle
11771                 // the point lies in with the minimum amount of redundant computation.
11772
11773                 _vab.subVectors( b, a );
11774                 _vac.subVectors( c, a );
11775                 _vap.subVectors( p, a );
11776                 const d1 = _vab.dot( _vap );
11777                 const d2 = _vac.dot( _vap );
11778                 if ( d1 <= 0 && d2 <= 0 ) {
11779
11780                         // vertex region of A; barycentric coords (1, 0, 0)
11781                         return target.copy( a );
11782
11783                 }
11784
11785                 _vbp.subVectors( p, b );
11786                 const d3 = _vab.dot( _vbp );
11787                 const d4 = _vac.dot( _vbp );
11788                 if ( d3 >= 0 && d4 <= d3 ) {
11789
11790                         // vertex region of B; barycentric coords (0, 1, 0)
11791                         return target.copy( b );
11792
11793                 }
11794
11795                 const vc = d1 * d4 - d3 * d2;
11796                 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
11797
11798                         v = d1 / ( d1 - d3 );
11799                         // edge region of AB; barycentric coords (1-v, v, 0)
11800                         return target.copy( a ).addScaledVector( _vab, v );
11801
11802                 }
11803
11804                 _vcp.subVectors( p, c );
11805                 const d5 = _vab.dot( _vcp );
11806                 const d6 = _vac.dot( _vcp );
11807                 if ( d6 >= 0 && d5 <= d6 ) {
11808
11809                         // vertex region of C; barycentric coords (0, 0, 1)
11810                         return target.copy( c );
11811
11812                 }
11813
11814                 const vb = d5 * d2 - d1 * d6;
11815                 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
11816
11817                         w = d2 / ( d2 - d6 );
11818                         // edge region of AC; barycentric coords (1-w, 0, w)
11819                         return target.copy( a ).addScaledVector( _vac, w );
11820
11821                 }
11822
11823                 const va = d3 * d6 - d5 * d4;
11824                 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
11825
11826                         _vbc.subVectors( c, b );
11827                         w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
11828                         // edge region of BC; barycentric coords (0, 1-w, w)
11829                         return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
11830
11831                 }
11832
11833                 // face region
11834                 const denom = 1 / ( va + vb + vc );
11835                 // u = va * denom
11836                 v = vb * denom;
11837                 w = vc * denom;
11838
11839                 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
11840
11841         }
11842
11843         equals( triangle ) {
11844
11845                 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
11846
11847         }
11848
11849     }
11850
11851     const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
11852         'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
11853         'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
11854         'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
11855         'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
11856         'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
11857         'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
11858         'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
11859         'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
11860         'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
11861         'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
11862         'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
11863         'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
11864         'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
11865         'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
11866         'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
11867         'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
11868         'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
11869         'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
11870         'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
11871         'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
11872         'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
11873         'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
11874         'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
11875
11876     const _hslA = { h: 0, s: 0, l: 0 };
11877     const _hslB = { h: 0, s: 0, l: 0 };
11878
11879     function hue2rgb( p, q, t ) {
11880
11881         if ( t < 0 ) t += 1;
11882         if ( t > 1 ) t -= 1;
11883         if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
11884         if ( t < 1 / 2 ) return q;
11885         if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
11886         return p;
11887
11888     }
11889
11890     function SRGBToLinear( c ) {
11891
11892         return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
11893
11894     }
11895
11896     function LinearToSRGB( c ) {
11897
11898         return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
11899
11900     }
11901
11902     class Color {
11903
11904         constructor( r, g, b ) {
11905
11906                 Object.defineProperty( this, 'isColor', { value: true } );
11907
11908                 if ( g === undefined && b === undefined ) {
11909
11910                         // r is THREE.Color, hex or string
11911                         return this.set( r );
11912
11913                 }
11914
11915                 return this.setRGB( r, g, b );
11916
11917         }
11918
11919         set( value ) {
11920
11921                 if ( value && value.isColor ) {
11922
11923                         this.copy( value );
11924
11925                 } else if ( typeof value === 'number' ) {
11926
11927                         this.setHex( value );
11928
11929                 } else if ( typeof value === 'string' ) {
11930
11931                         this.setStyle( value );
11932
11933                 }
11934
11935                 return this;
11936
11937         }
11938
11939         setScalar( scalar ) {
11940
11941                 this.r = scalar;
11942                 this.g = scalar;
11943                 this.b = scalar;
11944
11945                 return this;
11946
11947         }
11948
11949         setHex( hex ) {
11950
11951                 hex = Math.floor( hex );
11952
11953                 this.r = ( hex >> 16 & 255 ) / 255;
11954                 this.g = ( hex >> 8 & 255 ) / 255;
11955                 this.b = ( hex & 255 ) / 255;
11956
11957                 return this;
11958
11959         }
11960
11961         setRGB( r, g, b ) {
11962
11963                 this.r = r;
11964                 this.g = g;
11965                 this.b = b;
11966
11967                 return this;
11968
11969         }
11970
11971         setHSL( h, s, l ) {
11972
11973                 // h,s,l ranges are in 0.0 - 1.0
11974                 h = MathUtils.euclideanModulo( h, 1 );
11975                 s = MathUtils.clamp( s, 0, 1 );
11976                 l = MathUtils.clamp( l, 0, 1 );
11977
11978                 if ( s === 0 ) {
11979
11980                         this.r = this.g = this.b = l;
11981
11982                 } else {
11983
11984                         const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
11985                         const q = ( 2 * l ) - p;
11986
11987                         this.r = hue2rgb( q, p, h + 1 / 3 );
11988                         this.g = hue2rgb( q, p, h );
11989                         this.b = hue2rgb( q, p, h - 1 / 3 );
11990
11991                 }
11992
11993                 return this;
11994
11995         }
11996
11997         setStyle( style ) {
11998
11999                 function handleAlpha( string ) {
12000
12001                         if ( string === undefined ) return;
12002
12003                         if ( parseFloat( string ) < 1 ) {
12004
12005                                 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
12006
12007                         }
12008
12009                 }
12010
12011
12012                 let m;
12013
12014                 if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) {
12015
12016                         // rgb / hsl
12017
12018                         let color;
12019                         const name = m[ 1 ];
12020                         const components = m[ 2 ];
12021
12022                         switch ( name ) {
12023
12024                                 case 'rgb':
12025                                 case 'rgba':
12026
12027                                         if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
12028
12029                                                 // rgb(255,0,0) rgba(255,0,0,0.5)
12030                                                 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
12031                                                 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
12032                                                 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
12033
12034                                                 handleAlpha( color[ 4 ] );
12035
12036                                                 return this;
12037
12038                                         }
12039
12040                                         if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
12041
12042                                                 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
12043                                                 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
12044                                                 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
12045                                                 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
12046
12047                                                 handleAlpha( color[ 4 ] );
12048
12049                                                 return this;
12050
12051                                         }
12052
12053                                         break;
12054
12055                                 case 'hsl':
12056                                 case 'hsla':
12057
12058                                         if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
12059
12060                                                 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
12061                                                 const h = parseFloat( color[ 1 ] ) / 360;
12062                                                 const s = parseInt( color[ 2 ], 10 ) / 100;
12063                                                 const l = parseInt( color[ 3 ], 10 ) / 100;
12064
12065                                                 handleAlpha( color[ 4 ] );
12066
12067                                                 return this.setHSL( h, s, l );
12068
12069                                         }
12070
12071                                         break;
12072
12073                         }
12074
12075                 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
12076
12077                         // hex color
12078
12079                         const hex = m[ 1 ];
12080                         const size = hex.length;
12081
12082                         if ( size === 3 ) {
12083
12084                                 // #ff0
12085                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
12086                                 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
12087                                 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
12088
12089                                 return this;
12090
12091                         } else if ( size === 6 ) {
12092
12093                                 // #ff0000
12094                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
12095                                 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
12096                                 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
12097
12098                                 return this;
12099
12100                         }
12101
12102                 }
12103
12104                 if ( style && style.length > 0 ) {
12105
12106                         return this.setColorName( style );
12107
12108                 }
12109
12110                 return this;
12111
12112         }
12113
12114         setColorName( style ) {
12115
12116                 // color keywords
12117                 const hex = _colorKeywords[ style ];
12118
12119                 if ( hex !== undefined ) {
12120
12121                         // red
12122                         this.setHex( hex );
12123
12124                 } else {
12125
12126                         // unknown color
12127                         console.warn( 'THREE.Color: Unknown color ' + style );
12128
12129                 }
12130
12131                 return this;
12132
12133         }
12134
12135         clone() {
12136
12137                 return new this.constructor( this.r, this.g, this.b );
12138
12139         }
12140
12141         copy( color ) {
12142
12143                 this.r = color.r;
12144                 this.g = color.g;
12145                 this.b = color.b;
12146
12147                 return this;
12148
12149         }
12150
12151         copyGammaToLinear( color, gammaFactor = 2.0 ) {
12152
12153                 this.r = Math.pow( color.r, gammaFactor );
12154                 this.g = Math.pow( color.g, gammaFactor );
12155                 this.b = Math.pow( color.b, gammaFactor );
12156
12157                 return this;
12158
12159         }
12160
12161         copyLinearToGamma( color, gammaFactor = 2.0 ) {
12162
12163                 const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
12164
12165                 this.r = Math.pow( color.r, safeInverse );
12166                 this.g = Math.pow( color.g, safeInverse );
12167                 this.b = Math.pow( color.b, safeInverse );
12168
12169                 return this;
12170
12171         }
12172
12173         convertGammaToLinear( gammaFactor ) {
12174
12175                 this.copyGammaToLinear( this, gammaFactor );
12176
12177                 return this;
12178
12179         }
12180
12181         convertLinearToGamma( gammaFactor ) {
12182
12183                 this.copyLinearToGamma( this, gammaFactor );
12184
12185                 return this;
12186
12187         }
12188
12189         copySRGBToLinear( color ) {
12190
12191                 this.r = SRGBToLinear( color.r );
12192                 this.g = SRGBToLinear( color.g );
12193                 this.b = SRGBToLinear( color.b );
12194
12195                 return this;
12196
12197         }
12198
12199         copyLinearToSRGB( color ) {
12200
12201                 this.r = LinearToSRGB( color.r );
12202                 this.g = LinearToSRGB( color.g );
12203                 this.b = LinearToSRGB( color.b );
12204
12205                 return this;
12206
12207         }
12208
12209         convertSRGBToLinear() {
12210
12211                 this.copySRGBToLinear( this );
12212
12213                 return this;
12214
12215         }
12216
12217         convertLinearToSRGB() {
12218
12219                 this.copyLinearToSRGB( this );
12220
12221                 return this;
12222
12223         }
12224
12225         getHex() {
12226
12227                 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
12228
12229         }
12230
12231         getHexString() {
12232
12233                 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
12234
12235         }
12236
12237         getHSL( target ) {
12238
12239                 // h,s,l ranges are in 0.0 - 1.0
12240
12241                 if ( target === undefined ) {
12242
12243                         console.warn( 'THREE.Color: .getHSL() target is now required' );
12244                         target = { h: 0, s: 0, l: 0 };
12245
12246                 }
12247
12248                 const r = this.r, g = this.g, b = this.b;
12249
12250                 const max = Math.max( r, g, b );
12251                 const min = Math.min( r, g, b );
12252
12253                 let hue, saturation;
12254                 const lightness = ( min + max ) / 2.0;
12255
12256                 if ( min === max ) {
12257
12258                         hue = 0;
12259                         saturation = 0;
12260
12261                 } else {
12262
12263                         const delta = max - min;
12264
12265                         saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
12266
12267                         switch ( max ) {
12268
12269                                 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
12270                                 case g: hue = ( b - r ) / delta + 2; break;
12271                                 case b: hue = ( r - g ) / delta + 4; break;
12272
12273                         }
12274
12275                         hue /= 6;
12276
12277                 }
12278
12279                 target.h = hue;
12280                 target.s = saturation;
12281                 target.l = lightness;
12282
12283                 return target;
12284
12285         }
12286
12287         getStyle() {
12288
12289                 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
12290
12291         }
12292
12293         offsetHSL( h, s, l ) {
12294
12295                 this.getHSL( _hslA );
12296
12297                 _hslA.h += h; _hslA.s += s; _hslA.l += l;
12298
12299                 this.setHSL( _hslA.h, _hslA.s, _hslA.l );
12300
12301                 return this;
12302
12303         }
12304
12305         add( color ) {
12306
12307                 this.r += color.r;
12308                 this.g += color.g;
12309                 this.b += color.b;
12310
12311                 return this;
12312
12313         }
12314
12315         addColors( color1, color2 ) {
12316
12317                 this.r = color1.r + color2.r;
12318                 this.g = color1.g + color2.g;
12319                 this.b = color1.b + color2.b;
12320
12321                 return this;
12322
12323         }
12324
12325         addScalar( s ) {
12326
12327                 this.r += s;
12328                 this.g += s;
12329                 this.b += s;
12330
12331                 return this;
12332
12333         }
12334
12335         sub( color ) {
12336
12337                 this.r = Math.max( 0, this.r - color.r );
12338                 this.g = Math.max( 0, this.g - color.g );
12339                 this.b = Math.max( 0, this.b - color.b );
12340
12341                 return this;
12342
12343         }
12344
12345         multiply( color ) {
12346
12347                 this.r *= color.r;
12348                 this.g *= color.g;
12349                 this.b *= color.b;
12350
12351                 return this;
12352
12353         }
12354
12355         multiplyScalar( s ) {
12356
12357                 this.r *= s;
12358                 this.g *= s;
12359                 this.b *= s;
12360
12361                 return this;
12362
12363         }
12364
12365         lerp( color, alpha ) {
12366
12367                 this.r += ( color.r - this.r ) * alpha;
12368                 this.g += ( color.g - this.g ) * alpha;
12369                 this.b += ( color.b - this.b ) * alpha;
12370
12371                 return this;
12372
12373         }
12374
12375         lerpColors( color1, color2, alpha ) {
12376
12377                 this.r = color1.r + ( color2.r - color1.r ) * alpha;
12378                 this.g = color1.g + ( color2.g - color1.g ) * alpha;
12379                 this.b = color1.b + ( color2.b - color1.b ) * alpha;
12380
12381                 return this;
12382
12383         }
12384
12385         lerpHSL( color, alpha ) {
12386
12387                 this.getHSL( _hslA );
12388                 color.getHSL( _hslB );
12389
12390                 const h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );
12391                 const s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );
12392                 const l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );
12393
12394                 this.setHSL( h, s, l );
12395
12396                 return this;
12397
12398         }
12399
12400         equals( c ) {
12401
12402                 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
12403
12404         }
12405
12406         fromArray( array, offset = 0 ) {
12407
12408                 this.r = array[ offset ];
12409                 this.g = array[ offset + 1 ];
12410                 this.b = array[ offset + 2 ];
12411
12412                 return this;
12413
12414         }
12415
12416         toArray( array = [], offset = 0 ) {
12417
12418                 array[ offset ] = this.r;
12419                 array[ offset + 1 ] = this.g;
12420                 array[ offset + 2 ] = this.b;
12421
12422                 return array;
12423
12424         }
12425
12426         fromBufferAttribute( attribute, index ) {
12427
12428                 this.r = attribute.getX( index );
12429                 this.g = attribute.getY( index );
12430                 this.b = attribute.getZ( index );
12431
12432                 if ( attribute.normalized === true ) {
12433
12434                         // assuming Uint8Array
12435
12436                         this.r /= 255;
12437                         this.g /= 255;
12438                         this.b /= 255;
12439
12440                 }
12441
12442                 return this;
12443
12444         }
12445
12446         toJSON() {
12447
12448                 return this.getHex();
12449
12450         }
12451
12452     }
12453
12454     Color.NAMES = _colorKeywords;
12455     Color.prototype.r = 1;
12456     Color.prototype.g = 1;
12457     Color.prototype.b = 1;
12458
12459     class Face3 {
12460
12461         constructor( a, b, c, normal, color, materialIndex = 0 ) {
12462
12463                 this.a = a;
12464                 this.b = b;
12465                 this.c = c;
12466
12467                 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
12468                 this.vertexNormals = Array.isArray( normal ) ? normal : [];
12469
12470                 this.color = ( color && color.isColor ) ? color : new Color();
12471                 this.vertexColors = Array.isArray( color ) ? color : [];
12472
12473                 this.materialIndex = materialIndex;
12474
12475         }
12476
12477         clone() {
12478
12479                 return new this.constructor().copy( this );
12480
12481         }
12482
12483         copy( source ) {
12484
12485                 this.a = source.a;
12486                 this.b = source.b;
12487                 this.c = source.c;
12488
12489                 this.normal.copy( source.normal );
12490                 this.color.copy( source.color );
12491
12492                 this.materialIndex = source.materialIndex;
12493
12494                 for ( let i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
12495
12496                         this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
12497
12498                 }
12499
12500                 for ( let i = 0, il = source.vertexColors.length; i < il; i ++ ) {
12501
12502                         this.vertexColors[ i ] = source.vertexColors[ i ].clone();
12503
12504                 }
12505
12506                 return this;
12507
12508         }
12509
12510     }
12511
12512     let materialId = 0;
12513
12514     function Material() {
12515
12516         Object.defineProperty( this, 'id', { value: materialId ++ } );
12517
12518         this.uuid = MathUtils.generateUUID();
12519
12520         this.name = '';
12521         this.type = 'Material';
12522
12523         this.fog = true;
12524
12525         this.blending = NormalBlending;
12526         this.side = FrontSide;
12527         this.flatShading = false;
12528         this.vertexColors = false;
12529
12530         this.opacity = 1;
12531         this.transparent = false;
12532
12533         this.blendSrc = SrcAlphaFactor;
12534         this.blendDst = OneMinusSrcAlphaFactor;
12535         this.blendEquation = AddEquation;
12536         this.blendSrcAlpha = null;
12537         this.blendDstAlpha = null;
12538         this.blendEquationAlpha = null;
12539
12540         this.depthFunc = LessEqualDepth;
12541         this.depthTest = true;
12542         this.depthWrite = true;
12543
12544         this.stencilWriteMask = 0xff;
12545         this.stencilFunc = AlwaysStencilFunc;
12546         this.stencilRef = 0;
12547         this.stencilFuncMask = 0xff;
12548         this.stencilFail = KeepStencilOp;
12549         this.stencilZFail = KeepStencilOp;
12550         this.stencilZPass = KeepStencilOp;
12551         this.stencilWrite = false;
12552
12553         this.clippingPlanes = null;
12554         this.clipIntersection = false;
12555         this.clipShadows = false;
12556
12557         this.shadowSide = null;
12558
12559         this.colorWrite = true;
12560
12561         this.precision = null; // override the renderer's default precision for this material
12562
12563         this.polygonOffset = false;
12564         this.polygonOffsetFactor = 0;
12565         this.polygonOffsetUnits = 0;
12566
12567         this.dithering = false;
12568
12569         this.alphaTest = 0;
12570         this.premultipliedAlpha = false;
12571
12572         this.visible = true;
12573
12574         this.toneMapped = true;
12575
12576         this.userData = {};
12577
12578         this.version = 0;
12579
12580     }
12581
12582     Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
12583
12584         constructor: Material,
12585
12586         isMaterial: true,
12587
12588         onBeforeCompile: function ( /* shaderobject, renderer */ ) {},
12589
12590         customProgramCacheKey: function () {
12591
12592                 return this.onBeforeCompile.toString();
12593
12594         },
12595
12596         setValues: function ( values ) {
12597
12598                 if ( values === undefined ) return;
12599
12600                 for ( const key in values ) {
12601
12602                         const newValue = values[ key ];
12603
12604                         if ( newValue === undefined ) {
12605
12606                                 console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
12607                                 continue;
12608
12609                         }
12610
12611                         // for backward compatability if shading is set in the constructor
12612                         if ( key === 'shading' ) {
12613
12614                                 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
12615                                 this.flatShading = ( newValue === FlatShading ) ? true : false;
12616                                 continue;
12617
12618                         }
12619
12620                         const currentValue = this[ key ];
12621
12622                         if ( currentValue === undefined ) {
12623
12624                                 console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
12625                                 continue;
12626
12627                         }
12628
12629                         if ( currentValue && currentValue.isColor ) {
12630
12631                                 currentValue.set( newValue );
12632
12633                         } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
12634
12635                                 currentValue.copy( newValue );
12636
12637                         } else {
12638
12639                                 this[ key ] = newValue;
12640
12641                         }
12642
12643                 }
12644
12645         },
12646
12647         toJSON: function ( meta ) {
12648
12649                 const isRoot = ( meta === undefined || typeof meta === 'string' );
12650
12651                 if ( isRoot ) {
12652
12653                         meta = {
12654                                 textures: {},
12655                                 images: {}
12656                         };
12657
12658                 }
12659
12660                 const data = {
12661                         metadata: {
12662                                 version: 4.5,
12663                                 type: 'Material',
12664                                 generator: 'Material.toJSON'
12665                         }
12666                 };
12667
12668                 // standard Material serialization
12669                 data.uuid = this.uuid;
12670                 data.type = this.type;
12671
12672                 if ( this.name !== '' ) data.name = this.name;
12673
12674                 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
12675
12676                 if ( this.roughness !== undefined ) data.roughness = this.roughness;
12677                 if ( this.metalness !== undefined ) data.metalness = this.metalness;
12678
12679                 if ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();
12680                 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
12681                 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
12682
12683                 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
12684                 if ( this.shininess !== undefined ) data.shininess = this.shininess;
12685                 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
12686                 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
12687
12688                 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
12689
12690                         data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
12691
12692                 }
12693
12694                 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
12695
12696                         data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
12697
12698                 }
12699
12700                 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
12701
12702                         data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
12703                         data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
12704
12705                 }
12706
12707                 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
12708                 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
12709                 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
12710                 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
12711
12712                 if ( this.aoMap && this.aoMap.isTexture ) {
12713
12714                         data.aoMap = this.aoMap.toJSON( meta ).uuid;
12715                         data.aoMapIntensity = this.aoMapIntensity;
12716
12717                 }
12718
12719                 if ( this.bumpMap && this.bumpMap.isTexture ) {
12720
12721                         data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
12722                         data.bumpScale = this.bumpScale;
12723
12724                 }
12725
12726                 if ( this.normalMap && this.normalMap.isTexture ) {
12727
12728                         data.normalMap = this.normalMap.toJSON( meta ).uuid;
12729                         data.normalMapType = this.normalMapType;
12730                         data.normalScale = this.normalScale.toArray();
12731
12732                 }
12733
12734                 if ( this.displacementMap && this.displacementMap.isTexture ) {
12735
12736                         data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
12737                         data.displacementScale = this.displacementScale;
12738                         data.displacementBias = this.displacementBias;
12739
12740                 }
12741
12742                 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
12743                 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
12744
12745                 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
12746                 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
12747
12748                 if ( this.envMap && this.envMap.isTexture ) {
12749
12750                         data.envMap = this.envMap.toJSON( meta ).uuid;
12751                         data.reflectivity = this.reflectivity; // Scale behind envMap
12752                         data.refractionRatio = this.refractionRatio;
12753
12754                         if ( this.combine !== undefined ) data.combine = this.combine;
12755                         if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
12756
12757                 }
12758
12759                 if ( this.gradientMap && this.gradientMap.isTexture ) {
12760
12761                         data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
12762
12763                 }
12764
12765                 if ( this.size !== undefined ) data.size = this.size;
12766                 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
12767
12768                 if ( this.blending !== NormalBlending ) data.blending = this.blending;
12769                 if ( this.flatShading === true ) data.flatShading = this.flatShading;
12770                 if ( this.side !== FrontSide ) data.side = this.side;
12771                 if ( this.vertexColors ) data.vertexColors = true;
12772
12773                 if ( this.opacity < 1 ) data.opacity = this.opacity;
12774                 if ( this.transparent === true ) data.transparent = this.transparent;
12775
12776                 data.depthFunc = this.depthFunc;
12777                 data.depthTest = this.depthTest;
12778                 data.depthWrite = this.depthWrite;
12779
12780                 data.stencilWrite = this.stencilWrite;
12781                 data.stencilWriteMask = this.stencilWriteMask;
12782                 data.stencilFunc = this.stencilFunc;
12783                 data.stencilRef = this.stencilRef;
12784                 data.stencilFuncMask = this.stencilFuncMask;
12785                 data.stencilFail = this.stencilFail;
12786                 data.stencilZFail = this.stencilZFail;
12787                 data.stencilZPass = this.stencilZPass;
12788
12789                 // rotation (SpriteMaterial)
12790                 if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
12791
12792                 if ( this.polygonOffset === true ) data.polygonOffset = true;
12793                 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
12794                 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
12795
12796                 if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
12797                 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
12798                 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
12799                 if ( this.scale !== undefined ) data.scale = this.scale;
12800
12801                 if ( this.dithering === true ) data.dithering = true;
12802
12803                 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
12804                 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
12805
12806                 if ( this.wireframe === true ) data.wireframe = this.wireframe;
12807                 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
12808                 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
12809                 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
12810
12811                 if ( this.morphTargets === true ) data.morphTargets = true;
12812                 if ( this.morphNormals === true ) data.morphNormals = true;
12813                 if ( this.skinning === true ) data.skinning = true;
12814
12815                 if ( this.visible === false ) data.visible = false;
12816
12817                 if ( this.toneMapped === false ) data.toneMapped = false;
12818
12819                 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
12820
12821                 // TODO: Copied from Object3D.toJSON
12822
12823                 function extractFromCache( cache ) {
12824
12825                         const values = [];
12826
12827                         for ( const key in cache ) {
12828
12829                                 const data = cache[ key ];
12830                                 delete data.metadata;
12831                                 values.push( data );
12832
12833                         }
12834
12835                         return values;
12836
12837                 }
12838
12839                 if ( isRoot ) {
12840
12841                         const textures = extractFromCache( meta.textures );
12842                         const images = extractFromCache( meta.images );
12843
12844                         if ( textures.length > 0 ) data.textures = textures;
12845                         if ( images.length > 0 ) data.images = images;
12846
12847                 }
12848
12849                 return data;
12850
12851         },
12852
12853         clone: function () {
12854
12855                 return new this.constructor().copy( this );
12856
12857         },
12858
12859         copy: function ( source ) {
12860
12861                 this.name = source.name;
12862
12863                 this.fog = source.fog;
12864
12865                 this.blending = source.blending;
12866                 this.side = source.side;
12867                 this.flatShading = source.flatShading;
12868                 this.vertexColors = source.vertexColors;
12869
12870                 this.opacity = source.opacity;
12871                 this.transparent = source.transparent;
12872
12873                 this.blendSrc = source.blendSrc;
12874                 this.blendDst = source.blendDst;
12875                 this.blendEquation = source.blendEquation;
12876                 this.blendSrcAlpha = source.blendSrcAlpha;
12877                 this.blendDstAlpha = source.blendDstAlpha;
12878                 this.blendEquationAlpha = source.blendEquationAlpha;
12879
12880                 this.depthFunc = source.depthFunc;
12881                 this.depthTest = source.depthTest;
12882                 this.depthWrite = source.depthWrite;
12883
12884                 this.stencilWriteMask = source.stencilWriteMask;
12885                 this.stencilFunc = source.stencilFunc;
12886                 this.stencilRef = source.stencilRef;
12887                 this.stencilFuncMask = source.stencilFuncMask;
12888                 this.stencilFail = source.stencilFail;
12889                 this.stencilZFail = source.stencilZFail;
12890                 this.stencilZPass = source.stencilZPass;
12891                 this.stencilWrite = source.stencilWrite;
12892
12893                 const srcPlanes = source.clippingPlanes;
12894                 let dstPlanes = null;
12895
12896                 if ( srcPlanes !== null ) {
12897
12898                         const n = srcPlanes.length;
12899                         dstPlanes = new Array( n );
12900
12901                         for ( let i = 0; i !== n; ++ i ) {
12902
12903                                 dstPlanes[ i ] = srcPlanes[ i ].clone();
12904
12905                         }
12906
12907                 }
12908
12909                 this.clippingPlanes = dstPlanes;
12910                 this.clipIntersection = source.clipIntersection;
12911                 this.clipShadows = source.clipShadows;
12912
12913                 this.shadowSide = source.shadowSide;
12914
12915                 this.colorWrite = source.colorWrite;
12916
12917                 this.precision = source.precision;
12918
12919                 this.polygonOffset = source.polygonOffset;
12920                 this.polygonOffsetFactor = source.polygonOffsetFactor;
12921                 this.polygonOffsetUnits = source.polygonOffsetUnits;
12922
12923                 this.dithering = source.dithering;
12924
12925                 this.alphaTest = source.alphaTest;
12926                 this.premultipliedAlpha = source.premultipliedAlpha;
12927
12928                 this.visible = source.visible;
12929
12930                 this.toneMapped = source.toneMapped;
12931
12932                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
12933
12934                 return this;
12935
12936         },
12937
12938         dispose: function () {
12939
12940                 this.dispatchEvent( { type: 'dispose' } );
12941
12942         }
12943
12944     } );
12945
12946     Object.defineProperty( Material.prototype, 'needsUpdate', {
12947
12948         set: function ( value ) {
12949
12950                 if ( value === true ) this.version ++;
12951
12952         }
12953
12954     } );
12955
12956     /**
12957      * parameters = {
12958      *  color: <hex>,
12959      *  opacity: <float>,
12960      *  map: new THREE.Texture( <Image> ),
12961      *
12962      *  lightMap: new THREE.Texture( <Image> ),
12963      *  lightMapIntensity: <float>
12964      *
12965      *  aoMap: new THREE.Texture( <Image> ),
12966      *  aoMapIntensity: <float>
12967      *
12968      *  specularMap: new THREE.Texture( <Image> ),
12969      *
12970      *  alphaMap: new THREE.Texture( <Image> ),
12971      *
12972      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
12973      *  combine: THREE.Multiply,
12974      *  reflectivity: <float>,
12975      *  refractionRatio: <float>,
12976      *
12977      *  depthTest: <bool>,
12978      *  depthWrite: <bool>,
12979      *
12980      *  wireframe: <boolean>,
12981      *  wireframeLinewidth: <float>,
12982      *
12983      *  skinning: <bool>,
12984      *  morphTargets: <bool>
12985      * }
12986      */
12987
12988     function MeshBasicMaterial( parameters ) {
12989
12990         Material.call( this );
12991
12992         this.type = 'MeshBasicMaterial';
12993
12994         this.color = new Color( 0xffffff ); // emissive
12995
12996         this.map = null;
12997
12998         this.lightMap = null;
12999         this.lightMapIntensity = 1.0;
13000
13001         this.aoMap = null;
13002         this.aoMapIntensity = 1.0;
13003
13004         this.specularMap = null;
13005
13006         this.alphaMap = null;
13007
13008         this.envMap = null;
13009         this.combine = MultiplyOperation;
13010         this.reflectivity = 1;
13011         this.refractionRatio = 0.98;
13012
13013         this.wireframe = false;
13014         this.wireframeLinewidth = 1;
13015         this.wireframeLinecap = 'round';
13016         this.wireframeLinejoin = 'round';
13017
13018         this.skinning = false;
13019         this.morphTargets = false;
13020
13021         this.setValues( parameters );
13022
13023     }
13024
13025     MeshBasicMaterial.prototype = Object.create( Material.prototype );
13026     MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
13027
13028     MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
13029
13030     MeshBasicMaterial.prototype.copy = function ( source ) {
13031
13032         Material.prototype.copy.call( this, source );
13033
13034         this.color.copy( source.color );
13035
13036         this.map = source.map;
13037
13038         this.lightMap = source.lightMap;
13039         this.lightMapIntensity = source.lightMapIntensity;
13040
13041         this.aoMap = source.aoMap;
13042         this.aoMapIntensity = source.aoMapIntensity;
13043
13044         this.specularMap = source.specularMap;
13045
13046         this.alphaMap = source.alphaMap;
13047
13048         this.envMap = source.envMap;
13049         this.combine = source.combine;
13050         this.reflectivity = source.reflectivity;
13051         this.refractionRatio = source.refractionRatio;
13052
13053         this.wireframe = source.wireframe;
13054         this.wireframeLinewidth = source.wireframeLinewidth;
13055         this.wireframeLinecap = source.wireframeLinecap;
13056         this.wireframeLinejoin = source.wireframeLinejoin;
13057
13058         this.skinning = source.skinning;
13059         this.morphTargets = source.morphTargets;
13060
13061         return this;
13062
13063     };
13064
13065     const _vector$3 = new Vector3();
13066     const _vector2$1 = new Vector2();
13067
13068     function BufferAttribute( array, itemSize, normalized ) {
13069
13070         if ( Array.isArray( array ) ) {
13071
13072                 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
13073
13074         }
13075
13076         this.name = '';
13077
13078         this.array = array;
13079         this.itemSize = itemSize;
13080         this.count = array !== undefined ? array.length / itemSize : 0;
13081         this.normalized = normalized === true;
13082
13083         this.usage = StaticDrawUsage;
13084         this.updateRange = { offset: 0, count: - 1 };
13085
13086         this.version = 0;
13087
13088     }
13089
13090     Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
13091
13092         set: function ( value ) {
13093
13094                 if ( value === true ) this.version ++;
13095
13096         }
13097
13098     } );
13099
13100     Object.assign( BufferAttribute.prototype, {
13101
13102         isBufferAttribute: true,
13103
13104         onUploadCallback: function () {},
13105
13106         setUsage: function ( value ) {
13107
13108                 this.usage = value;
13109
13110                 return this;
13111
13112         },
13113
13114         copy: function ( source ) {
13115
13116                 this.name = source.name;
13117                 this.array = new source.array.constructor( source.array );
13118                 this.itemSize = source.itemSize;
13119                 this.count = source.count;
13120                 this.normalized = source.normalized;
13121
13122                 this.usage = source.usage;
13123
13124                 return this;
13125
13126         },
13127
13128         copyAt: function ( index1, attribute, index2 ) {
13129
13130                 index1 *= this.itemSize;
13131                 index2 *= attribute.itemSize;
13132
13133                 for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
13134
13135                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
13136
13137                 }
13138
13139                 return this;
13140
13141         },
13142
13143         copyArray: function ( array ) {
13144
13145                 this.array.set( array );
13146
13147                 return this;
13148
13149         },
13150
13151         copyColorsArray: function ( colors ) {
13152
13153                 const array = this.array;
13154                 let offset = 0;
13155
13156                 for ( let i = 0, l = colors.length; i < l; i ++ ) {
13157
13158                         let color = colors[ i ];
13159
13160                         if ( color === undefined ) {
13161
13162                                 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
13163                                 color = new Color();
13164
13165                         }
13166
13167                         array[ offset ++ ] = color.r;
13168                         array[ offset ++ ] = color.g;
13169                         array[ offset ++ ] = color.b;
13170
13171                 }
13172
13173                 return this;
13174
13175         },
13176
13177         copyVector2sArray: function ( vectors ) {
13178
13179                 const array = this.array;
13180                 let offset = 0;
13181
13182                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
13183
13184                         let vector = vectors[ i ];
13185
13186                         if ( vector === undefined ) {
13187
13188                                 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
13189                                 vector = new Vector2();
13190
13191                         }
13192
13193                         array[ offset ++ ] = vector.x;
13194                         array[ offset ++ ] = vector.y;
13195
13196                 }
13197
13198                 return this;
13199
13200         },
13201
13202         copyVector3sArray: function ( vectors ) {
13203
13204                 const array = this.array;
13205                 let offset = 0;
13206
13207                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
13208
13209                         let vector = vectors[ i ];
13210
13211                         if ( vector === undefined ) {
13212
13213                                 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
13214                                 vector = new Vector3();
13215
13216                         }
13217
13218                         array[ offset ++ ] = vector.x;
13219                         array[ offset ++ ] = vector.y;
13220                         array[ offset ++ ] = vector.z;
13221
13222                 }
13223
13224                 return this;
13225
13226         },
13227
13228         copyVector4sArray: function ( vectors ) {
13229
13230                 const array = this.array;
13231                 let offset = 0;
13232
13233                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
13234
13235                         let vector = vectors[ i ];
13236
13237                         if ( vector === undefined ) {
13238
13239                                 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
13240                                 vector = new Vector4();
13241
13242                         }
13243
13244                         array[ offset ++ ] = vector.x;
13245                         array[ offset ++ ] = vector.y;
13246                         array[ offset ++ ] = vector.z;
13247                         array[ offset ++ ] = vector.w;
13248
13249                 }
13250
13251                 return this;
13252
13253         },
13254
13255         applyMatrix3: function ( m ) {
13256
13257                 if ( this.itemSize === 2 ) {
13258
13259                         for ( let i = 0, l = this.count; i < l; i ++ ) {
13260
13261                                 _vector2$1.fromBufferAttribute( this, i );
13262                                 _vector2$1.applyMatrix3( m );
13263
13264                                 this.setXY( i, _vector2$1.x, _vector2$1.y );
13265
13266                         }
13267
13268                 } else if ( this.itemSize === 3 ) {
13269
13270                         for ( let i = 0, l = this.count; i < l; i ++ ) {
13271
13272                                 _vector$3.fromBufferAttribute( this, i );
13273                                 _vector$3.applyMatrix3( m );
13274
13275                                 this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
13276
13277                         }
13278
13279                 }
13280
13281                 return this;
13282
13283         },
13284
13285         applyMatrix4: function ( m ) {
13286
13287                 for ( let i = 0, l = this.count; i < l; i ++ ) {
13288
13289                         _vector$3.x = this.getX( i );
13290                         _vector$3.y = this.getY( i );
13291                         _vector$3.z = this.getZ( i );
13292
13293                         _vector$3.applyMatrix4( m );
13294
13295                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
13296
13297                 }
13298
13299                 return this;
13300
13301         },
13302
13303         applyNormalMatrix: function ( m ) {
13304
13305                 for ( let i = 0, l = this.count; i < l; i ++ ) {
13306
13307                         _vector$3.x = this.getX( i );
13308                         _vector$3.y = this.getY( i );
13309                         _vector$3.z = this.getZ( i );
13310
13311                         _vector$3.applyNormalMatrix( m );
13312
13313                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
13314
13315                 }
13316
13317                 return this;
13318
13319         },
13320
13321         transformDirection: function ( m ) {
13322
13323                 for ( let i = 0, l = this.count; i < l; i ++ ) {
13324
13325                         _vector$3.x = this.getX( i );
13326                         _vector$3.y = this.getY( i );
13327                         _vector$3.z = this.getZ( i );
13328
13329                         _vector$3.transformDirection( m );
13330
13331                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
13332
13333                 }
13334
13335                 return this;
13336
13337         },
13338
13339         set: function ( value, offset = 0 ) {
13340
13341                 this.array.set( value, offset );
13342
13343                 return this;
13344
13345         },
13346
13347         getX: function ( index ) {
13348
13349                 return this.array[ index * this.itemSize ];
13350
13351         },
13352
13353         setX: function ( index, x ) {
13354
13355                 this.array[ index * this.itemSize ] = x;
13356
13357                 return this;
13358
13359         },
13360
13361         getY: function ( index ) {
13362
13363                 return this.array[ index * this.itemSize + 1 ];
13364
13365         },
13366
13367         setY: function ( index, y ) {
13368
13369                 this.array[ index * this.itemSize + 1 ] = y;
13370
13371                 return this;
13372
13373         },
13374
13375         getZ: function ( index ) {
13376
13377                 return this.array[ index * this.itemSize + 2 ];
13378
13379         },
13380
13381         setZ: function ( index, z ) {
13382
13383                 this.array[ index * this.itemSize + 2 ] = z;
13384
13385                 return this;
13386
13387         },
13388
13389         getW: function ( index ) {
13390
13391                 return this.array[ index * this.itemSize + 3 ];
13392
13393         },
13394
13395         setW: function ( index, w ) {
13396
13397                 this.array[ index * this.itemSize + 3 ] = w;
13398
13399                 return this;
13400
13401         },
13402
13403         setXY: function ( index, x, y ) {
13404
13405                 index *= this.itemSize;
13406
13407                 this.array[ index + 0 ] = x;
13408                 this.array[ index + 1 ] = y;
13409
13410                 return this;
13411
13412         },
13413
13414         setXYZ: function ( index, x, y, z ) {
13415
13416                 index *= this.itemSize;
13417
13418                 this.array[ index + 0 ] = x;
13419                 this.array[ index + 1 ] = y;
13420                 this.array[ index + 2 ] = z;
13421
13422                 return this;
13423
13424         },
13425
13426         setXYZW: function ( index, x, y, z, w ) {
13427
13428                 index *= this.itemSize;
13429
13430                 this.array[ index + 0 ] = x;
13431                 this.array[ index + 1 ] = y;
13432                 this.array[ index + 2 ] = z;
13433                 this.array[ index + 3 ] = w;
13434
13435                 return this;
13436
13437         },
13438
13439         onUpload: function ( callback ) {
13440
13441                 this.onUploadCallback = callback;
13442
13443                 return this;
13444
13445         },
13446
13447         clone: function () {
13448
13449                 return new this.constructor( this.array, this.itemSize ).copy( this );
13450
13451         },
13452
13453         toJSON: function () {
13454
13455                 return {
13456                         itemSize: this.itemSize,
13457                         type: this.array.constructor.name,
13458                         array: Array.prototype.slice.call( this.array ),
13459                         normalized: this.normalized
13460                 };
13461
13462         }
13463
13464     } );
13465
13466     //
13467
13468     function Int8BufferAttribute( array, itemSize, normalized ) {
13469
13470         BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
13471
13472     }
13473
13474     Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13475     Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
13476
13477
13478     function Uint8BufferAttribute( array, itemSize, normalized ) {
13479
13480         BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
13481
13482     }
13483
13484     Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13485     Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
13486
13487
13488     function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
13489
13490         BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
13491
13492     }
13493
13494     Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13495     Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
13496
13497
13498     function Int16BufferAttribute( array, itemSize, normalized ) {
13499
13500         BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
13501
13502     }
13503
13504     Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13505     Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
13506
13507
13508     function Uint16BufferAttribute( array, itemSize, normalized ) {
13509
13510         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
13511
13512     }
13513
13514     Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13515     Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
13516
13517
13518     function Int32BufferAttribute( array, itemSize, normalized ) {
13519
13520         BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
13521
13522     }
13523
13524     Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13525     Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
13526
13527
13528     function Uint32BufferAttribute( array, itemSize, normalized ) {
13529
13530         BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
13531
13532     }
13533
13534     Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13535     Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
13536
13537     function Float16BufferAttribute( array, itemSize, normalized ) {
13538
13539         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
13540
13541     }
13542
13543     Float16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13544     Float16BufferAttribute.prototype.constructor = Float16BufferAttribute;
13545     Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
13546
13547     function Float32BufferAttribute( array, itemSize, normalized ) {
13548
13549         BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
13550
13551     }
13552
13553     Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13554     Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
13555
13556
13557     function Float64BufferAttribute( array, itemSize, normalized ) {
13558
13559         BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
13560
13561     }
13562
13563     Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13564     Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
13565
13566     function arrayMax( array ) {
13567
13568         if ( array.length === 0 ) return - Infinity;
13569
13570         let max = array[ 0 ];
13571
13572         for ( let i = 1, l = array.length; i < l; ++ i ) {
13573
13574                 if ( array[ i ] > max ) max = array[ i ];
13575
13576         }
13577
13578         return max;
13579
13580     }
13581
13582     const TYPED_ARRAYS = {
13583         Int8Array: Int8Array,
13584         Uint8Array: Uint8Array,
13585         // Workaround for IE11 pre KB2929437. See #11440
13586         Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
13587         Int16Array: Int16Array,
13588         Uint16Array: Uint16Array,
13589         Int32Array: Int32Array,
13590         Uint32Array: Uint32Array,
13591         Float32Array: Float32Array,
13592         Float64Array: Float64Array
13593     };
13594
13595     function getTypedArray( type, buffer ) {
13596
13597         return new TYPED_ARRAYS[ type ]( buffer );
13598
13599     }
13600
13601     let _id = 0;
13602
13603     const _m1$2 = new Matrix4();
13604     const _obj = new Object3D();
13605     const _offset = new Vector3();
13606     const _box$2 = new Box3();
13607     const _boxMorphTargets = new Box3();
13608     const _vector$4 = new Vector3();
13609
13610     function BufferGeometry() {
13611
13612         Object.defineProperty( this, 'id', { value: _id ++ } );
13613
13614         this.uuid = MathUtils.generateUUID();
13615
13616         this.name = '';
13617         this.type = 'BufferGeometry';
13618
13619         this.index = null;
13620         this.attributes = {};
13621
13622         this.morphAttributes = {};
13623         this.morphTargetsRelative = false;
13624
13625         this.groups = [];
13626
13627         this.boundingBox = null;
13628         this.boundingSphere = null;
13629
13630         this.drawRange = { start: 0, count: Infinity };
13631
13632         this.userData = {};
13633
13634     }
13635
13636     BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
13637
13638         constructor: BufferGeometry,
13639
13640         isBufferGeometry: true,
13641
13642         getIndex: function () {
13643
13644                 return this.index;
13645
13646         },
13647
13648         setIndex: function ( index ) {
13649
13650                 if ( Array.isArray( index ) ) {
13651
13652                         this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
13653
13654                 } else {
13655
13656                         this.index = index;
13657
13658                 }
13659
13660                 return this;
13661
13662         },
13663
13664         getAttribute: function ( name ) {
13665
13666                 return this.attributes[ name ];
13667
13668         },
13669
13670         setAttribute: function ( name, attribute ) {
13671
13672                 this.attributes[ name ] = attribute;
13673
13674                 return this;
13675
13676         },
13677
13678         deleteAttribute: function ( name ) {
13679
13680                 delete this.attributes[ name ];
13681
13682                 return this;
13683
13684         },
13685
13686         hasAttribute: function ( name ) {
13687
13688                 return this.attributes[ name ] !== undefined;
13689
13690         },
13691
13692         addGroup: function ( start, count, materialIndex = 0 ) {
13693
13694                 this.groups.push( {
13695
13696                         start: start,
13697                         count: count,
13698                         materialIndex: materialIndex
13699
13700                 } );
13701
13702         },
13703
13704         clearGroups: function () {
13705
13706                 this.groups = [];
13707
13708         },
13709
13710         setDrawRange: function ( start, count ) {
13711
13712                 this.drawRange.start = start;
13713                 this.drawRange.count = count;
13714
13715         },
13716
13717         applyMatrix4: function ( matrix ) {
13718
13719                 const position = this.attributes.position;
13720
13721                 if ( position !== undefined ) {
13722
13723                         position.applyMatrix4( matrix );
13724
13725                         position.needsUpdate = true;
13726
13727                 }
13728
13729                 const normal = this.attributes.normal;
13730
13731                 if ( normal !== undefined ) {
13732
13733                         const normalMatrix = new Matrix3().getNormalMatrix( matrix );
13734
13735                         normal.applyNormalMatrix( normalMatrix );
13736
13737                         normal.needsUpdate = true;
13738
13739                 }
13740
13741                 const tangent = this.attributes.tangent;
13742
13743                 if ( tangent !== undefined ) {
13744
13745                         tangent.transformDirection( matrix );
13746
13747                         tangent.needsUpdate = true;
13748
13749                 }
13750
13751                 if ( this.boundingBox !== null ) {
13752
13753                         this.computeBoundingBox();
13754
13755                 }
13756
13757                 if ( this.boundingSphere !== null ) {
13758
13759                         this.computeBoundingSphere();
13760
13761                 }
13762
13763                 return this;
13764
13765         },
13766
13767         rotateX: function ( angle ) {
13768
13769                 // rotate geometry around world x-axis
13770
13771                 _m1$2.makeRotationX( angle );
13772
13773                 this.applyMatrix4( _m1$2 );
13774
13775                 return this;
13776
13777         },
13778
13779         rotateY: function ( angle ) {
13780
13781                 // rotate geometry around world y-axis
13782
13783                 _m1$2.makeRotationY( angle );
13784
13785                 this.applyMatrix4( _m1$2 );
13786
13787                 return this;
13788
13789         },
13790
13791         rotateZ: function ( angle ) {
13792
13793                 // rotate geometry around world z-axis
13794
13795                 _m1$2.makeRotationZ( angle );
13796
13797                 this.applyMatrix4( _m1$2 );
13798
13799                 return this;
13800
13801         },
13802
13803         translate: function ( x, y, z ) {
13804
13805                 // translate geometry
13806
13807                 _m1$2.makeTranslation( x, y, z );
13808
13809                 this.applyMatrix4( _m1$2 );
13810
13811                 return this;
13812
13813         },
13814
13815         scale: function ( x, y, z ) {
13816
13817                 // scale geometry
13818
13819                 _m1$2.makeScale( x, y, z );
13820
13821                 this.applyMatrix4( _m1$2 );
13822
13823                 return this;
13824
13825         },
13826
13827         lookAt: function ( vector ) {
13828
13829                 _obj.lookAt( vector );
13830
13831                 _obj.updateMatrix();
13832
13833                 this.applyMatrix4( _obj.matrix );
13834
13835                 return this;
13836
13837         },
13838
13839         center: function () {
13840
13841                 this.computeBoundingBox();
13842
13843                 this.boundingBox.getCenter( _offset ).negate();
13844
13845                 this.translate( _offset.x, _offset.y, _offset.z );
13846
13847                 return this;
13848
13849         },
13850
13851         setFromPoints: function ( points ) {
13852
13853                 const position = [];
13854
13855                 for ( let i = 0, l = points.length; i < l; i ++ ) {
13856
13857                         const point = points[ i ];
13858                         position.push( point.x, point.y, point.z || 0 );
13859
13860                 }
13861
13862                 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
13863
13864                 return this;
13865
13866         },
13867
13868         computeBoundingBox: function () {
13869
13870                 if ( this.boundingBox === null ) {
13871
13872                         this.boundingBox = new Box3();
13873
13874                 }
13875
13876                 const position = this.attributes.position;
13877                 const morphAttributesPosition = this.morphAttributes.position;
13878
13879                 if ( position && position.isGLBufferAttribute ) {
13880
13881                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
13882
13883                         this.boundingBox.set(
13884                                 new Vector3( - Infinity, - Infinity, - Infinity ),
13885                                 new Vector3( + Infinity, + Infinity, + Infinity )
13886                         );
13887
13888                         return;
13889
13890                 }
13891
13892                 if ( position !== undefined ) {
13893
13894                         this.boundingBox.setFromBufferAttribute( position );
13895
13896                         // process morph attributes if present
13897
13898                         if ( morphAttributesPosition ) {
13899
13900                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
13901
13902                                         const morphAttribute = morphAttributesPosition[ i ];
13903                                         _box$2.setFromBufferAttribute( morphAttribute );
13904
13905                                         if ( this.morphTargetsRelative ) {
13906
13907                                                 _vector$4.addVectors( this.boundingBox.min, _box$2.min );
13908                                                 this.boundingBox.expandByPoint( _vector$4 );
13909
13910                                                 _vector$4.addVectors( this.boundingBox.max, _box$2.max );
13911                                                 this.boundingBox.expandByPoint( _vector$4 );
13912
13913                                         } else {
13914
13915                                                 this.boundingBox.expandByPoint( _box$2.min );
13916                                                 this.boundingBox.expandByPoint( _box$2.max );
13917
13918                                         }
13919
13920                                 }
13921
13922                         }
13923
13924                 } else {
13925
13926                         this.boundingBox.makeEmpty();
13927
13928                 }
13929
13930                 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
13931
13932                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
13933
13934                 }
13935
13936         },
13937
13938         computeBoundingSphere: function () {
13939
13940                 if ( this.boundingSphere === null ) {
13941
13942                         this.boundingSphere = new Sphere();
13943
13944                 }
13945
13946                 const position = this.attributes.position;
13947                 const morphAttributesPosition = this.morphAttributes.position;
13948
13949                 if ( position && position.isGLBufferAttribute ) {
13950
13951                         console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
13952
13953                         this.boundingSphere.set( new Vector3(), Infinity );
13954
13955                         return;
13956
13957                 }
13958
13959                 if ( position ) {
13960
13961                         // first, find the center of the bounding sphere
13962
13963                         const center = this.boundingSphere.center;
13964
13965                         _box$2.setFromBufferAttribute( position );
13966
13967                         // process morph attributes if present
13968
13969                         if ( morphAttributesPosition ) {
13970
13971                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
13972
13973                                         const morphAttribute = morphAttributesPosition[ i ];
13974                                         _boxMorphTargets.setFromBufferAttribute( morphAttribute );
13975
13976                                         if ( this.morphTargetsRelative ) {
13977
13978                                                 _vector$4.addVectors( _box$2.min, _boxMorphTargets.min );
13979                                                 _box$2.expandByPoint( _vector$4 );
13980
13981                                                 _vector$4.addVectors( _box$2.max, _boxMorphTargets.max );
13982                                                 _box$2.expandByPoint( _vector$4 );
13983
13984                                         } else {
13985
13986                                                 _box$2.expandByPoint( _boxMorphTargets.min );
13987                                                 _box$2.expandByPoint( _boxMorphTargets.max );
13988
13989                                         }
13990
13991                                 }
13992
13993                         }
13994
13995                         _box$2.getCenter( center );
13996
13997                         // second, try to find a boundingSphere with a radius smaller than the
13998                         // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
13999
14000                         let maxRadiusSq = 0;
14001
14002                         for ( let i = 0, il = position.count; i < il; i ++ ) {
14003
14004                                 _vector$4.fromBufferAttribute( position, i );
14005
14006                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
14007
14008                         }
14009
14010                         // process morph attributes if present
14011
14012                         if ( morphAttributesPosition ) {
14013
14014                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
14015
14016                                         const morphAttribute = morphAttributesPosition[ i ];
14017                                         const morphTargetsRelative = this.morphTargetsRelative;
14018
14019                                         for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
14020
14021                                                 _vector$4.fromBufferAttribute( morphAttribute, j );
14022
14023                                                 if ( morphTargetsRelative ) {
14024
14025                                                         _offset.fromBufferAttribute( position, j );
14026                                                         _vector$4.add( _offset );
14027
14028                                                 }
14029
14030                                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
14031
14032                                         }
14033
14034                                 }
14035
14036                         }
14037
14038                         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
14039
14040                         if ( isNaN( this.boundingSphere.radius ) ) {
14041
14042                                 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
14043
14044                         }
14045
14046                 }
14047
14048         },
14049
14050         computeFaceNormals: function () {
14051
14052                 // backwards compatibility
14053
14054         },
14055
14056         computeTangents: function () {
14057
14058                 const index = this.index;
14059                 const attributes = this.attributes;
14060
14061                 // based on http://www.terathon.com/code/tangent.html
14062                 // (per vertex tangents)
14063
14064                 if ( index === null ||
14065                          attributes.position === undefined ||
14066                          attributes.normal === undefined ||
14067                          attributes.uv === undefined ) {
14068
14069                         console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
14070                         return;
14071
14072                 }
14073
14074                 const indices = index.array;
14075                 const positions = attributes.position.array;
14076                 const normals = attributes.normal.array;
14077                 const uvs = attributes.uv.array;
14078
14079                 const nVertices = positions.length / 3;
14080
14081                 if ( attributes.tangent === undefined ) {
14082
14083                         this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
14084
14085                 }
14086
14087                 const tangents = attributes.tangent.array;
14088
14089                 const tan1 = [], tan2 = [];
14090
14091                 for ( let i = 0; i < nVertices; i ++ ) {
14092
14093                         tan1[ i ] = new Vector3();
14094                         tan2[ i ] = new Vector3();
14095
14096                 }
14097
14098                 const vA = new Vector3(),
14099                         vB = new Vector3(),
14100                         vC = new Vector3(),
14101
14102                         uvA = new Vector2(),
14103                         uvB = new Vector2(),
14104                         uvC = new Vector2(),
14105
14106                         sdir = new Vector3(),
14107                         tdir = new Vector3();
14108
14109                 function handleTriangle( a, b, c ) {
14110
14111                         vA.fromArray( positions, a * 3 );
14112                         vB.fromArray( positions, b * 3 );
14113                         vC.fromArray( positions, c * 3 );
14114
14115                         uvA.fromArray( uvs, a * 2 );
14116                         uvB.fromArray( uvs, b * 2 );
14117                         uvC.fromArray( uvs, c * 2 );
14118
14119                         vB.sub( vA );
14120                         vC.sub( vA );
14121
14122                         uvB.sub( uvA );
14123                         uvC.sub( uvA );
14124
14125                         const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
14126
14127                         // silently ignore degenerate uv triangles having coincident or colinear vertices
14128
14129                         if ( ! isFinite( r ) ) return;
14130
14131                         sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
14132                         tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
14133
14134                         tan1[ a ].add( sdir );
14135                         tan1[ b ].add( sdir );
14136                         tan1[ c ].add( sdir );
14137
14138                         tan2[ a ].add( tdir );
14139                         tan2[ b ].add( tdir );
14140                         tan2[ c ].add( tdir );
14141
14142                 }
14143
14144                 let groups = this.groups;
14145
14146                 if ( groups.length === 0 ) {
14147
14148                         groups = [ {
14149                                 start: 0,
14150                                 count: indices.length
14151                         } ];
14152
14153                 }
14154
14155                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
14156
14157                         const group = groups[ i ];
14158
14159                         const start = group.start;
14160                         const count = group.count;
14161
14162                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
14163
14164                                 handleTriangle(
14165                                         indices[ j + 0 ],
14166                                         indices[ j + 1 ],
14167                                         indices[ j + 2 ]
14168                                 );
14169
14170                         }
14171
14172                 }
14173
14174                 const tmp = new Vector3(), tmp2 = new Vector3();
14175                 const n = new Vector3(), n2 = new Vector3();
14176
14177                 function handleVertex( v ) {
14178
14179                         n.fromArray( normals, v * 3 );
14180                         n2.copy( n );
14181
14182                         const t = tan1[ v ];
14183
14184                         // Gram-Schmidt orthogonalize
14185
14186                         tmp.copy( t );
14187                         tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
14188
14189                         // Calculate handedness
14190
14191                         tmp2.crossVectors( n2, t );
14192                         const test = tmp2.dot( tan2[ v ] );
14193                         const w = ( test < 0.0 ) ? - 1.0 : 1.0;
14194
14195                         tangents[ v * 4 ] = tmp.x;
14196                         tangents[ v * 4 + 1 ] = tmp.y;
14197                         tangents[ v * 4 + 2 ] = tmp.z;
14198                         tangents[ v * 4 + 3 ] = w;
14199
14200                 }
14201
14202                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
14203
14204                         const group = groups[ i ];
14205
14206                         const start = group.start;
14207                         const count = group.count;
14208
14209                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
14210
14211                                 handleVertex( indices[ j + 0 ] );
14212                                 handleVertex( indices[ j + 1 ] );
14213                                 handleVertex( indices[ j + 2 ] );
14214
14215                         }
14216
14217                 }
14218
14219         },
14220
14221         computeVertexNormals: function () {
14222
14223                 const index = this.index;
14224                 const positionAttribute = this.getAttribute( 'position' );
14225
14226                 if ( positionAttribute !== undefined ) {
14227
14228                         let normalAttribute = this.getAttribute( 'normal' );
14229
14230                         if ( normalAttribute === undefined ) {
14231
14232                                 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
14233                                 this.setAttribute( 'normal', normalAttribute );
14234
14235                         } else {
14236
14237                                 // reset existing normals to zero
14238
14239                                 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
14240
14241                                         normalAttribute.setXYZ( i, 0, 0, 0 );
14242
14243                                 }
14244
14245                         }
14246
14247                         const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
14248                         const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
14249                         const cb = new Vector3(), ab = new Vector3();
14250
14251                         // indexed elements
14252
14253                         if ( index ) {
14254
14255                                 for ( let i = 0, il = index.count; i < il; i += 3 ) {
14256
14257                                         const vA = index.getX( i + 0 );
14258                                         const vB = index.getX( i + 1 );
14259                                         const vC = index.getX( i + 2 );
14260
14261                                         pA.fromBufferAttribute( positionAttribute, vA );
14262                                         pB.fromBufferAttribute( positionAttribute, vB );
14263                                         pC.fromBufferAttribute( positionAttribute, vC );
14264
14265                                         cb.subVectors( pC, pB );
14266                                         ab.subVectors( pA, pB );
14267                                         cb.cross( ab );
14268
14269                                         nA.fromBufferAttribute( normalAttribute, vA );
14270                                         nB.fromBufferAttribute( normalAttribute, vB );
14271                                         nC.fromBufferAttribute( normalAttribute, vC );
14272
14273                                         nA.add( cb );
14274                                         nB.add( cb );
14275                                         nC.add( cb );
14276
14277                                         normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
14278                                         normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
14279                                         normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
14280
14281                                 }
14282
14283                         } else {
14284
14285                                 // non-indexed elements (unconnected triangle soup)
14286
14287                                 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
14288
14289                                         pA.fromBufferAttribute( positionAttribute, i + 0 );
14290                                         pB.fromBufferAttribute( positionAttribute, i + 1 );
14291                                         pC.fromBufferAttribute( positionAttribute, i + 2 );
14292
14293                                         cb.subVectors( pC, pB );
14294                                         ab.subVectors( pA, pB );
14295                                         cb.cross( ab );
14296
14297                                         normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
14298                                         normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
14299                                         normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
14300
14301                                 }
14302
14303                         }
14304
14305                         this.normalizeNormals();
14306
14307                         normalAttribute.needsUpdate = true;
14308
14309                 }
14310
14311         },
14312
14313         merge: function ( geometry, offset ) {
14314
14315                 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
14316
14317                         console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
14318                         return;
14319
14320                 }
14321
14322                 if ( offset === undefined ) {
14323
14324                         offset = 0;
14325
14326                         console.warn(
14327                                 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
14328                                 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
14329                         );
14330
14331                 }
14332
14333                 const attributes = this.attributes;
14334
14335                 for ( const key in attributes ) {
14336
14337                         if ( geometry.attributes[ key ] === undefined ) continue;
14338
14339                         const attribute1 = attributes[ key ];
14340                         const attributeArray1 = attribute1.array;
14341
14342                         const attribute2 = geometry.attributes[ key ];
14343                         const attributeArray2 = attribute2.array;
14344
14345                         const attributeOffset = attribute2.itemSize * offset;
14346                         const length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
14347
14348                         for ( let i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
14349
14350                                 attributeArray1[ j ] = attributeArray2[ i ];
14351
14352                         }
14353
14354                 }
14355
14356                 return this;
14357
14358         },
14359
14360         normalizeNormals: function () {
14361
14362                 const normals = this.attributes.normal;
14363
14364                 for ( let i = 0, il = normals.count; i < il; i ++ ) {
14365
14366                         _vector$4.fromBufferAttribute( normals, i );
14367
14368                         _vector$4.normalize();
14369
14370                         normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
14371
14372                 }
14373
14374         },
14375
14376         toNonIndexed: function () {
14377
14378                 function convertBufferAttribute( attribute, indices ) {
14379
14380                         const array = attribute.array;
14381                         const itemSize = attribute.itemSize;
14382                         const normalized = attribute.normalized;
14383
14384                         const array2 = new array.constructor( indices.length * itemSize );
14385
14386                         let index = 0, index2 = 0;
14387
14388                         for ( let i = 0, l = indices.length; i < l; i ++ ) {
14389
14390                                 index = indices[ i ] * itemSize;
14391
14392                                 for ( let j = 0; j < itemSize; j ++ ) {
14393
14394                                         array2[ index2 ++ ] = array[ index ++ ];
14395
14396                                 }
14397
14398                         }
14399
14400                         return new BufferAttribute( array2, itemSize, normalized );
14401
14402                 }
14403
14404                 //
14405
14406                 if ( this.index === null ) {
14407
14408                         console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
14409                         return this;
14410
14411                 }
14412
14413                 const geometry2 = new BufferGeometry();
14414
14415                 const indices = this.index.array;
14416                 const attributes = this.attributes;
14417
14418                 // attributes
14419
14420                 for ( const name in attributes ) {
14421
14422                         const attribute = attributes[ name ];
14423
14424                         const newAttribute = convertBufferAttribute( attribute, indices );
14425
14426                         geometry2.setAttribute( name, newAttribute );
14427
14428                 }
14429
14430                 // morph attributes
14431
14432                 const morphAttributes = this.morphAttributes;
14433
14434                 for ( const name in morphAttributes ) {
14435
14436                         const morphArray = [];
14437                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
14438
14439                         for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
14440
14441                                 const attribute = morphAttribute[ i ];
14442
14443                                 const newAttribute = convertBufferAttribute( attribute, indices );
14444
14445                                 morphArray.push( newAttribute );
14446
14447                         }
14448
14449                         geometry2.morphAttributes[ name ] = morphArray;
14450
14451                 }
14452
14453                 geometry2.morphTargetsRelative = this.morphTargetsRelative;
14454
14455                 // groups
14456
14457                 const groups = this.groups;
14458
14459                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
14460
14461                         const group = groups[ i ];
14462                         geometry2.addGroup( group.start, group.count, group.materialIndex );
14463
14464                 }
14465
14466                 return geometry2;
14467
14468         },
14469
14470         toJSON: function () {
14471
14472                 const data = {
14473                         metadata: {
14474                                 version: 4.5,
14475                                 type: 'BufferGeometry',
14476                                 generator: 'BufferGeometry.toJSON'
14477                         }
14478                 };
14479
14480                 // standard BufferGeometry serialization
14481
14482                 data.uuid = this.uuid;
14483                 data.type = this.type;
14484                 if ( this.name !== '' ) data.name = this.name;
14485                 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
14486
14487                 if ( this.parameters !== undefined ) {
14488
14489                         const parameters = this.parameters;
14490
14491                         for ( const key in parameters ) {
14492
14493                                 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
14494
14495                         }
14496
14497                         return data;
14498
14499                 }
14500
14501                 data.data = { attributes: {} };
14502
14503                 const index = this.index;
14504
14505                 if ( index !== null ) {
14506
14507                         data.data.index = {
14508                                 type: index.array.constructor.name,
14509                                 array: Array.prototype.slice.call( index.array )
14510                         };
14511
14512                 }
14513
14514                 const attributes = this.attributes;
14515
14516                 for ( const key in attributes ) {
14517
14518                         const attribute = attributes[ key ];
14519
14520                         const attributeData = attribute.toJSON( data.data );
14521
14522                         if ( attribute.name !== '' ) attributeData.name = attribute.name;
14523
14524                         data.data.attributes[ key ] = attributeData;
14525
14526                 }
14527
14528                 const morphAttributes = {};
14529                 let hasMorphAttributes = false;
14530
14531                 for ( const key in this.morphAttributes ) {
14532
14533                         const attributeArray = this.morphAttributes[ key ];
14534
14535                         const array = [];
14536
14537                         for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
14538
14539                                 const attribute = attributeArray[ i ];
14540
14541                                 const attributeData = attribute.toJSON( data.data );
14542
14543                                 if ( attribute.name !== '' ) attributeData.name = attribute.name;
14544
14545                                 array.push( attributeData );
14546
14547                         }
14548
14549                         if ( array.length > 0 ) {
14550
14551                                 morphAttributes[ key ] = array;
14552
14553                                 hasMorphAttributes = true;
14554
14555                         }
14556
14557                 }
14558
14559                 if ( hasMorphAttributes ) {
14560
14561                         data.data.morphAttributes = morphAttributes;
14562                         data.data.morphTargetsRelative = this.morphTargetsRelative;
14563
14564                 }
14565
14566                 const groups = this.groups;
14567
14568                 if ( groups.length > 0 ) {
14569
14570                         data.data.groups = JSON.parse( JSON.stringify( groups ) );
14571
14572                 }
14573
14574                 const boundingSphere = this.boundingSphere;
14575
14576                 if ( boundingSphere !== null ) {
14577
14578                         data.data.boundingSphere = {
14579                                 center: boundingSphere.center.toArray(),
14580                                 radius: boundingSphere.radius
14581                         };
14582
14583                 }
14584
14585                 return data;
14586
14587         },
14588
14589         clone: function () {
14590
14591                 /*
14592                  // Handle primitives
14593
14594                  const parameters = this.parameters;
14595
14596                  if ( parameters !== undefined ) {
14597
14598                  const values = [];
14599
14600                  for ( const key in parameters ) {
14601
14602                  values.push( parameters[ key ] );
14603
14604                  }
14605
14606                  const geometry = Object.create( this.constructor.prototype );
14607                  this.constructor.apply( geometry, values );
14608                  return geometry;
14609
14610                  }
14611
14612                  return new this.constructor().copy( this );
14613                  */
14614
14615                 return new BufferGeometry().copy( this );
14616
14617         },
14618
14619         copy: function ( source ) {
14620
14621                 // reset
14622
14623                 this.index = null;
14624                 this.attributes = {};
14625                 this.morphAttributes = {};
14626                 this.groups = [];
14627                 this.boundingBox = null;
14628                 this.boundingSphere = null;
14629
14630                 // used for storing cloned, shared data
14631
14632                 const data = {};
14633
14634                 // name
14635
14636                 this.name = source.name;
14637
14638                 // index
14639
14640                 const index = source.index;
14641
14642                 if ( index !== null ) {
14643
14644                         this.setIndex( index.clone( data ) );
14645
14646                 }
14647
14648                 // attributes
14649
14650                 const attributes = source.attributes;
14651
14652                 for ( const name in attributes ) {
14653
14654                         const attribute = attributes[ name ];
14655                         this.setAttribute( name, attribute.clone( data ) );
14656
14657                 }
14658
14659                 // morph attributes
14660
14661                 const morphAttributes = source.morphAttributes;
14662
14663                 for ( const name in morphAttributes ) {
14664
14665                         const array = [];
14666                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
14667
14668                         for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
14669
14670                                 array.push( morphAttribute[ i ].clone( data ) );
14671
14672                         }
14673
14674                         this.morphAttributes[ name ] = array;
14675
14676                 }
14677
14678                 this.morphTargetsRelative = source.morphTargetsRelative;
14679
14680                 // groups
14681
14682                 const groups = source.groups;
14683
14684                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
14685
14686                         const group = groups[ i ];
14687                         this.addGroup( group.start, group.count, group.materialIndex );
14688
14689                 }
14690
14691                 // bounding box
14692
14693                 const boundingBox = source.boundingBox;
14694
14695                 if ( boundingBox !== null ) {
14696
14697                         this.boundingBox = boundingBox.clone();
14698
14699                 }
14700
14701                 // bounding sphere
14702
14703                 const boundingSphere = source.boundingSphere;
14704
14705                 if ( boundingSphere !== null ) {
14706
14707                         this.boundingSphere = boundingSphere.clone();
14708
14709                 }
14710
14711                 // draw range
14712
14713                 this.drawRange.start = source.drawRange.start;
14714                 this.drawRange.count = source.drawRange.count;
14715
14716                 // user data
14717
14718                 this.userData = source.userData;
14719
14720                 return this;
14721
14722         },
14723
14724         dispose: function () {
14725
14726                 this.dispatchEvent( { type: 'dispose' } );
14727
14728         }
14729
14730     } );
14731
14732     const _inverseMatrix = new Matrix4();
14733     const _ray = new Ray();
14734     const _sphere = new Sphere();
14735
14736     const _vA = new Vector3();
14737     const _vB = new Vector3();
14738     const _vC = new Vector3();
14739
14740     const _tempA = new Vector3();
14741     const _tempB = new Vector3();
14742     const _tempC = new Vector3();
14743
14744     const _morphA = new Vector3();
14745     const _morphB = new Vector3();
14746     const _morphC = new Vector3();
14747
14748     const _uvA = new Vector2();
14749     const _uvB = new Vector2();
14750     const _uvC = new Vector2();
14751
14752     const _intersectionPoint = new Vector3();
14753     const _intersectionPointWorld = new Vector3();
14754
14755     function Mesh( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
14756
14757         Object3D.call( this );
14758
14759         this.type = 'Mesh';
14760
14761         this.geometry = geometry;
14762         this.material = material;
14763
14764         this.updateMorphTargets();
14765
14766     }
14767
14768     Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
14769
14770         constructor: Mesh,
14771
14772         isMesh: true,
14773
14774         copy: function ( source ) {
14775
14776                 Object3D.prototype.copy.call( this, source );
14777
14778                 if ( source.morphTargetInfluences !== undefined ) {
14779
14780                         this.morphTargetInfluences = source.morphTargetInfluences.slice();
14781
14782                 }
14783
14784                 if ( source.morphTargetDictionary !== undefined ) {
14785
14786                         this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
14787
14788                 }
14789
14790                 this.material = source.material;
14791                 this.geometry = source.geometry;
14792
14793                 return this;
14794
14795         },
14796
14797         updateMorphTargets: function () {
14798
14799                 const geometry = this.geometry;
14800
14801                 if ( geometry.isBufferGeometry ) {
14802
14803                         const morphAttributes = geometry.morphAttributes;
14804                         const keys = Object.keys( morphAttributes );
14805
14806                         if ( keys.length > 0 ) {
14807
14808                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
14809
14810                                 if ( morphAttribute !== undefined ) {
14811
14812                                         this.morphTargetInfluences = [];
14813                                         this.morphTargetDictionary = {};
14814
14815                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
14816
14817                                                 const name = morphAttribute[ m ].name || String( m );
14818
14819                                                 this.morphTargetInfluences.push( 0 );
14820                                                 this.morphTargetDictionary[ name ] = m;
14821
14822                                         }
14823
14824                                 }
14825
14826                         }
14827
14828                 } else {
14829
14830                         const morphTargets = geometry.morphTargets;
14831
14832                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
14833
14834                                 console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
14835
14836                         }
14837
14838                 }
14839
14840         },
14841
14842         raycast: function ( raycaster, intersects ) {
14843
14844                 const geometry = this.geometry;
14845                 const material = this.material;
14846                 const matrixWorld = this.matrixWorld;
14847
14848                 if ( material === undefined ) return;
14849
14850                 // Checking boundingSphere distance to ray
14851
14852                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14853
14854                 _sphere.copy( geometry.boundingSphere );
14855                 _sphere.applyMatrix4( matrixWorld );
14856
14857                 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
14858
14859                 //
14860
14861                 _inverseMatrix.copy( matrixWorld ).invert();
14862                 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
14863
14864                 // Check boundingBox before continuing
14865
14866                 if ( geometry.boundingBox !== null ) {
14867
14868                         if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
14869
14870                 }
14871
14872                 let intersection;
14873
14874                 if ( geometry.isBufferGeometry ) {
14875
14876                         const index = geometry.index;
14877                         const position = geometry.attributes.position;
14878                         const morphPosition = geometry.morphAttributes.position;
14879                         const morphTargetsRelative = geometry.morphTargetsRelative;
14880                         const uv = geometry.attributes.uv;
14881                         const uv2 = geometry.attributes.uv2;
14882                         const groups = geometry.groups;
14883                         const drawRange = geometry.drawRange;
14884
14885                         if ( index !== null ) {
14886
14887                                 // indexed buffer geometry
14888
14889                                 if ( Array.isArray( material ) ) {
14890
14891                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
14892
14893                                                 const group = groups[ i ];
14894                                                 const groupMaterial = material[ group.materialIndex ];
14895
14896                                                 const start = Math.max( group.start, drawRange.start );
14897                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
14898
14899                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
14900
14901                                                         const a = index.getX( j );
14902                                                         const b = index.getX( j + 1 );
14903                                                         const c = index.getX( j + 2 );
14904
14905                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
14906
14907                                                         if ( intersection ) {
14908
14909                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
14910                                                                 intersection.face.materialIndex = group.materialIndex;
14911                                                                 intersects.push( intersection );
14912
14913                                                         }
14914
14915                                                 }
14916
14917                                         }
14918
14919                                 } else {
14920
14921                                         const start = Math.max( 0, drawRange.start );
14922                                         const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
14923
14924                                         for ( let i = start, il = end; i < il; i += 3 ) {
14925
14926                                                 const a = index.getX( i );
14927                                                 const b = index.getX( i + 1 );
14928                                                 const c = index.getX( i + 2 );
14929
14930                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
14931
14932                                                 if ( intersection ) {
14933
14934                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
14935                                                         intersects.push( intersection );
14936
14937                                                 }
14938
14939                                         }
14940
14941                                 }
14942
14943                         } else if ( position !== undefined ) {
14944
14945                                 // non-indexed buffer geometry
14946
14947                                 if ( Array.isArray( material ) ) {
14948
14949                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
14950
14951                                                 const group = groups[ i ];
14952                                                 const groupMaterial = material[ group.materialIndex ];
14953
14954                                                 const start = Math.max( group.start, drawRange.start );
14955                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
14956
14957                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
14958
14959                                                         const a = j;
14960                                                         const b = j + 1;
14961                                                         const c = j + 2;
14962
14963                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
14964
14965                                                         if ( intersection ) {
14966
14967                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
14968                                                                 intersection.face.materialIndex = group.materialIndex;
14969                                                                 intersects.push( intersection );
14970
14971                                                         }
14972
14973                                                 }
14974
14975                                         }
14976
14977                                 } else {
14978
14979                                         const start = Math.max( 0, drawRange.start );
14980                                         const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
14981
14982                                         for ( let i = start, il = end; i < il; i += 3 ) {
14983
14984                                                 const a = i;
14985                                                 const b = i + 1;
14986                                                 const c = i + 2;
14987
14988                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
14989
14990                                                 if ( intersection ) {
14991
14992                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
14993                                                         intersects.push( intersection );
14994
14995                                                 }
14996
14997                                         }
14998
14999                                 }
15000
15001                         }
15002
15003                 } else if ( geometry.isGeometry ) {
15004
15005                         console.error( 'THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
15006
15007                 }
15008
15009         }
15010
15011     } );
15012
15013     function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
15014
15015         let intersect;
15016
15017         if ( material.side === BackSide ) {
15018
15019                 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
15020
15021         } else {
15022
15023                 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
15024
15025         }
15026
15027         if ( intersect === null ) return null;
15028
15029         _intersectionPointWorld.copy( point );
15030         _intersectionPointWorld.applyMatrix4( object.matrixWorld );
15031
15032         const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
15033
15034         if ( distance < raycaster.near || distance > raycaster.far ) return null;
15035
15036         return {
15037                 distance: distance,
15038                 point: _intersectionPointWorld.clone(),
15039                 object: object
15040         };
15041
15042     }
15043
15044     function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
15045
15046         _vA.fromBufferAttribute( position, a );
15047         _vB.fromBufferAttribute( position, b );
15048         _vC.fromBufferAttribute( position, c );
15049
15050         const morphInfluences = object.morphTargetInfluences;
15051
15052         if ( material.morphTargets && morphPosition && morphInfluences ) {
15053
15054                 _morphA.set( 0, 0, 0 );
15055                 _morphB.set( 0, 0, 0 );
15056                 _morphC.set( 0, 0, 0 );
15057
15058                 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
15059
15060                         const influence = morphInfluences[ i ];
15061                         const morphAttribute = morphPosition[ i ];
15062
15063                         if ( influence === 0 ) continue;
15064
15065                         _tempA.fromBufferAttribute( morphAttribute, a );
15066                         _tempB.fromBufferAttribute( morphAttribute, b );
15067                         _tempC.fromBufferAttribute( morphAttribute, c );
15068
15069                         if ( morphTargetsRelative ) {
15070
15071                                 _morphA.addScaledVector( _tempA, influence );
15072                                 _morphB.addScaledVector( _tempB, influence );
15073                                 _morphC.addScaledVector( _tempC, influence );
15074
15075                         } else {
15076
15077                                 _morphA.addScaledVector( _tempA.sub( _vA ), influence );
15078                                 _morphB.addScaledVector( _tempB.sub( _vB ), influence );
15079                                 _morphC.addScaledVector( _tempC.sub( _vC ), influence );
15080
15081                         }
15082
15083                 }
15084
15085                 _vA.add( _morphA );
15086                 _vB.add( _morphB );
15087                 _vC.add( _morphC );
15088
15089         }
15090
15091         if ( object.isSkinnedMesh ) {
15092
15093                 object.boneTransform( a, _vA );
15094                 object.boneTransform( b, _vB );
15095                 object.boneTransform( c, _vC );
15096
15097         }
15098
15099         const intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
15100
15101         if ( intersection ) {
15102
15103                 if ( uv ) {
15104
15105                         _uvA.fromBufferAttribute( uv, a );
15106                         _uvB.fromBufferAttribute( uv, b );
15107                         _uvC.fromBufferAttribute( uv, c );
15108
15109                         intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
15110
15111                 }
15112
15113                 if ( uv2 ) {
15114
15115                         _uvA.fromBufferAttribute( uv2, a );
15116                         _uvB.fromBufferAttribute( uv2, b );
15117                         _uvC.fromBufferAttribute( uv2, c );
15118
15119                         intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
15120
15121                 }
15122
15123                 const face = new Face3( a, b, c );
15124                 Triangle.getNormal( _vA, _vB, _vC, face.normal );
15125
15126                 intersection.face = face;
15127
15128         }
15129
15130         return intersection;
15131
15132     }
15133
15134     class BoxGeometry extends BufferGeometry {
15135
15136         constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
15137
15138                 super();
15139
15140                 this.type = 'BoxGeometry';
15141
15142                 this.parameters = {
15143                         width: width,
15144                         height: height,
15145                         depth: depth,
15146                         widthSegments: widthSegments,
15147                         heightSegments: heightSegments,
15148                         depthSegments: depthSegments
15149                 };
15150
15151                 const scope = this;
15152
15153                 // segments
15154
15155                 widthSegments = Math.floor( widthSegments );
15156                 heightSegments = Math.floor( heightSegments );
15157                 depthSegments = Math.floor( depthSegments );
15158
15159                 // buffers
15160
15161                 const indices = [];
15162                 const vertices = [];
15163                 const normals = [];
15164                 const uvs = [];
15165
15166                 // helper variables
15167
15168                 let numberOfVertices = 0;
15169                 let groupStart = 0;
15170
15171                 // build each side of the box geometry
15172
15173                 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
15174                 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
15175                 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
15176                 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
15177                 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
15178                 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
15179
15180                 // build geometry
15181
15182                 this.setIndex( indices );
15183                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
15184                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
15185                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
15186
15187                 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
15188
15189                         const segmentWidth = width / gridX;
15190                         const segmentHeight = height / gridY;
15191
15192                         const widthHalf = width / 2;
15193                         const heightHalf = height / 2;
15194                         const depthHalf = depth / 2;
15195
15196                         const gridX1 = gridX + 1;
15197                         const gridY1 = gridY + 1;
15198
15199                         let vertexCounter = 0;
15200                         let groupCount = 0;
15201
15202                         const vector = new Vector3();
15203
15204                         // generate vertices, normals and uvs
15205
15206                         for ( let iy = 0; iy < gridY1; iy ++ ) {
15207
15208                                 const y = iy * segmentHeight - heightHalf;
15209
15210                                 for ( let ix = 0; ix < gridX1; ix ++ ) {
15211
15212                                         const x = ix * segmentWidth - widthHalf;
15213
15214                                         // set values to correct vector component
15215
15216                                         vector[ u ] = x * udir;
15217                                         vector[ v ] = y * vdir;
15218                                         vector[ w ] = depthHalf;
15219
15220                                         // now apply vector to vertex buffer
15221
15222                                         vertices.push( vector.x, vector.y, vector.z );
15223
15224                                         // set values to correct vector component
15225
15226                                         vector[ u ] = 0;
15227                                         vector[ v ] = 0;
15228                                         vector[ w ] = depth > 0 ? 1 : - 1;
15229
15230                                         // now apply vector to normal buffer
15231
15232                                         normals.push( vector.x, vector.y, vector.z );
15233
15234                                         // uvs
15235
15236                                         uvs.push( ix / gridX );
15237                                         uvs.push( 1 - ( iy / gridY ) );
15238
15239                                         // counters
15240
15241                                         vertexCounter += 1;
15242
15243                                 }
15244
15245                         }
15246
15247                         // indices
15248
15249                         // 1. you need three indices to draw a single face
15250                         // 2. a single segment consists of two faces
15251                         // 3. so we need to generate six (2*3) indices per segment
15252
15253                         for ( let iy = 0; iy < gridY; iy ++ ) {
15254
15255                                 for ( let ix = 0; ix < gridX; ix ++ ) {
15256
15257                                         const a = numberOfVertices + ix + gridX1 * iy;
15258                                         const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
15259                                         const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
15260                                         const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
15261
15262                                         // faces
15263
15264                                         indices.push( a, b, d );
15265                                         indices.push( b, c, d );
15266
15267                                         // increase counter
15268
15269                                         groupCount += 6;
15270
15271                                 }
15272
15273                         }
15274
15275                         // add a group to the geometry. this will ensure multi material support
15276
15277                         scope.addGroup( groupStart, groupCount, materialIndex );
15278
15279                         // calculate new start value for groups
15280
15281                         groupStart += groupCount;
15282
15283                         // update total number of vertices
15284
15285                         numberOfVertices += vertexCounter;
15286
15287                 }
15288
15289         }
15290
15291     }
15292
15293     /**
15294      * Uniform Utilities
15295      */
15296
15297     function cloneUniforms( src ) {
15298
15299         const dst = {};
15300
15301         for ( const u in src ) {
15302
15303                 dst[ u ] = {};
15304
15305                 for ( const p in src[ u ] ) {
15306
15307                         const property = src[ u ][ p ];
15308
15309                         if ( property && ( property.isColor ||
15310                                 property.isMatrix3 || property.isMatrix4 ||
15311                                 property.isVector2 || property.isVector3 || property.isVector4 ||
15312                                 property.isTexture ) ) {
15313
15314                                 dst[ u ][ p ] = property.clone();
15315
15316                         } else if ( Array.isArray( property ) ) {
15317
15318                                 dst[ u ][ p ] = property.slice();
15319
15320                         } else {
15321
15322                                 dst[ u ][ p ] = property;
15323
15324                         }
15325
15326                 }
15327
15328         }
15329
15330         return dst;
15331
15332     }
15333
15334     function mergeUniforms( uniforms ) {
15335
15336         const merged = {};
15337
15338         for ( let u = 0; u < uniforms.length; u ++ ) {
15339
15340                 const tmp = cloneUniforms( uniforms[ u ] );
15341
15342                 for ( const p in tmp ) {
15343
15344                         merged[ p ] = tmp[ p ];
15345
15346                 }
15347
15348         }
15349
15350         return merged;
15351
15352     }
15353
15354     // Legacy
15355
15356     const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
15357
15358     var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
15359
15360     var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
15361
15362     /**
15363      * parameters = {
15364      *  defines: { "label" : "value" },
15365      *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
15366      *
15367      *  fragmentShader: <string>,
15368      *  vertexShader: <string>,
15369      *
15370      *  wireframe: <boolean>,
15371      *  wireframeLinewidth: <float>,
15372      *
15373      *  lights: <bool>,
15374      *
15375      *  skinning: <bool>,
15376      *  morphTargets: <bool>,
15377      *  morphNormals: <bool>
15378      * }
15379      */
15380
15381     function ShaderMaterial( parameters ) {
15382
15383         Material.call( this );
15384
15385         this.type = 'ShaderMaterial';
15386
15387         this.defines = {};
15388         this.uniforms = {};
15389
15390         this.vertexShader = default_vertex;
15391         this.fragmentShader = default_fragment;
15392
15393         this.linewidth = 1;
15394
15395         this.wireframe = false;
15396         this.wireframeLinewidth = 1;
15397
15398         this.fog = false; // set to use scene fog
15399         this.lights = false; // set to use scene lights
15400         this.clipping = false; // set to use user-defined clipping planes
15401
15402         this.skinning = false; // set to use skinning attribute streams
15403         this.morphTargets = false; // set to use morph targets
15404         this.morphNormals = false; // set to use morph normals
15405
15406         this.extensions = {
15407                 derivatives: false, // set to use derivatives
15408                 fragDepth: false, // set to use fragment depth values
15409                 drawBuffers: false, // set to use draw buffers
15410                 shaderTextureLOD: false // set to use shader texture LOD
15411         };
15412
15413         // When rendered geometry doesn't include these attributes but the material does,
15414         // use these default values in WebGL. This avoids errors when buffer data is missing.
15415         this.defaultAttributeValues = {
15416                 'color': [ 1, 1, 1 ],
15417                 'uv': [ 0, 0 ],
15418                 'uv2': [ 0, 0 ]
15419         };
15420
15421         this.index0AttributeName = undefined;
15422         this.uniformsNeedUpdate = false;
15423
15424         this.glslVersion = null;
15425
15426         if ( parameters !== undefined ) {
15427
15428                 if ( parameters.attributes !== undefined ) {
15429
15430                         console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
15431
15432                 }
15433
15434                 this.setValues( parameters );
15435
15436         }
15437
15438     }
15439
15440     ShaderMaterial.prototype = Object.create( Material.prototype );
15441     ShaderMaterial.prototype.constructor = ShaderMaterial;
15442
15443     ShaderMaterial.prototype.isShaderMaterial = true;
15444
15445     ShaderMaterial.prototype.copy = function ( source ) {
15446
15447         Material.prototype.copy.call( this, source );
15448
15449         this.fragmentShader = source.fragmentShader;
15450         this.vertexShader = source.vertexShader;
15451
15452         this.uniforms = cloneUniforms( source.uniforms );
15453
15454         this.defines = Object.assign( {}, source.defines );
15455
15456         this.wireframe = source.wireframe;
15457         this.wireframeLinewidth = source.wireframeLinewidth;
15458
15459         this.lights = source.lights;
15460         this.clipping = source.clipping;
15461
15462         this.skinning = source.skinning;
15463
15464         this.morphTargets = source.morphTargets;
15465         this.morphNormals = source.morphNormals;
15466
15467         this.extensions = Object.assign( {}, source.extensions );
15468
15469         this.glslVersion = source.glslVersion;
15470
15471         return this;
15472
15473     };
15474
15475     ShaderMaterial.prototype.toJSON = function ( meta ) {
15476
15477         const data = Material.prototype.toJSON.call( this, meta );
15478
15479         data.glslVersion = this.glslVersion;
15480         data.uniforms = {};
15481
15482         for ( const name in this.uniforms ) {
15483
15484                 const uniform = this.uniforms[ name ];
15485                 const value = uniform.value;
15486
15487                 if ( value && value.isTexture ) {
15488
15489                         data.uniforms[ name ] = {
15490                                 type: 't',
15491                                 value: value.toJSON( meta ).uuid
15492                         };
15493
15494                 } else if ( value && value.isColor ) {
15495
15496                         data.uniforms[ name ] = {
15497                                 type: 'c',
15498                                 value: value.getHex()
15499                         };
15500
15501                 } else if ( value && value.isVector2 ) {
15502
15503                         data.uniforms[ name ] = {
15504                                 type: 'v2',
15505                                 value: value.toArray()
15506                         };
15507
15508                 } else if ( value && value.isVector3 ) {
15509
15510                         data.uniforms[ name ] = {
15511                                 type: 'v3',
15512                                 value: value.toArray()
15513                         };
15514
15515                 } else if ( value && value.isVector4 ) {
15516
15517                         data.uniforms[ name ] = {
15518                                 type: 'v4',
15519                                 value: value.toArray()
15520                         };
15521
15522                 } else if ( value && value.isMatrix3 ) {
15523
15524                         data.uniforms[ name ] = {
15525                                 type: 'm3',
15526                                 value: value.toArray()
15527                         };
15528
15529                 } else if ( value && value.isMatrix4 ) {
15530
15531                         data.uniforms[ name ] = {
15532                                 type: 'm4',
15533                                 value: value.toArray()
15534                         };
15535
15536                 } else {
15537
15538                         data.uniforms[ name ] = {
15539                                 value: value
15540                         };
15541
15542                         // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
15543
15544                 }
15545
15546         }
15547
15548         if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
15549
15550         data.vertexShader = this.vertexShader;
15551         data.fragmentShader = this.fragmentShader;
15552
15553         const extensions = {};
15554
15555         for ( const key in this.extensions ) {
15556
15557                 if ( this.extensions[ key ] === true ) extensions[ key ] = true;
15558
15559         }
15560
15561         if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
15562
15563         return data;
15564
15565     };
15566
15567     function Camera$1() {
15568
15569         Object3D.call( this );
15570
15571         this.type = 'Camera';
15572
15573         this.matrixWorldInverse = new Matrix4();
15574
15575         this.projectionMatrix = new Matrix4();
15576         this.projectionMatrixInverse = new Matrix4();
15577
15578     }
15579
15580     Camera$1.prototype = Object.assign( Object.create( Object3D.prototype ), {
15581
15582         constructor: Camera$1,
15583
15584         isCamera: true,
15585
15586         copy: function ( source, recursive ) {
15587
15588                 Object3D.prototype.copy.call( this, source, recursive );
15589
15590                 this.matrixWorldInverse.copy( source.matrixWorldInverse );
15591
15592                 this.projectionMatrix.copy( source.projectionMatrix );
15593                 this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
15594
15595                 return this;
15596
15597         },
15598
15599         getWorldDirection: function ( target ) {
15600
15601                 if ( target === undefined ) {
15602
15603                         console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
15604                         target = new Vector3();
15605
15606                 }
15607
15608                 this.updateWorldMatrix( true, false );
15609
15610                 const e = this.matrixWorld.elements;
15611
15612                 return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
15613
15614         },
15615
15616         updateMatrixWorld: function ( force ) {
15617
15618                 Object3D.prototype.updateMatrixWorld.call( this, force );
15619
15620                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
15621
15622         },
15623
15624         updateWorldMatrix: function ( updateParents, updateChildren ) {
15625
15626                 Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );
15627
15628                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
15629
15630         },
15631
15632         clone: function () {
15633
15634                 return new this.constructor().copy( this );
15635
15636         }
15637
15638     } );
15639
15640     function PerspectiveCamera( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
15641
15642         Camera$1.call( this );
15643
15644         this.type = 'PerspectiveCamera';
15645
15646         this.fov = fov;
15647         this.zoom = 1;
15648
15649         this.near = near;
15650         this.far = far;
15651         this.focus = 10;
15652
15653         this.aspect = aspect;
15654         this.view = null;
15655
15656         this.filmGauge = 35;    // width of the film (default in millimeters)
15657         this.filmOffset = 0;    // horizontal film offset (same unit as gauge)
15658
15659         this.updateProjectionMatrix();
15660
15661     }
15662
15663     PerspectiveCamera.prototype = Object.assign( Object.create( Camera$1.prototype ), {
15664
15665         constructor: PerspectiveCamera,
15666
15667         isPerspectiveCamera: true,
15668
15669         copy: function ( source, recursive ) {
15670
15671                 Camera$1.prototype.copy.call( this, source, recursive );
15672
15673                 this.fov = source.fov;
15674                 this.zoom = source.zoom;
15675
15676                 this.near = source.near;
15677                 this.far = source.far;
15678                 this.focus = source.focus;
15679
15680                 this.aspect = source.aspect;
15681                 this.view = source.view === null ? null : Object.assign( {}, source.view );
15682
15683                 this.filmGauge = source.filmGauge;
15684                 this.filmOffset = source.filmOffset;
15685
15686                 return this;
15687
15688         },
15689
15690         /**
15691          * Sets the FOV by focal length in respect to the current .filmGauge.
15692          *
15693          * The default film gauge is 35, so that the focal length can be specified for
15694          * a 35mm (full frame) camera.
15695          *
15696          * Values for focal length and film gauge must have the same unit.
15697          */
15698         setFocalLength: function ( focalLength ) {
15699
15700                 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
15701                 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
15702
15703                 this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );
15704                 this.updateProjectionMatrix();
15705
15706         },
15707
15708         /**
15709          * Calculates the focal length from the current .fov and .filmGauge.
15710          */
15711         getFocalLength: function () {
15712
15713                 const vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );
15714
15715                 return 0.5 * this.getFilmHeight() / vExtentSlope;
15716
15717         },
15718
15719         getEffectiveFOV: function () {
15720
15721                 return MathUtils.RAD2DEG * 2 * Math.atan(
15722                         Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );
15723
15724         },
15725
15726         getFilmWidth: function () {
15727
15728                 // film not completely covered in portrait format (aspect < 1)
15729                 return this.filmGauge * Math.min( this.aspect, 1 );
15730
15731         },
15732
15733         getFilmHeight: function () {
15734
15735                 // film not completely covered in landscape format (aspect > 1)
15736                 return this.filmGauge / Math.max( this.aspect, 1 );
15737
15738         },
15739
15740         /**
15741          * Sets an offset in a larger frustum. This is useful for multi-window or
15742          * multi-monitor/multi-machine setups.
15743          *
15744          * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
15745          * the monitors are in grid like this
15746          *
15747          *   +---+---+---+
15748          *   | A | B | C |
15749          *   +---+---+---+
15750          *   | D | E | F |
15751          *   +---+---+---+
15752          *
15753          * then for each monitor you would call it like this
15754          *
15755          *   const w = 1920;
15756          *   const h = 1080;
15757          *   const fullWidth = w * 3;
15758          *   const fullHeight = h * 2;
15759          *
15760          *   --A--
15761          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
15762          *   --B--
15763          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
15764          *   --C--
15765          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
15766          *   --D--
15767          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
15768          *   --E--
15769          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
15770          *   --F--
15771          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
15772          *
15773          *   Note there is no reason monitors have to be the same size or in a grid.
15774          */
15775         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
15776
15777                 this.aspect = fullWidth / fullHeight;
15778
15779                 if ( this.view === null ) {
15780
15781                         this.view = {
15782                                 enabled: true,
15783                                 fullWidth: 1,
15784                                 fullHeight: 1,
15785                                 offsetX: 0,
15786                                 offsetY: 0,
15787                                 width: 1,
15788                                 height: 1
15789                         };
15790
15791                 }
15792
15793                 this.view.enabled = true;
15794                 this.view.fullWidth = fullWidth;
15795                 this.view.fullHeight = fullHeight;
15796                 this.view.offsetX = x;
15797                 this.view.offsetY = y;
15798                 this.view.width = width;
15799                 this.view.height = height;
15800
15801                 this.updateProjectionMatrix();
15802
15803         },
15804
15805         clearViewOffset: function () {
15806
15807                 if ( this.view !== null ) {
15808
15809                         this.view.enabled = false;
15810
15811                 }
15812
15813                 this.updateProjectionMatrix();
15814
15815         },
15816
15817         updateProjectionMatrix: function () {
15818
15819                 const near = this.near;
15820                 let top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom;
15821                 let height = 2 * top;
15822                 let width = this.aspect * height;
15823                 let left = - 0.5 * width;
15824                 const view = this.view;
15825
15826                 if ( this.view !== null && this.view.enabled ) {
15827
15828                         const fullWidth = view.fullWidth,
15829                                 fullHeight = view.fullHeight;
15830
15831                         left += view.offsetX * width / fullWidth;
15832                         top -= view.offsetY * height / fullHeight;
15833                         width *= view.width / fullWidth;
15834                         height *= view.height / fullHeight;
15835
15836                 }
15837
15838                 const skew = this.filmOffset;
15839                 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
15840
15841                 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
15842
15843                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
15844
15845         },
15846
15847         toJSON: function ( meta ) {
15848
15849                 const data = Object3D.prototype.toJSON.call( this, meta );
15850
15851                 data.object.fov = this.fov;
15852                 data.object.zoom = this.zoom;
15853
15854                 data.object.near = this.near;
15855                 data.object.far = this.far;
15856                 data.object.focus = this.focus;
15857
15858                 data.object.aspect = this.aspect;
15859
15860                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
15861
15862                 data.object.filmGauge = this.filmGauge;
15863                 data.object.filmOffset = this.filmOffset;
15864
15865                 return data;
15866
15867         }
15868
15869     } );
15870
15871     const fov = 90, aspect = 1;
15872
15873     function CubeCamera( near, far, renderTarget ) {
15874
15875         Object3D.call( this );
15876
15877         this.type = 'CubeCamera';
15878
15879         if ( renderTarget.isWebGLCubeRenderTarget !== true ) {
15880
15881                 console.error( 'THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.' );
15882                 return;
15883
15884         }
15885
15886         this.renderTarget = renderTarget;
15887
15888         const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
15889         cameraPX.layers = this.layers;
15890         cameraPX.up.set( 0, - 1, 0 );
15891         cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
15892         this.add( cameraPX );
15893
15894         const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
15895         cameraNX.layers = this.layers;
15896         cameraNX.up.set( 0, - 1, 0 );
15897         cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
15898         this.add( cameraNX );
15899
15900         const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
15901         cameraPY.layers = this.layers;
15902         cameraPY.up.set( 0, 0, 1 );
15903         cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
15904         this.add( cameraPY );
15905
15906         const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
15907         cameraNY.layers = this.layers;
15908         cameraNY.up.set( 0, 0, - 1 );
15909         cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
15910         this.add( cameraNY );
15911
15912         const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
15913         cameraPZ.layers = this.layers;
15914         cameraPZ.up.set( 0, - 1, 0 );
15915         cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
15916         this.add( cameraPZ );
15917
15918         const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
15919         cameraNZ.layers = this.layers;
15920         cameraNZ.up.set( 0, - 1, 0 );
15921         cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
15922         this.add( cameraNZ );
15923
15924         this.update = function ( renderer, scene ) {
15925
15926                 if ( this.parent === null ) this.updateMatrixWorld();
15927
15928                 const currentXrEnabled = renderer.xr.enabled;
15929                 const currentRenderTarget = renderer.getRenderTarget();
15930
15931                 renderer.xr.enabled = false;
15932
15933                 const generateMipmaps = renderTarget.texture.generateMipmaps;
15934
15935                 renderTarget.texture.generateMipmaps = false;
15936
15937                 renderer.setRenderTarget( renderTarget, 0 );
15938                 renderer.render( scene, cameraPX );
15939
15940                 renderer.setRenderTarget( renderTarget, 1 );
15941                 renderer.render( scene, cameraNX );
15942
15943                 renderer.setRenderTarget( renderTarget, 2 );
15944                 renderer.render( scene, cameraPY );
15945
15946                 renderer.setRenderTarget( renderTarget, 3 );
15947                 renderer.render( scene, cameraNY );
15948
15949                 renderer.setRenderTarget( renderTarget, 4 );
15950                 renderer.render( scene, cameraPZ );
15951
15952                 renderTarget.texture.generateMipmaps = generateMipmaps;
15953
15954                 renderer.setRenderTarget( renderTarget, 5 );
15955                 renderer.render( scene, cameraNZ );
15956
15957                 renderer.setRenderTarget( currentRenderTarget );
15958
15959                 renderer.xr.enabled = currentXrEnabled;
15960
15961         };
15962
15963     }
15964
15965     CubeCamera.prototype = Object.create( Object3D.prototype );
15966     CubeCamera.prototype.constructor = CubeCamera;
15967
15968     function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
15969
15970         images = images !== undefined ? images : [];
15971         mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
15972         format = format !== undefined ? format : RGBFormat;
15973
15974         Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
15975
15976         this.flipY = false;
15977
15978         // Why CubeTexture._needsFlipEnvMap is necessary:
15979         //
15980         // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
15981         // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
15982         // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
15983
15984         // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
15985         // and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
15986         // when using WebGLCubeRenderTarget.texture as a cube texture.
15987
15988         this._needsFlipEnvMap = true;
15989
15990     }
15991
15992     CubeTexture.prototype = Object.create( Texture.prototype );
15993     CubeTexture.prototype.constructor = CubeTexture;
15994
15995     CubeTexture.prototype.isCubeTexture = true;
15996
15997     Object.defineProperty( CubeTexture.prototype, 'images', {
15998
15999         get: function () {
16000
16001                 return this.image;
16002
16003         },
16004
16005         set: function ( value ) {
16006
16007                 this.image = value;
16008
16009         }
16010
16011     } );
16012
16013     class WebGLCubeRenderTarget extends WebGLRenderTarget {
16014
16015         constructor( size, options, dummy ) {
16016
16017                 if ( Number.isInteger( options ) ) {
16018
16019                         console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
16020
16021                         options = dummy;
16022
16023                 }
16024
16025                 super( size, size, options );
16026
16027                 Object.defineProperty( this, 'isWebGLCubeRenderTarget', { value: true } );
16028
16029                 options = options || {};
16030
16031                 this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
16032
16033                 this.texture._needsFlipEnvMap = false;
16034
16035         }
16036
16037         fromEquirectangularTexture( renderer, texture ) {
16038
16039                 this.texture.type = texture.type;
16040                 this.texture.format = RGBAFormat; // see #18859
16041                 this.texture.encoding = texture.encoding;
16042
16043                 this.texture.generateMipmaps = texture.generateMipmaps;
16044                 this.texture.minFilter = texture.minFilter;
16045                 this.texture.magFilter = texture.magFilter;
16046
16047                 const shader = {
16048
16049                         uniforms: {
16050                                 tEquirect: { value: null },
16051                         },
16052
16053                         vertexShader: /* glsl */`
16054
16055                                 varying vec3 vWorldDirection;
16056
16057                                 vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
16058
16059                                         return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
16060
16061                                 }
16062
16063                                 void main() {
16064
16065                                         vWorldDirection = transformDirection( position, modelMatrix );
16066
16067                                         #include <begin_vertex>
16068                                         #include <project_vertex>
16069
16070                                 }
16071                         `,
16072
16073                         fragmentShader: /* glsl */`
16074
16075                                 uniform sampler2D tEquirect;
16076
16077                                 varying vec3 vWorldDirection;
16078
16079                                 #include <common>
16080
16081                                 void main() {
16082
16083                                         vec3 direction = normalize( vWorldDirection );
16084
16085                                         vec2 sampleUV = equirectUv( direction );
16086
16087                                         gl_FragColor = texture2D( tEquirect, sampleUV );
16088
16089                                 }
16090                         `
16091                 };
16092
16093                 const geometry = new BoxGeometry( 5, 5, 5 );
16094
16095                 const material = new ShaderMaterial( {
16096
16097                         name: 'CubemapFromEquirect',
16098
16099                         uniforms: cloneUniforms( shader.uniforms ),
16100                         vertexShader: shader.vertexShader,
16101                         fragmentShader: shader.fragmentShader,
16102                         side: BackSide,
16103                         blending: NoBlending
16104
16105                 } );
16106
16107                 material.uniforms.tEquirect.value = texture;
16108
16109                 const mesh = new Mesh( geometry, material );
16110
16111                 const currentMinFilter = texture.minFilter;
16112
16113                 // Avoid blurred poles
16114                 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
16115
16116                 const camera = new CubeCamera( 1, 10, this );
16117                 camera.update( renderer, mesh );
16118
16119                 texture.minFilter = currentMinFilter;
16120
16121                 mesh.geometry.dispose();
16122                 mesh.material.dispose();
16123
16124                 return this;
16125
16126         }
16127
16128         clear( renderer, color, depth, stencil ) {
16129
16130                 const currentRenderTarget = renderer.getRenderTarget();
16131
16132                 for ( let i = 0; i < 6; i ++ ) {
16133
16134                         renderer.setRenderTarget( this, i );
16135
16136                         renderer.clear( color, depth, stencil );
16137
16138                 }
16139
16140                 renderer.setRenderTarget( currentRenderTarget );
16141
16142         }
16143
16144     }
16145
16146     function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
16147
16148         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
16149
16150         this.image = { data: data || null, width: width || 1, height: height || 1 };
16151
16152         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
16153         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
16154
16155         this.generateMipmaps = false;
16156         this.flipY = false;
16157         this.unpackAlignment = 1;
16158
16159         this.needsUpdate = true;
16160
16161     }
16162
16163     DataTexture.prototype = Object.create( Texture.prototype );
16164     DataTexture.prototype.constructor = DataTexture;
16165
16166     DataTexture.prototype.isDataTexture = true;
16167
16168     const _sphere$1 = /*@__PURE__*/ new Sphere();
16169     const _vector$5 = /*@__PURE__*/ new Vector3();
16170
16171     class Frustum {
16172
16173         constructor( p0, p1, p2, p3, p4, p5 ) {
16174
16175                 this.planes = [
16176
16177                         ( p0 !== undefined ) ? p0 : new Plane(),
16178                         ( p1 !== undefined ) ? p1 : new Plane(),
16179                         ( p2 !== undefined ) ? p2 : new Plane(),
16180                         ( p3 !== undefined ) ? p3 : new Plane(),
16181                         ( p4 !== undefined ) ? p4 : new Plane(),
16182                         ( p5 !== undefined ) ? p5 : new Plane()
16183
16184                 ];
16185
16186         }
16187
16188         set( p0, p1, p2, p3, p4, p5 ) {
16189
16190                 const planes = this.planes;
16191
16192                 planes[ 0 ].copy( p0 );
16193                 planes[ 1 ].copy( p1 );
16194                 planes[ 2 ].copy( p2 );
16195                 planes[ 3 ].copy( p3 );
16196                 planes[ 4 ].copy( p4 );
16197                 planes[ 5 ].copy( p5 );
16198
16199                 return this;
16200
16201         }
16202
16203         clone() {
16204
16205                 return new this.constructor().copy( this );
16206
16207         }
16208
16209         copy( frustum ) {
16210
16211                 const planes = this.planes;
16212
16213                 for ( let i = 0; i < 6; i ++ ) {
16214
16215                         planes[ i ].copy( frustum.planes[ i ] );
16216
16217                 }
16218
16219                 return this;
16220
16221         }
16222
16223         setFromProjectionMatrix( m ) {
16224
16225                 const planes = this.planes;
16226                 const me = m.elements;
16227                 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
16228                 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
16229                 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
16230                 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
16231
16232                 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
16233                 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
16234                 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
16235                 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
16236                 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
16237                 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
16238
16239                 return this;
16240
16241         }
16242
16243         intersectsObject( object ) {
16244
16245                 const geometry = object.geometry;
16246
16247                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
16248
16249                 _sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
16250
16251                 return this.intersectsSphere( _sphere$1 );
16252
16253         }
16254
16255         intersectsSprite( sprite ) {
16256
16257                 _sphere$1.center.set( 0, 0, 0 );
16258                 _sphere$1.radius = 0.7071067811865476;
16259                 _sphere$1.applyMatrix4( sprite.matrixWorld );
16260
16261                 return this.intersectsSphere( _sphere$1 );
16262
16263         }
16264
16265         intersectsSphere( sphere ) {
16266
16267                 const planes = this.planes;
16268                 const center = sphere.center;
16269                 const negRadius = - sphere.radius;
16270
16271                 for ( let i = 0; i < 6; i ++ ) {
16272
16273                         const distance = planes[ i ].distanceToPoint( center );
16274
16275                         if ( distance < negRadius ) {
16276
16277                                 return false;
16278
16279                         }
16280
16281                 }
16282
16283                 return true;
16284
16285         }
16286
16287         intersectsBox( box ) {
16288
16289                 const planes = this.planes;
16290
16291                 for ( let i = 0; i < 6; i ++ ) {
16292
16293                         const plane = planes[ i ];
16294
16295                         // corner at max distance
16296
16297                         _vector$5.x = plane.normal.x > 0 ? box.max.x : box.min.x;
16298                         _vector$5.y = plane.normal.y > 0 ? box.max.y : box.min.y;
16299                         _vector$5.z = plane.normal.z > 0 ? box.max.z : box.min.z;
16300
16301                         if ( plane.distanceToPoint( _vector$5 ) < 0 ) {
16302
16303                                 return false;
16304
16305                         }
16306
16307                 }
16308
16309                 return true;
16310
16311         }
16312
16313         containsPoint( point ) {
16314
16315                 const planes = this.planes;
16316
16317                 for ( let i = 0; i < 6; i ++ ) {
16318
16319                         if ( planes[ i ].distanceToPoint( point ) < 0 ) {
16320
16321                                 return false;
16322
16323                         }
16324
16325                 }
16326
16327                 return true;
16328
16329         }
16330
16331     }
16332
16333     function WebGLAnimation() {
16334
16335         let context = null;
16336         let isAnimating = false;
16337         let animationLoop = null;
16338         let requestId = null;
16339
16340         function onAnimationFrame( time, frame ) {
16341
16342                 animationLoop( time, frame );
16343
16344                 requestId = context.requestAnimationFrame( onAnimationFrame );
16345
16346         }
16347
16348         return {
16349
16350                 start: function () {
16351
16352                         if ( isAnimating === true ) return;
16353                         if ( animationLoop === null ) return;
16354
16355                         requestId = context.requestAnimationFrame( onAnimationFrame );
16356
16357                         isAnimating = true;
16358
16359                 },
16360
16361                 stop: function () {
16362
16363                         context.cancelAnimationFrame( requestId );
16364
16365                         isAnimating = false;
16366
16367                 },
16368
16369                 setAnimationLoop: function ( callback ) {
16370
16371                         animationLoop = callback;
16372
16373                 },
16374
16375                 setContext: function ( value ) {
16376
16377                         context = value;
16378
16379                 }
16380
16381         };
16382
16383     }
16384
16385     function WebGLAttributes( gl, capabilities ) {
16386
16387         const isWebGL2 = capabilities.isWebGL2;
16388
16389         const buffers = new WeakMap();
16390
16391         function createBuffer( attribute, bufferType ) {
16392
16393                 const array = attribute.array;
16394                 const usage = attribute.usage;
16395
16396                 const buffer = gl.createBuffer();
16397
16398                 gl.bindBuffer( bufferType, buffer );
16399                 gl.bufferData( bufferType, array, usage );
16400
16401                 attribute.onUploadCallback();
16402
16403                 let type = 5126;
16404
16405                 if ( array instanceof Float32Array ) {
16406
16407                         type = 5126;
16408
16409                 } else if ( array instanceof Float64Array ) {
16410
16411                         console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
16412
16413                 } else if ( array instanceof Uint16Array ) {
16414
16415                         if ( attribute.isFloat16BufferAttribute ) {
16416
16417                                 if ( isWebGL2 ) {
16418
16419                                         type = 5131;
16420
16421                                 } else {
16422
16423                                         console.warn( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
16424
16425                                 }
16426
16427                         } else {
16428
16429                                 type = 5123;
16430
16431                         }
16432
16433                 } else if ( array instanceof Int16Array ) {
16434
16435                         type = 5122;
16436
16437                 } else if ( array instanceof Uint32Array ) {
16438
16439                         type = 5125;
16440
16441                 } else if ( array instanceof Int32Array ) {
16442
16443                         type = 5124;
16444
16445                 } else if ( array instanceof Int8Array ) {
16446
16447                         type = 5120;
16448
16449                 } else if ( array instanceof Uint8Array ) {
16450
16451                         type = 5121;
16452
16453                 }
16454
16455                 return {
16456                         buffer: buffer,
16457                         type: type,
16458                         bytesPerElement: array.BYTES_PER_ELEMENT,
16459                         version: attribute.version
16460                 };
16461
16462         }
16463
16464         function updateBuffer( buffer, attribute, bufferType ) {
16465
16466                 const array = attribute.array;
16467                 const updateRange = attribute.updateRange;
16468
16469                 gl.bindBuffer( bufferType, buffer );
16470
16471                 if ( updateRange.count === - 1 ) {
16472
16473                         // Not using update ranges
16474
16475                         gl.bufferSubData( bufferType, 0, array );
16476
16477                 } else {
16478
16479                         if ( isWebGL2 ) {
16480
16481                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
16482                                         array, updateRange.offset, updateRange.count );
16483
16484                         } else {
16485
16486                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
16487                                         array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
16488
16489                         }
16490
16491                         updateRange.count = - 1; // reset range
16492
16493                 }
16494
16495         }
16496
16497         //
16498
16499         function get( attribute ) {
16500
16501                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
16502
16503                 return buffers.get( attribute );
16504
16505         }
16506
16507         function remove( attribute ) {
16508
16509                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
16510
16511                 const data = buffers.get( attribute );
16512
16513                 if ( data ) {
16514
16515                         gl.deleteBuffer( data.buffer );
16516
16517                         buffers.delete( attribute );
16518
16519                 }
16520
16521         }
16522
16523         function update( attribute, bufferType ) {
16524
16525                 if ( attribute.isGLBufferAttribute ) {
16526
16527                         const cached = buffers.get( attribute );
16528
16529                         if ( ! cached || cached.version < attribute.version ) {
16530
16531                                 buffers.set( attribute, {
16532                                         buffer: attribute.buffer,
16533                                         type: attribute.type,
16534                                         bytesPerElement: attribute.elementSize,
16535                                         version: attribute.version
16536                                 } );
16537
16538                         }
16539
16540                         return;
16541
16542                 }
16543
16544                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
16545
16546                 const data = buffers.get( attribute );
16547
16548                 if ( data === undefined ) {
16549
16550                         buffers.set( attribute, createBuffer( attribute, bufferType ) );
16551
16552                 } else if ( data.version < attribute.version ) {
16553
16554                         updateBuffer( data.buffer, attribute, bufferType );
16555
16556                         data.version = attribute.version;
16557
16558                 }
16559
16560         }
16561
16562         return {
16563
16564                 get: get,
16565                 remove: remove,
16566                 update: update
16567
16568         };
16569
16570     }
16571
16572     class PlaneGeometry extends BufferGeometry {
16573
16574         constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
16575
16576                 super();
16577                 this.type = 'PlaneGeometry';
16578
16579                 this.parameters = {
16580                         width: width,
16581                         height: height,
16582                         widthSegments: widthSegments,
16583                         heightSegments: heightSegments
16584                 };
16585
16586                 const width_half = width / 2;
16587                 const height_half = height / 2;
16588
16589                 const gridX = Math.floor( widthSegments );
16590                 const gridY = Math.floor( heightSegments );
16591
16592                 const gridX1 = gridX + 1;
16593                 const gridY1 = gridY + 1;
16594
16595                 const segment_width = width / gridX;
16596                 const segment_height = height / gridY;
16597
16598                 //
16599
16600                 const indices = [];
16601                 const vertices = [];
16602                 const normals = [];
16603                 const uvs = [];
16604
16605                 for ( let iy = 0; iy < gridY1; iy ++ ) {
16606
16607                         const y = iy * segment_height - height_half;
16608
16609                         for ( let ix = 0; ix < gridX1; ix ++ ) {
16610
16611                                 const x = ix * segment_width - width_half;
16612
16613                                 vertices.push( x, - y, 0 );
16614
16615                                 normals.push( 0, 0, 1 );
16616
16617                                 uvs.push( ix / gridX );
16618                                 uvs.push( 1 - ( iy / gridY ) );
16619
16620                         }
16621
16622                 }
16623
16624                 for ( let iy = 0; iy < gridY; iy ++ ) {
16625
16626                         for ( let ix = 0; ix < gridX; ix ++ ) {
16627
16628                                 const a = ix + gridX1 * iy;
16629                                 const b = ix + gridX1 * ( iy + 1 );
16630                                 const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
16631                                 const d = ( ix + 1 ) + gridX1 * iy;
16632
16633                                 indices.push( a, b, d );
16634                                 indices.push( b, c, d );
16635
16636                         }
16637
16638                 }
16639
16640                 this.setIndex( indices );
16641                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
16642                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
16643                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
16644
16645         }
16646
16647     }
16648
16649     var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
16650
16651     var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
16652
16653     var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
16654
16655     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( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif";
16656
16657     var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
16658
16659     var begin_vertex = "vec3 transformed = vec3( position );";
16660
16661     var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
16662
16663     var bsdfs = "vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif";
16664
16665     var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\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";
16666
16667     var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif";
16668
16669     var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
16670
16671     var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
16672
16673     var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
16674
16675     var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
16676
16677     var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
16678
16679     var color_pars_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
16680
16681     var color_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor.xyz *= color.xyz;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
16682
16683     var common$1 = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}";
16684
16685     var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n\t\tvec2 f = fract( uv );\n\t\tuv += 0.5 - f;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\tvec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x += texelSize;\n\t\tvec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.y += texelSize;\n\t\tvec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x -= texelSize;\n\t\tvec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tvec3 tm = mix( tl, tr, f.x );\n\t\tvec3 bm = mix( bl, br, f.x );\n\t\treturn mix( tm, bm, f.y );\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif";
16686
16687     var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
16688
16689     var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
16690
16691     var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
16692
16693     var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
16694
16695     var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
16696
16697     var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
16698
16699     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.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}";
16700
16701     var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
16702
16703     var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif";
16704
16705     var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
16706
16707     var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif";
16708
16709     var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif";
16710
16711     var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = - mvPosition.z;\n#endif";
16712
16713     var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
16714
16715     var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
16716
16717     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";
16718
16719     var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}";
16720
16721     var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";
16722
16723     var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
16724
16725     var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\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\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\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\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\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\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif";
16726
16727     var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\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};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\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";
16728
16729     var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif";
16730
16731     var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
16732
16733     var lights_toon_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)";
16734
16735     var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
16736
16737     var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)";
16738
16739     var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif";
16740
16741     var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat specularRoughness;\n\tvec3 specularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
16742
16743     var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\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\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
16744
16745     var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif";
16746
16747     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, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif";
16748
16749     var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
16750
16751     var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
16752
16753     var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
16754
16755     var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif";
16756
16757     var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
16758
16759     var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
16760
16761     var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
16762
16763     var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
16764
16765     var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
16766
16767     var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
16768
16769     var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
16770
16771     var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
16772
16773     var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif";
16774
16775     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\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;";
16776
16777     var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif";
16778
16779     var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif";
16780
16781     var clearcoat_normal_fragment_begin = "#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
16782
16783     var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\t#endif\n#endif";
16784
16785     var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif";
16786
16787     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}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}";
16788
16789     var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
16790
16791     var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
16792
16793     var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
16794
16795     var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif";
16796
16797     var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
16798
16799     var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
16800
16801     var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
16802
16803     var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
16804
16805     var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif";
16806
16807     var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}";
16808
16809     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";
16810
16811     var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif";
16812
16813     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";
16814
16815     var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
16816
16817     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";
16818
16819     var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
16820
16821     var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
16822
16823     var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\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}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(  1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,  1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,  1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
16824
16825     var transmissionmap_fragment = "#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif";
16826
16827     var transmissionmap_pars_fragment = "#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\n#endif";
16828
16829     var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
16830
16831     var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif";
16832
16833     var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
16834
16835     var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
16836
16837     var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif";
16838
16839     var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
16840
16841     var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
16842
16843     var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
16844
16845     var background_vert = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
16846
16847     var cube_frag = "#include <envmap_common_pars_fragment>\nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include <envmap_fragment>\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
16848
16849     var cube_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
16850
16851     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>\nvarying vec2 vHighPrecisionZW;\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\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
16852
16853     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>\nvarying vec2 vHighPrecisionZW;\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\tvHighPrecisionZW = gl_Position.zw;\n}";
16854
16855     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}";
16856
16857     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}";
16858
16859     var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
16860
16861     var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
16862
16863     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 <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
16864
16865     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 <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
16866
16867     var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\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 <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_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\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <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 <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
16868
16869     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}";
16870
16871     var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <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_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\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\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include <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}";
16872
16873     var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <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 <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}";
16874
16875     var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_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 <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
16876
16877     var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_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 <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#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\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\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
16878
16879     var meshtoon_frag = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\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 <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_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 <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_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 + 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}";
16880
16881     var meshtoon_vert = "#define TOON\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}";
16882
16883     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_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\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}";
16884
16885     var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
16886
16887     var meshphysical_frag = "#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSMISSION\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSMISSION\n\tuniform float transmission;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <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 <transmissionmap_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_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#ifdef TRANSMISSION\n\t\tfloat totalTransmission = transmission;\n\t#endif\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 <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <transmissionmap_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\t#ifdef TRANSMISSION\n\t\tdiffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );\n\t#endif\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}";
16888
16889     var meshphysical_vert = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <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\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <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}";
16890
16891     var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\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}";
16892
16893     var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <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 <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\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <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#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
16894
16895     var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\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 <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
16896
16897     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\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}";
16898
16899     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 <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
16900
16901     var shadow_vert = "#include <common>\n#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 <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 <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
16902
16903     var sprite_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_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_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
16904
16905     var sprite_vert = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
16906
16907     const ShaderChunk = {
16908         alphamap_fragment: alphamap_fragment,
16909         alphamap_pars_fragment: alphamap_pars_fragment,
16910         alphatest_fragment: alphatest_fragment,
16911         aomap_fragment: aomap_fragment,
16912         aomap_pars_fragment: aomap_pars_fragment,
16913         begin_vertex: begin_vertex,
16914         beginnormal_vertex: beginnormal_vertex,
16915         bsdfs: bsdfs,
16916         bumpmap_pars_fragment: bumpmap_pars_fragment,
16917         clipping_planes_fragment: clipping_planes_fragment,
16918         clipping_planes_pars_fragment: clipping_planes_pars_fragment,
16919         clipping_planes_pars_vertex: clipping_planes_pars_vertex,
16920         clipping_planes_vertex: clipping_planes_vertex,
16921         color_fragment: color_fragment,
16922         color_pars_fragment: color_pars_fragment,
16923         color_pars_vertex: color_pars_vertex,
16924         color_vertex: color_vertex,
16925         common: common$1,
16926         cube_uv_reflection_fragment: cube_uv_reflection_fragment,
16927         defaultnormal_vertex: defaultnormal_vertex,
16928         displacementmap_pars_vertex: displacementmap_pars_vertex,
16929         displacementmap_vertex: displacementmap_vertex,
16930         emissivemap_fragment: emissivemap_fragment,
16931         emissivemap_pars_fragment: emissivemap_pars_fragment,
16932         encodings_fragment: encodings_fragment,
16933         encodings_pars_fragment: encodings_pars_fragment,
16934         envmap_fragment: envmap_fragment,
16935         envmap_common_pars_fragment: envmap_common_pars_fragment,
16936         envmap_pars_fragment: envmap_pars_fragment,
16937         envmap_pars_vertex: envmap_pars_vertex,
16938         envmap_physical_pars_fragment: envmap_physical_pars_fragment,
16939         envmap_vertex: envmap_vertex,
16940         fog_vertex: fog_vertex,
16941         fog_pars_vertex: fog_pars_vertex,
16942         fog_fragment: fog_fragment,
16943         fog_pars_fragment: fog_pars_fragment,
16944         gradientmap_pars_fragment: gradientmap_pars_fragment,
16945         lightmap_fragment: lightmap_fragment,
16946         lightmap_pars_fragment: lightmap_pars_fragment,
16947         lights_lambert_vertex: lights_lambert_vertex,
16948         lights_pars_begin: lights_pars_begin,
16949         lights_toon_fragment: lights_toon_fragment,
16950         lights_toon_pars_fragment: lights_toon_pars_fragment,
16951         lights_phong_fragment: lights_phong_fragment,
16952         lights_phong_pars_fragment: lights_phong_pars_fragment,
16953         lights_physical_fragment: lights_physical_fragment,
16954         lights_physical_pars_fragment: lights_physical_pars_fragment,
16955         lights_fragment_begin: lights_fragment_begin,
16956         lights_fragment_maps: lights_fragment_maps,
16957         lights_fragment_end: lights_fragment_end,
16958         logdepthbuf_fragment: logdepthbuf_fragment,
16959         logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
16960         logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
16961         logdepthbuf_vertex: logdepthbuf_vertex,
16962         map_fragment: map_fragment,
16963         map_pars_fragment: map_pars_fragment,
16964         map_particle_fragment: map_particle_fragment,
16965         map_particle_pars_fragment: map_particle_pars_fragment,
16966         metalnessmap_fragment: metalnessmap_fragment,
16967         metalnessmap_pars_fragment: metalnessmap_pars_fragment,
16968         morphnormal_vertex: morphnormal_vertex,
16969         morphtarget_pars_vertex: morphtarget_pars_vertex,
16970         morphtarget_vertex: morphtarget_vertex,
16971         normal_fragment_begin: normal_fragment_begin,
16972         normal_fragment_maps: normal_fragment_maps,
16973         normalmap_pars_fragment: normalmap_pars_fragment,
16974         clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
16975         clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
16976         clearcoat_pars_fragment: clearcoat_pars_fragment,
16977         packing: packing,
16978         premultiplied_alpha_fragment: premultiplied_alpha_fragment,
16979         project_vertex: project_vertex,
16980         dithering_fragment: dithering_fragment,
16981         dithering_pars_fragment: dithering_pars_fragment,
16982         roughnessmap_fragment: roughnessmap_fragment,
16983         roughnessmap_pars_fragment: roughnessmap_pars_fragment,
16984         shadowmap_pars_fragment: shadowmap_pars_fragment,
16985         shadowmap_pars_vertex: shadowmap_pars_vertex,
16986         shadowmap_vertex: shadowmap_vertex,
16987         shadowmask_pars_fragment: shadowmask_pars_fragment,
16988         skinbase_vertex: skinbase_vertex,
16989         skinning_pars_vertex: skinning_pars_vertex,
16990         skinning_vertex: skinning_vertex,
16991         skinnormal_vertex: skinnormal_vertex,
16992         specularmap_fragment: specularmap_fragment,
16993         specularmap_pars_fragment: specularmap_pars_fragment,
16994         tonemapping_fragment: tonemapping_fragment,
16995         tonemapping_pars_fragment: tonemapping_pars_fragment,
16996         transmissionmap_fragment: transmissionmap_fragment,
16997         transmissionmap_pars_fragment: transmissionmap_pars_fragment,
16998         uv_pars_fragment: uv_pars_fragment,
16999         uv_pars_vertex: uv_pars_vertex,
17000         uv_vertex: uv_vertex,
17001         uv2_pars_fragment: uv2_pars_fragment,
17002         uv2_pars_vertex: uv2_pars_vertex,
17003         uv2_vertex: uv2_vertex,
17004         worldpos_vertex: worldpos_vertex,
17005
17006         background_frag: background_frag,
17007         background_vert: background_vert,
17008         cube_frag: cube_frag,
17009         cube_vert: cube_vert,
17010         depth_frag: depth_frag,
17011         depth_vert: depth_vert,
17012         distanceRGBA_frag: distanceRGBA_frag,
17013         distanceRGBA_vert: distanceRGBA_vert,
17014         equirect_frag: equirect_frag,
17015         equirect_vert: equirect_vert,
17016         linedashed_frag: linedashed_frag,
17017         linedashed_vert: linedashed_vert,
17018         meshbasic_frag: meshbasic_frag,
17019         meshbasic_vert: meshbasic_vert,
17020         meshlambert_frag: meshlambert_frag,
17021         meshlambert_vert: meshlambert_vert,
17022         meshmatcap_frag: meshmatcap_frag,
17023         meshmatcap_vert: meshmatcap_vert,
17024         meshtoon_frag: meshtoon_frag,
17025         meshtoon_vert: meshtoon_vert,
17026         meshphong_frag: meshphong_frag,
17027         meshphong_vert: meshphong_vert,
17028         meshphysical_frag: meshphysical_frag,
17029         meshphysical_vert: meshphysical_vert,
17030         normal_frag: normal_frag,
17031         normal_vert: normal_vert,
17032         points_frag: points_frag,
17033         points_vert: points_vert,
17034         shadow_frag: shadow_frag,
17035         shadow_vert: shadow_vert,
17036         sprite_frag: sprite_frag,
17037         sprite_vert: sprite_vert
17038     };
17039
17040     /**
17041      * Uniforms library for shared webgl shaders
17042      */
17043
17044     const UniformsLib = {
17045
17046         common: {
17047
17048                 diffuse: { value: new Color( 0xeeeeee ) },
17049                 opacity: { value: 1.0 },
17050
17051                 map: { value: null },
17052                 uvTransform: { value: new Matrix3() },
17053                 uv2Transform: { value: new Matrix3() },
17054
17055                 alphaMap: { value: null },
17056
17057         },
17058
17059         specularmap: {
17060
17061                 specularMap: { value: null },
17062
17063         },
17064
17065         envmap: {
17066
17067                 envMap: { value: null },
17068                 flipEnvMap: { value: - 1 },
17069                 reflectivity: { value: 1.0 },
17070                 refractionRatio: { value: 0.98 },
17071                 maxMipLevel: { value: 0 }
17072
17073         },
17074
17075         aomap: {
17076
17077                 aoMap: { value: null },
17078                 aoMapIntensity: { value: 1 }
17079
17080         },
17081
17082         lightmap: {
17083
17084                 lightMap: { value: null },
17085                 lightMapIntensity: { value: 1 }
17086
17087         },
17088
17089         emissivemap: {
17090
17091                 emissiveMap: { value: null }
17092
17093         },
17094
17095         bumpmap: {
17096
17097                 bumpMap: { value: null },
17098                 bumpScale: { value: 1 }
17099
17100         },
17101
17102         normalmap: {
17103
17104                 normalMap: { value: null },
17105                 normalScale: { value: new Vector2( 1, 1 ) }
17106
17107         },
17108
17109         displacementmap: {
17110
17111                 displacementMap: { value: null },
17112                 displacementScale: { value: 1 },
17113                 displacementBias: { value: 0 }
17114
17115         },
17116
17117         roughnessmap: {
17118
17119                 roughnessMap: { value: null }
17120
17121         },
17122
17123         metalnessmap: {
17124
17125                 metalnessMap: { value: null }
17126
17127         },
17128
17129         gradientmap: {
17130
17131                 gradientMap: { value: null }
17132
17133         },
17134
17135         fog: {
17136
17137                 fogDensity: { value: 0.00025 },
17138                 fogNear: { value: 1 },
17139                 fogFar: { value: 2000 },
17140                 fogColor: { value: new Color( 0xffffff ) }
17141
17142         },
17143
17144         lights: {
17145
17146                 ambientLightColor: { value: [] },
17147
17148                 lightProbe: { value: [] },
17149
17150                 directionalLights: { value: [], properties: {
17151                         direction: {},
17152                         color: {}
17153                 } },
17154
17155                 directionalLightShadows: { value: [], properties: {
17156                         shadowBias: {},
17157                         shadowNormalBias: {},
17158                         shadowRadius: {},
17159                         shadowMapSize: {}
17160                 } },
17161
17162                 directionalShadowMap: { value: [] },
17163                 directionalShadowMatrix: { value: [] },
17164
17165                 spotLights: { value: [], properties: {
17166                         color: {},
17167                         position: {},
17168                         direction: {},
17169                         distance: {},
17170                         coneCos: {},
17171                         penumbraCos: {},
17172                         decay: {}
17173                 } },
17174
17175                 spotLightShadows: { value: [], properties: {
17176                         shadowBias: {},
17177                         shadowNormalBias: {},
17178                         shadowRadius: {},
17179                         shadowMapSize: {}
17180                 } },
17181
17182                 spotShadowMap: { value: [] },
17183                 spotShadowMatrix: { value: [] },
17184
17185                 pointLights: { value: [], properties: {
17186                         color: {},
17187                         position: {},
17188                         decay: {},
17189                         distance: {}
17190                 } },
17191
17192                 pointLightShadows: { value: [], properties: {
17193                         shadowBias: {},
17194                         shadowNormalBias: {},
17195                         shadowRadius: {},
17196                         shadowMapSize: {},
17197                         shadowCameraNear: {},
17198                         shadowCameraFar: {}
17199                 } },
17200
17201                 pointShadowMap: { value: [] },
17202                 pointShadowMatrix: { value: [] },
17203
17204                 hemisphereLights: { value: [], properties: {
17205                         direction: {},
17206                         skyColor: {},
17207                         groundColor: {}
17208                 } },
17209
17210                 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
17211                 rectAreaLights: { value: [], properties: {
17212                         color: {},
17213                         position: {},
17214                         width: {},
17215                         height: {}
17216                 } },
17217
17218                 ltc_1: { value: null },
17219                 ltc_2: { value: null }
17220
17221         },
17222
17223         points: {
17224
17225                 diffuse: { value: new Color( 0xeeeeee ) },
17226                 opacity: { value: 1.0 },
17227                 size: { value: 1.0 },
17228                 scale: { value: 1.0 },
17229                 map: { value: null },
17230                 alphaMap: { value: null },
17231                 uvTransform: { value: new Matrix3() }
17232
17233         },
17234
17235         sprite: {
17236
17237                 diffuse: { value: new Color( 0xeeeeee ) },
17238                 opacity: { value: 1.0 },
17239                 center: { value: new Vector2( 0.5, 0.5 ) },
17240                 rotation: { value: 0.0 },
17241                 map: { value: null },
17242                 alphaMap: { value: null },
17243                 uvTransform: { value: new Matrix3() }
17244
17245         }
17246
17247     };
17248
17249     const ShaderLib = {
17250
17251         basic: {
17252
17253                 uniforms: mergeUniforms( [
17254                         UniformsLib.common,
17255                         UniformsLib.specularmap,
17256                         UniformsLib.envmap,
17257                         UniformsLib.aomap,
17258                         UniformsLib.lightmap,
17259                         UniformsLib.fog
17260                 ] ),
17261
17262                 vertexShader: ShaderChunk.meshbasic_vert,
17263                 fragmentShader: ShaderChunk.meshbasic_frag
17264
17265         },
17266
17267         lambert: {
17268
17269                 uniforms: mergeUniforms( [
17270                         UniformsLib.common,
17271                         UniformsLib.specularmap,
17272                         UniformsLib.envmap,
17273                         UniformsLib.aomap,
17274                         UniformsLib.lightmap,
17275                         UniformsLib.emissivemap,
17276                         UniformsLib.fog,
17277                         UniformsLib.lights,
17278                         {
17279                                 emissive: { value: new Color( 0x000000 ) }
17280                         }
17281                 ] ),
17282
17283                 vertexShader: ShaderChunk.meshlambert_vert,
17284                 fragmentShader: ShaderChunk.meshlambert_frag
17285
17286         },
17287
17288         phong: {
17289
17290                 uniforms: mergeUniforms( [
17291                         UniformsLib.common,
17292                         UniformsLib.specularmap,
17293                         UniformsLib.envmap,
17294                         UniformsLib.aomap,
17295                         UniformsLib.lightmap,
17296                         UniformsLib.emissivemap,
17297                         UniformsLib.bumpmap,
17298                         UniformsLib.normalmap,
17299                         UniformsLib.displacementmap,
17300                         UniformsLib.fog,
17301                         UniformsLib.lights,
17302                         {
17303                                 emissive: { value: new Color( 0x000000 ) },
17304                                 specular: { value: new Color( 0x111111 ) },
17305                                 shininess: { value: 30 }
17306                         }
17307                 ] ),
17308
17309                 vertexShader: ShaderChunk.meshphong_vert,
17310                 fragmentShader: ShaderChunk.meshphong_frag
17311
17312         },
17313
17314         standard: {
17315
17316                 uniforms: mergeUniforms( [
17317                         UniformsLib.common,
17318                         UniformsLib.envmap,
17319                         UniformsLib.aomap,
17320                         UniformsLib.lightmap,
17321                         UniformsLib.emissivemap,
17322                         UniformsLib.bumpmap,
17323                         UniformsLib.normalmap,
17324                         UniformsLib.displacementmap,
17325                         UniformsLib.roughnessmap,
17326                         UniformsLib.metalnessmap,
17327                         UniformsLib.fog,
17328                         UniformsLib.lights,
17329                         {
17330                                 emissive: { value: new Color( 0x000000 ) },
17331                                 roughness: { value: 1.0 },
17332                                 metalness: { value: 0.0 },
17333                                 envMapIntensity: { value: 1 } // temporary
17334                         }
17335                 ] ),
17336
17337                 vertexShader: ShaderChunk.meshphysical_vert,
17338                 fragmentShader: ShaderChunk.meshphysical_frag
17339
17340         },
17341
17342         toon: {
17343
17344                 uniforms: mergeUniforms( [
17345                         UniformsLib.common,
17346                         UniformsLib.aomap,
17347                         UniformsLib.lightmap,
17348                         UniformsLib.emissivemap,
17349                         UniformsLib.bumpmap,
17350                         UniformsLib.normalmap,
17351                         UniformsLib.displacementmap,
17352                         UniformsLib.gradientmap,
17353                         UniformsLib.fog,
17354                         UniformsLib.lights,
17355                         {
17356                                 emissive: { value: new Color( 0x000000 ) }
17357                         }
17358                 ] ),
17359
17360                 vertexShader: ShaderChunk.meshtoon_vert,
17361                 fragmentShader: ShaderChunk.meshtoon_frag
17362
17363         },
17364
17365         matcap: {
17366
17367                 uniforms: mergeUniforms( [
17368                         UniformsLib.common,
17369                         UniformsLib.bumpmap,
17370                         UniformsLib.normalmap,
17371                         UniformsLib.displacementmap,
17372                         UniformsLib.fog,
17373                         {
17374                                 matcap: { value: null }
17375                         }
17376                 ] ),
17377
17378                 vertexShader: ShaderChunk.meshmatcap_vert,
17379                 fragmentShader: ShaderChunk.meshmatcap_frag
17380
17381         },
17382
17383         points: {
17384
17385                 uniforms: mergeUniforms( [
17386                         UniformsLib.points,
17387                         UniformsLib.fog
17388                 ] ),
17389
17390                 vertexShader: ShaderChunk.points_vert,
17391                 fragmentShader: ShaderChunk.points_frag
17392
17393         },
17394
17395         dashed: {
17396
17397                 uniforms: mergeUniforms( [
17398                         UniformsLib.common,
17399                         UniformsLib.fog,
17400                         {
17401                                 scale: { value: 1 },
17402                                 dashSize: { value: 1 },
17403                                 totalSize: { value: 2 }
17404                         }
17405                 ] ),
17406
17407                 vertexShader: ShaderChunk.linedashed_vert,
17408                 fragmentShader: ShaderChunk.linedashed_frag
17409
17410         },
17411
17412         depth: {
17413
17414                 uniforms: mergeUniforms( [
17415                         UniformsLib.common,
17416                         UniformsLib.displacementmap
17417                 ] ),
17418
17419                 vertexShader: ShaderChunk.depth_vert,
17420                 fragmentShader: ShaderChunk.depth_frag
17421
17422         },
17423
17424         normal: {
17425
17426                 uniforms: mergeUniforms( [
17427                         UniformsLib.common,
17428                         UniformsLib.bumpmap,
17429                         UniformsLib.normalmap,
17430                         UniformsLib.displacementmap,
17431                         {
17432                                 opacity: { value: 1.0 }
17433                         }
17434                 ] ),
17435
17436                 vertexShader: ShaderChunk.normal_vert,
17437                 fragmentShader: ShaderChunk.normal_frag
17438
17439         },
17440
17441         sprite: {
17442
17443                 uniforms: mergeUniforms( [
17444                         UniformsLib.sprite,
17445                         UniformsLib.fog
17446                 ] ),
17447
17448                 vertexShader: ShaderChunk.sprite_vert,
17449                 fragmentShader: ShaderChunk.sprite_frag
17450
17451         },
17452
17453         background: {
17454
17455                 uniforms: {
17456                         uvTransform: { value: new Matrix3() },
17457                         t2D: { value: null },
17458                 },
17459
17460                 vertexShader: ShaderChunk.background_vert,
17461                 fragmentShader: ShaderChunk.background_frag
17462
17463         },
17464         /* -------------------------------------------------------------------------
17465         //      Cube map shader
17466          ------------------------------------------------------------------------- */
17467
17468         cube: {
17469
17470                 uniforms: mergeUniforms( [
17471                         UniformsLib.envmap,
17472                         {
17473                                 opacity: { value: 1.0 }
17474                         }
17475                 ] ),
17476
17477                 vertexShader: ShaderChunk.cube_vert,
17478                 fragmentShader: ShaderChunk.cube_frag
17479
17480         },
17481
17482         equirect: {
17483
17484                 uniforms: {
17485                         tEquirect: { value: null },
17486                 },
17487
17488                 vertexShader: ShaderChunk.equirect_vert,
17489                 fragmentShader: ShaderChunk.equirect_frag
17490
17491         },
17492
17493         distanceRGBA: {
17494
17495                 uniforms: mergeUniforms( [
17496                         UniformsLib.common,
17497                         UniformsLib.displacementmap,
17498                         {
17499                                 referencePosition: { value: new Vector3() },
17500                                 nearDistance: { value: 1 },
17501                                 farDistance: { value: 1000 }
17502                         }
17503                 ] ),
17504
17505                 vertexShader: ShaderChunk.distanceRGBA_vert,
17506                 fragmentShader: ShaderChunk.distanceRGBA_frag
17507
17508         },
17509
17510         shadow: {
17511
17512                 uniforms: mergeUniforms( [
17513                         UniformsLib.lights,
17514                         UniformsLib.fog,
17515                         {
17516                                 color: { value: new Color( 0x00000 ) },
17517                                 opacity: { value: 1.0 }
17518                         },
17519                 ] ),
17520
17521                 vertexShader: ShaderChunk.shadow_vert,
17522                 fragmentShader: ShaderChunk.shadow_frag
17523
17524         }
17525
17526     };
17527
17528     ShaderLib.physical = {
17529
17530         uniforms: mergeUniforms( [
17531                 ShaderLib.standard.uniforms,
17532                 {
17533                         clearcoat: { value: 0 },
17534                         clearcoatMap: { value: null },
17535                         clearcoatRoughness: { value: 0 },
17536                         clearcoatRoughnessMap: { value: null },
17537                         clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
17538                         clearcoatNormalMap: { value: null },
17539                         sheen: { value: new Color( 0x000000 ) },
17540                         transmission: { value: 0 },
17541                         transmissionMap: { value: null },
17542                 }
17543         ] ),
17544
17545         vertexShader: ShaderChunk.meshphysical_vert,
17546         fragmentShader: ShaderChunk.meshphysical_frag
17547
17548     };
17549
17550     function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha ) {
17551
17552         const clearColor = new Color( 0x000000 );
17553         let clearAlpha = 0;
17554
17555         let planeMesh;
17556         let boxMesh;
17557
17558         let currentBackground = null;
17559         let currentBackgroundVersion = 0;
17560         let currentTonemapping = null;
17561
17562         function render( renderList, scene, camera, forceClear ) {
17563
17564                 let background = scene.isScene === true ? scene.background : null;
17565
17566                 if ( background && background.isTexture ) {
17567
17568                         background = cubemaps.get( background );
17569
17570                 }
17571
17572                 // Ignore background in AR
17573                 // TODO: Reconsider this.
17574
17575                 const xr = renderer.xr;
17576                 const session = xr.getSession && xr.getSession();
17577
17578                 if ( session && session.environmentBlendMode === 'additive' ) {
17579
17580                         background = null;
17581
17582                 }
17583
17584                 if ( background === null ) {
17585
17586                         setClear( clearColor, clearAlpha );
17587
17588                 } else if ( background && background.isColor ) {
17589
17590                         setClear( background, 1 );
17591                         forceClear = true;
17592
17593                 }
17594
17595                 if ( renderer.autoClear || forceClear ) {
17596
17597                         renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
17598
17599                 }
17600
17601                 if ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {
17602
17603                         if ( boxMesh === undefined ) {
17604
17605                                 boxMesh = new Mesh(
17606                                         new BoxGeometry( 1, 1, 1 ),
17607                                         new ShaderMaterial( {
17608                                                 name: 'BackgroundCubeMaterial',
17609                                                 uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
17610                                                 vertexShader: ShaderLib.cube.vertexShader,
17611                                                 fragmentShader: ShaderLib.cube.fragmentShader,
17612                                                 side: BackSide,
17613                                                 depthTest: false,
17614                                                 depthWrite: false,
17615                                                 fog: false
17616                                         } )
17617                                 );
17618
17619                                 boxMesh.geometry.deleteAttribute( 'normal' );
17620                                 boxMesh.geometry.deleteAttribute( 'uv' );
17621
17622                                 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
17623
17624                                         this.matrixWorld.copyPosition( camera.matrixWorld );
17625
17626                                 };
17627
17628                                 // enable code injection for non-built-in material
17629                                 Object.defineProperty( boxMesh.material, 'envMap', {
17630
17631                                         get: function () {
17632
17633                                                 return this.uniforms.envMap.value;
17634
17635                                         }
17636
17637                                 } );
17638
17639                                 objects.update( boxMesh );
17640
17641                         }
17642
17643                         if ( background.isWebGLCubeRenderTarget ) {
17644
17645                                 // TODO Deprecate
17646
17647                                 background = background.texture;
17648
17649                         }
17650
17651                         boxMesh.material.uniforms.envMap.value = background;
17652                         boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background._needsFlipEnvMap ) ? - 1 : 1;
17653
17654                         if ( currentBackground !== background ||
17655                                 currentBackgroundVersion !== background.version ||
17656                                 currentTonemapping !== renderer.toneMapping ) {
17657
17658                                 boxMesh.material.needsUpdate = true;
17659
17660                                 currentBackground = background;
17661                                 currentBackgroundVersion = background.version;
17662                                 currentTonemapping = renderer.toneMapping;
17663
17664                         }
17665
17666                         // push to the pre-sorted opaque render list
17667                         renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
17668
17669                 } else if ( background && background.isTexture ) {
17670
17671                         if ( planeMesh === undefined ) {
17672
17673                                 planeMesh = new Mesh(
17674                                         new PlaneGeometry( 2, 2 ),
17675                                         new ShaderMaterial( {
17676                                                 name: 'BackgroundMaterial',
17677                                                 uniforms: cloneUniforms( ShaderLib.background.uniforms ),
17678                                                 vertexShader: ShaderLib.background.vertexShader,
17679                                                 fragmentShader: ShaderLib.background.fragmentShader,
17680                                                 side: FrontSide,
17681                                                 depthTest: false,
17682                                                 depthWrite: false,
17683                                                 fog: false
17684                                         } )
17685                                 );
17686
17687                                 planeMesh.geometry.deleteAttribute( 'normal' );
17688
17689                                 // enable code injection for non-built-in material
17690                                 Object.defineProperty( planeMesh.material, 'map', {
17691
17692                                         get: function () {
17693
17694                                                 return this.uniforms.t2D.value;
17695
17696                                         }
17697
17698                                 } );
17699
17700                                 objects.update( planeMesh );
17701
17702                         }
17703
17704                         planeMesh.material.uniforms.t2D.value = background;
17705
17706                         if ( background.matrixAutoUpdate === true ) {
17707
17708                                 background.updateMatrix();
17709
17710                         }
17711
17712                         planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
17713
17714                         if ( currentBackground !== background ||
17715                                 currentBackgroundVersion !== background.version ||
17716                                 currentTonemapping !== renderer.toneMapping ) {
17717
17718                                 planeMesh.material.needsUpdate = true;
17719
17720                                 currentBackground = background;
17721                                 currentBackgroundVersion = background.version;
17722                                 currentTonemapping = renderer.toneMapping;
17723
17724                         }
17725
17726
17727                         // push to the pre-sorted opaque render list
17728                         renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
17729
17730                 }
17731
17732         }
17733
17734         function setClear( color, alpha ) {
17735
17736                 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
17737
17738         }
17739
17740         return {
17741
17742                 getClearColor: function () {
17743
17744                         return clearColor;
17745
17746                 },
17747                 setClearColor: function ( color, alpha = 1 ) {
17748
17749                         clearColor.set( color );
17750                         clearAlpha = alpha;
17751                         setClear( clearColor, clearAlpha );
17752
17753                 },
17754                 getClearAlpha: function () {
17755
17756                         return clearAlpha;
17757
17758                 },
17759                 setClearAlpha: function ( alpha ) {
17760
17761                         clearAlpha = alpha;
17762                         setClear( clearColor, clearAlpha );
17763
17764                 },
17765                 render: render
17766
17767         };
17768
17769     }
17770
17771     function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
17772
17773         const maxVertexAttributes = gl.getParameter( 34921 );
17774
17775         const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
17776         const vaoAvailable = capabilities.isWebGL2 || extension !== null;
17777
17778         const bindingStates = {};
17779
17780         const defaultState = createBindingState( null );
17781         let currentState = defaultState;
17782
17783         function setup( object, material, program, geometry, index ) {
17784
17785                 let updateBuffers = false;
17786
17787                 if ( vaoAvailable ) {
17788
17789                         const state = getBindingState( geometry, program, material );
17790
17791                         if ( currentState !== state ) {
17792
17793                                 currentState = state;
17794                                 bindVertexArrayObject( currentState.object );
17795
17796                         }
17797
17798                         updateBuffers = needsUpdate( geometry, index );
17799
17800                         if ( updateBuffers ) saveCache( geometry, index );
17801
17802                 } else {
17803
17804                         const wireframe = ( material.wireframe === true );
17805
17806                         if ( currentState.geometry !== geometry.id ||
17807                                 currentState.program !== program.id ||
17808                                 currentState.wireframe !== wireframe ) {
17809
17810                                 currentState.geometry = geometry.id;
17811                                 currentState.program = program.id;
17812                                 currentState.wireframe = wireframe;
17813
17814                                 updateBuffers = true;
17815
17816                         }
17817
17818                 }
17819
17820                 if ( object.isInstancedMesh === true ) {
17821
17822                         updateBuffers = true;
17823
17824                 }
17825
17826                 if ( index !== null ) {
17827
17828                         attributes.update( index, 34963 );
17829
17830                 }
17831
17832                 if ( updateBuffers ) {
17833
17834                         setupVertexAttributes( object, material, program, geometry );
17835
17836                         if ( index !== null ) {
17837
17838                                 gl.bindBuffer( 34963, attributes.get( index ).buffer );
17839
17840                         }
17841
17842                 }
17843
17844         }
17845
17846         function createVertexArrayObject() {
17847
17848                 if ( capabilities.isWebGL2 ) return gl.createVertexArray();
17849
17850                 return extension.createVertexArrayOES();
17851
17852         }
17853
17854         function bindVertexArrayObject( vao ) {
17855
17856                 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
17857
17858                 return extension.bindVertexArrayOES( vao );
17859
17860         }
17861
17862         function deleteVertexArrayObject( vao ) {
17863
17864                 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
17865
17866                 return extension.deleteVertexArrayOES( vao );
17867
17868         }
17869
17870         function getBindingState( geometry, program, material ) {
17871
17872                 const wireframe = ( material.wireframe === true );
17873
17874                 let programMap = bindingStates[ geometry.id ];
17875
17876                 if ( programMap === undefined ) {
17877
17878                         programMap = {};
17879                         bindingStates[ geometry.id ] = programMap;
17880
17881                 }
17882
17883                 let stateMap = programMap[ program.id ];
17884
17885                 if ( stateMap === undefined ) {
17886
17887                         stateMap = {};
17888                         programMap[ program.id ] = stateMap;
17889
17890                 }
17891
17892                 let state = stateMap[ wireframe ];
17893
17894                 if ( state === undefined ) {
17895
17896                         state = createBindingState( createVertexArrayObject() );
17897                         stateMap[ wireframe ] = state;
17898
17899                 }
17900
17901                 return state;
17902
17903         }
17904
17905         function createBindingState( vao ) {
17906
17907                 const newAttributes = [];
17908                 const enabledAttributes = [];
17909                 const attributeDivisors = [];
17910
17911                 for ( let i = 0; i < maxVertexAttributes; i ++ ) {
17912
17913                         newAttributes[ i ] = 0;
17914                         enabledAttributes[ i ] = 0;
17915                         attributeDivisors[ i ] = 0;
17916
17917                 }
17918
17919                 return {
17920
17921                         // for backward compatibility on non-VAO support browser
17922                         geometry: null,
17923                         program: null,
17924                         wireframe: false,
17925
17926                         newAttributes: newAttributes,
17927                         enabledAttributes: enabledAttributes,
17928                         attributeDivisors: attributeDivisors,
17929                         object: vao,
17930                         attributes: {},
17931                         index: null
17932
17933                 };
17934
17935         }
17936
17937         function needsUpdate( geometry, index ) {
17938
17939                 const cachedAttributes = currentState.attributes;
17940                 const geometryAttributes = geometry.attributes;
17941
17942                 let attributesNum = 0;
17943
17944                 for ( const key in geometryAttributes ) {
17945
17946                         const cachedAttribute = cachedAttributes[ key ];
17947                         const geometryAttribute = geometryAttributes[ key ];
17948
17949                         if ( cachedAttribute === undefined ) return true;
17950
17951                         if ( cachedAttribute.attribute !== geometryAttribute ) return true;
17952
17953                         if ( cachedAttribute.data !== geometryAttribute.data ) return true;
17954
17955                         attributesNum ++;
17956
17957                 }
17958
17959                 if ( currentState.attributesNum !== attributesNum ) return true;
17960
17961                 if ( currentState.index !== index ) return true;
17962
17963                 return false;
17964
17965         }
17966
17967         function saveCache( geometry, index ) {
17968
17969                 const cache = {};
17970                 const attributes = geometry.attributes;
17971                 let attributesNum = 0;
17972
17973                 for ( const key in attributes ) {
17974
17975                         const attribute = attributes[ key ];
17976
17977                         const data = {};
17978                         data.attribute = attribute;
17979
17980                         if ( attribute.data ) {
17981
17982                                 data.data = attribute.data;
17983
17984                         }
17985
17986                         cache[ key ] = data;
17987
17988                         attributesNum ++;
17989
17990                 }
17991
17992                 currentState.attributes = cache;
17993                 currentState.attributesNum = attributesNum;
17994
17995                 currentState.index = index;
17996
17997         }
17998
17999         function initAttributes() {
18000
18001                 const newAttributes = currentState.newAttributes;
18002
18003                 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
18004
18005                         newAttributes[ i ] = 0;
18006
18007                 }
18008
18009         }
18010
18011         function enableAttribute( attribute ) {
18012
18013                 enableAttributeAndDivisor( attribute, 0 );
18014
18015         }
18016
18017         function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
18018
18019                 const newAttributes = currentState.newAttributes;
18020                 const enabledAttributes = currentState.enabledAttributes;
18021                 const attributeDivisors = currentState.attributeDivisors;
18022
18023                 newAttributes[ attribute ] = 1;
18024
18025                 if ( enabledAttributes[ attribute ] === 0 ) {
18026
18027                         gl.enableVertexAttribArray( attribute );
18028                         enabledAttributes[ attribute ] = 1;
18029
18030                 }
18031
18032                 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
18033
18034                         const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
18035
18036                         extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
18037                         attributeDivisors[ attribute ] = meshPerAttribute;
18038
18039                 }
18040
18041         }
18042
18043         function disableUnusedAttributes() {
18044
18045                 const newAttributes = currentState.newAttributes;
18046                 const enabledAttributes = currentState.enabledAttributes;
18047
18048                 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
18049
18050                         if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
18051
18052                                 gl.disableVertexAttribArray( i );
18053                                 enabledAttributes[ i ] = 0;
18054
18055                         }
18056
18057                 }
18058
18059         }
18060
18061         function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
18062
18063                 if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
18064
18065                         gl.vertexAttribIPointer( index, size, type, stride, offset );
18066
18067                 } else {
18068
18069                         gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
18070
18071                 }
18072
18073         }
18074
18075         function setupVertexAttributes( object, material, program, geometry ) {
18076
18077                 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
18078
18079                         if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
18080
18081                 }
18082
18083                 initAttributes();
18084
18085                 const geometryAttributes = geometry.attributes;
18086
18087                 const programAttributes = program.getAttributes();
18088
18089                 const materialDefaultAttributeValues = material.defaultAttributeValues;
18090
18091                 for ( const name in programAttributes ) {
18092
18093                         const programAttribute = programAttributes[ name ];
18094
18095                         if ( programAttribute >= 0 ) {
18096
18097                                 const geometryAttribute = geometryAttributes[ name ];
18098
18099                                 if ( geometryAttribute !== undefined ) {
18100
18101                                         const normalized = geometryAttribute.normalized;
18102                                         const size = geometryAttribute.itemSize;
18103
18104                                         const attribute = attributes.get( geometryAttribute );
18105
18106                                         // TODO Attribute may not be available on context restore
18107
18108                                         if ( attribute === undefined ) continue;
18109
18110                                         const buffer = attribute.buffer;
18111                                         const type = attribute.type;
18112                                         const bytesPerElement = attribute.bytesPerElement;
18113
18114                                         if ( geometryAttribute.isInterleavedBufferAttribute ) {
18115
18116                                                 const data = geometryAttribute.data;
18117                                                 const stride = data.stride;
18118                                                 const offset = geometryAttribute.offset;
18119
18120                                                 if ( data && data.isInstancedInterleavedBuffer ) {
18121
18122                                                         enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
18123
18124                                                         if ( geometry._maxInstanceCount === undefined ) {
18125
18126                                                                 geometry._maxInstanceCount = data.meshPerAttribute * data.count;
18127
18128                                                         }
18129
18130                                                 } else {
18131
18132                                                         enableAttribute( programAttribute );
18133
18134                                                 }
18135
18136                                                 gl.bindBuffer( 34962, buffer );
18137                                                 vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
18138
18139                                         } else {
18140
18141                                                 if ( geometryAttribute.isInstancedBufferAttribute ) {
18142
18143                                                         enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
18144
18145                                                         if ( geometry._maxInstanceCount === undefined ) {
18146
18147                                                                 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
18148
18149                                                         }
18150
18151                                                 } else {
18152
18153                                                         enableAttribute( programAttribute );
18154
18155                                                 }
18156
18157                                                 gl.bindBuffer( 34962, buffer );
18158                                                 vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
18159
18160                                         }
18161
18162                                 } else if ( name === 'instanceMatrix' ) {
18163
18164                                         const attribute = attributes.get( object.instanceMatrix );
18165
18166                                         // TODO Attribute may not be available on context restore
18167
18168                                         if ( attribute === undefined ) continue;
18169
18170                                         const buffer = attribute.buffer;
18171                                         const type = attribute.type;
18172
18173                                         enableAttributeAndDivisor( programAttribute + 0, 1 );
18174                                         enableAttributeAndDivisor( programAttribute + 1, 1 );
18175                                         enableAttributeAndDivisor( programAttribute + 2, 1 );
18176                                         enableAttributeAndDivisor( programAttribute + 3, 1 );
18177
18178                                         gl.bindBuffer( 34962, buffer );
18179
18180                                         gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
18181                                         gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
18182                                         gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
18183                                         gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
18184
18185                                 } else if ( name === 'instanceColor' ) {
18186
18187                                         const attribute = attributes.get( object.instanceColor );
18188
18189                                         // TODO Attribute may not be available on context restore
18190
18191                                         if ( attribute === undefined ) continue;
18192
18193                                         const buffer = attribute.buffer;
18194                                         const type = attribute.type;
18195
18196                                         enableAttributeAndDivisor( programAttribute, 1 );
18197
18198                                         gl.bindBuffer( 34962, buffer );
18199
18200                                         gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
18201
18202                                 } else if ( materialDefaultAttributeValues !== undefined ) {
18203
18204                                         const value = materialDefaultAttributeValues[ name ];
18205
18206                                         if ( value !== undefined ) {
18207
18208                                                 switch ( value.length ) {
18209
18210                                                         case 2:
18211                                                                 gl.vertexAttrib2fv( programAttribute, value );
18212                                                                 break;
18213
18214                                                         case 3:
18215                                                                 gl.vertexAttrib3fv( programAttribute, value );
18216                                                                 break;
18217
18218                                                         case 4:
18219                                                                 gl.vertexAttrib4fv( programAttribute, value );
18220                                                                 break;
18221
18222                                                         default:
18223                                                                 gl.vertexAttrib1fv( programAttribute, value );
18224
18225                                                 }
18226
18227                                         }
18228
18229                                 }
18230
18231                         }
18232
18233                 }
18234
18235                 disableUnusedAttributes();
18236
18237         }
18238
18239         function dispose() {
18240
18241                 reset();
18242
18243                 for ( const geometryId in bindingStates ) {
18244
18245                         const programMap = bindingStates[ geometryId ];
18246
18247                         for ( const programId in programMap ) {
18248
18249                                 const stateMap = programMap[ programId ];
18250
18251                                 for ( const wireframe in stateMap ) {
18252
18253                                         deleteVertexArrayObject( stateMap[ wireframe ].object );
18254
18255                                         delete stateMap[ wireframe ];
18256
18257                                 }
18258
18259                                 delete programMap[ programId ];
18260
18261                         }
18262
18263                         delete bindingStates[ geometryId ];
18264
18265                 }
18266
18267         }
18268
18269         function releaseStatesOfGeometry( geometry ) {
18270
18271                 if ( bindingStates[ geometry.id ] === undefined ) return;
18272
18273                 const programMap = bindingStates[ geometry.id ];
18274
18275                 for ( const programId in programMap ) {
18276
18277                         const stateMap = programMap[ programId ];
18278
18279                         for ( const wireframe in stateMap ) {
18280
18281                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
18282
18283                                 delete stateMap[ wireframe ];
18284
18285                         }
18286
18287                         delete programMap[ programId ];
18288
18289                 }
18290
18291                 delete bindingStates[ geometry.id ];
18292
18293         }
18294
18295         function releaseStatesOfProgram( program ) {
18296
18297                 for ( const geometryId in bindingStates ) {
18298
18299                         const programMap = bindingStates[ geometryId ];
18300
18301                         if ( programMap[ program.id ] === undefined ) continue;
18302
18303                         const stateMap = programMap[ program.id ];
18304
18305                         for ( const wireframe in stateMap ) {
18306
18307                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
18308
18309                                 delete stateMap[ wireframe ];
18310
18311                         }
18312
18313                         delete programMap[ program.id ];
18314
18315                 }
18316
18317         }
18318
18319         function reset() {
18320
18321                 resetDefaultState();
18322
18323                 if ( currentState === defaultState ) return;
18324
18325                 currentState = defaultState;
18326                 bindVertexArrayObject( currentState.object );
18327
18328         }
18329
18330         // for backward-compatilibity
18331
18332         function resetDefaultState() {
18333
18334                 defaultState.geometry = null;
18335                 defaultState.program = null;
18336                 defaultState.wireframe = false;
18337
18338         }
18339
18340         return {
18341
18342                 setup: setup,
18343                 reset: reset,
18344                 resetDefaultState: resetDefaultState,
18345                 dispose: dispose,
18346                 releaseStatesOfGeometry: releaseStatesOfGeometry,
18347                 releaseStatesOfProgram: releaseStatesOfProgram,
18348
18349                 initAttributes: initAttributes,
18350                 enableAttribute: enableAttribute,
18351                 disableUnusedAttributes: disableUnusedAttributes
18352
18353         };
18354
18355     }
18356
18357     function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
18358
18359         const isWebGL2 = capabilities.isWebGL2;
18360
18361         let mode;
18362
18363         function setMode( value ) {
18364
18365                 mode = value;
18366
18367         }
18368
18369         function render( start, count ) {
18370
18371                 gl.drawArrays( mode, start, count );
18372
18373                 info.update( count, mode, 1 );
18374
18375         }
18376
18377         function renderInstances( start, count, primcount ) {
18378
18379                 if ( primcount === 0 ) return;
18380
18381                 let extension, methodName;
18382
18383                 if ( isWebGL2 ) {
18384
18385                         extension = gl;
18386                         methodName = 'drawArraysInstanced';
18387
18388                 } else {
18389
18390                         extension = extensions.get( 'ANGLE_instanced_arrays' );
18391                         methodName = 'drawArraysInstancedANGLE';
18392
18393                         if ( extension === null ) {
18394
18395                                 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
18396                                 return;
18397
18398                         }
18399
18400                 }
18401
18402                 extension[ methodName ]( mode, start, count, primcount );
18403
18404                 info.update( count, mode, primcount );
18405
18406         }
18407
18408         //
18409
18410         this.setMode = setMode;
18411         this.render = render;
18412         this.renderInstances = renderInstances;
18413
18414     }
18415
18416     function WebGLCapabilities( gl, extensions, parameters ) {
18417
18418         let maxAnisotropy;
18419
18420         function getMaxAnisotropy() {
18421
18422                 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
18423
18424                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
18425
18426                 if ( extension !== null ) {
18427
18428                         maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
18429
18430                 } else {
18431
18432                         maxAnisotropy = 0;
18433
18434                 }
18435
18436                 return maxAnisotropy;
18437
18438         }
18439
18440         function getMaxPrecision( precision ) {
18441
18442                 if ( precision === 'highp' ) {
18443
18444                         if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
18445                                 gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
18446
18447                                 return 'highp';
18448
18449                         }
18450
18451                         precision = 'mediump';
18452
18453                 }
18454
18455                 if ( precision === 'mediump' ) {
18456
18457                         if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
18458                                 gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
18459
18460                                 return 'mediump';
18461
18462                         }
18463
18464                 }
18465
18466                 return 'lowp';
18467
18468         }
18469
18470         /* eslint-disable no-undef */
18471         const isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
18472                 ( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
18473         /* eslint-enable no-undef */
18474
18475         let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
18476         const maxPrecision = getMaxPrecision( precision );
18477
18478         if ( maxPrecision !== precision ) {
18479
18480                 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
18481                 precision = maxPrecision;
18482
18483         }
18484
18485         const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
18486
18487         const maxTextures = gl.getParameter( 34930 );
18488         const maxVertexTextures = gl.getParameter( 35660 );
18489         const maxTextureSize = gl.getParameter( 3379 );
18490         const maxCubemapSize = gl.getParameter( 34076 );
18491
18492         const maxAttributes = gl.getParameter( 34921 );
18493         const maxVertexUniforms = gl.getParameter( 36347 );
18494         const maxVaryings = gl.getParameter( 36348 );
18495         const maxFragmentUniforms = gl.getParameter( 36349 );
18496
18497         const vertexTextures = maxVertexTextures > 0;
18498         const floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
18499         const floatVertexTextures = vertexTextures && floatFragmentTextures;
18500
18501         const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
18502
18503         return {
18504
18505                 isWebGL2: isWebGL2,
18506
18507                 getMaxAnisotropy: getMaxAnisotropy,
18508                 getMaxPrecision: getMaxPrecision,
18509
18510                 precision: precision,
18511                 logarithmicDepthBuffer: logarithmicDepthBuffer,
18512
18513                 maxTextures: maxTextures,
18514                 maxVertexTextures: maxVertexTextures,
18515                 maxTextureSize: maxTextureSize,
18516                 maxCubemapSize: maxCubemapSize,
18517
18518                 maxAttributes: maxAttributes,
18519                 maxVertexUniforms: maxVertexUniforms,
18520                 maxVaryings: maxVaryings,
18521                 maxFragmentUniforms: maxFragmentUniforms,
18522
18523                 vertexTextures: vertexTextures,
18524                 floatFragmentTextures: floatFragmentTextures,
18525                 floatVertexTextures: floatVertexTextures,
18526
18527                 maxSamples: maxSamples
18528
18529         };
18530
18531     }
18532
18533     function WebGLClipping( properties ) {
18534
18535         const scope = this;
18536
18537         let globalState = null,
18538                 numGlobalPlanes = 0,
18539                 localClippingEnabled = false,
18540                 renderingShadows = false;
18541
18542         const plane = new Plane(),
18543                 viewNormalMatrix = new Matrix3(),
18544
18545                 uniform = { value: null, needsUpdate: false };
18546
18547         this.uniform = uniform;
18548         this.numPlanes = 0;
18549         this.numIntersection = 0;
18550
18551         this.init = function ( planes, enableLocalClipping, camera ) {
18552
18553                 const enabled =
18554                         planes.length !== 0 ||
18555                         enableLocalClipping ||
18556                         // enable state of previous frame - the clipping code has to
18557                         // run another frame in order to reset the state:
18558                         numGlobalPlanes !== 0 ||
18559                         localClippingEnabled;
18560
18561                 localClippingEnabled = enableLocalClipping;
18562
18563                 globalState = projectPlanes( planes, camera, 0 );
18564                 numGlobalPlanes = planes.length;
18565
18566                 return enabled;
18567
18568         };
18569
18570         this.beginShadows = function () {
18571
18572                 renderingShadows = true;
18573                 projectPlanes( null );
18574
18575         };
18576
18577         this.endShadows = function () {
18578
18579                 renderingShadows = false;
18580                 resetGlobalState();
18581
18582         };
18583
18584         this.setState = function ( material, camera, useCache ) {
18585
18586                 const planes = material.clippingPlanes,
18587                         clipIntersection = material.clipIntersection,
18588                         clipShadows = material.clipShadows;
18589
18590                 const materialProperties = properties.get( material );
18591
18592                 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
18593
18594                         // there's no local clipping
18595
18596                         if ( renderingShadows ) {
18597
18598                                 // there's no global clipping
18599
18600                                 projectPlanes( null );
18601
18602                         } else {
18603
18604                                 resetGlobalState();
18605
18606                         }
18607
18608                 } else {
18609
18610                         const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
18611                                 lGlobal = nGlobal * 4;
18612
18613                         let dstArray = materialProperties.clippingState || null;
18614
18615                         uniform.value = dstArray; // ensure unique state
18616
18617                         dstArray = projectPlanes( planes, camera, lGlobal, useCache );
18618
18619                         for ( let i = 0; i !== lGlobal; ++ i ) {
18620
18621                                 dstArray[ i ] = globalState[ i ];
18622
18623                         }
18624
18625                         materialProperties.clippingState = dstArray;
18626                         this.numIntersection = clipIntersection ? this.numPlanes : 0;
18627                         this.numPlanes += nGlobal;
18628
18629                 }
18630
18631
18632         };
18633
18634         function resetGlobalState() {
18635
18636                 if ( uniform.value !== globalState ) {
18637
18638                         uniform.value = globalState;
18639                         uniform.needsUpdate = numGlobalPlanes > 0;
18640
18641                 }
18642
18643                 scope.numPlanes = numGlobalPlanes;
18644                 scope.numIntersection = 0;
18645
18646         }
18647
18648         function projectPlanes( planes, camera, dstOffset, skipTransform ) {
18649
18650                 const nPlanes = planes !== null ? planes.length : 0;
18651                 let dstArray = null;
18652
18653                 if ( nPlanes !== 0 ) {
18654
18655                         dstArray = uniform.value;
18656
18657                         if ( skipTransform !== true || dstArray === null ) {
18658
18659                                 const flatSize = dstOffset + nPlanes * 4,
18660                                         viewMatrix = camera.matrixWorldInverse;
18661
18662                                 viewNormalMatrix.getNormalMatrix( viewMatrix );
18663
18664                                 if ( dstArray === null || dstArray.length < flatSize ) {
18665
18666                                         dstArray = new Float32Array( flatSize );
18667
18668                                 }
18669
18670                                 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
18671
18672                                         plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
18673
18674                                         plane.normal.toArray( dstArray, i4 );
18675                                         dstArray[ i4 + 3 ] = plane.constant;
18676
18677                                 }
18678
18679                         }
18680
18681                         uniform.value = dstArray;
18682                         uniform.needsUpdate = true;
18683
18684                 }
18685
18686                 scope.numPlanes = nPlanes;
18687                 scope.numIntersection = 0;
18688
18689                 return dstArray;
18690
18691         }
18692
18693     }
18694
18695     function WebGLCubeMaps( renderer ) {
18696
18697         let cubemaps = new WeakMap();
18698
18699         function mapTextureMapping( texture, mapping ) {
18700
18701                 if ( mapping === EquirectangularReflectionMapping ) {
18702
18703                         texture.mapping = CubeReflectionMapping;
18704
18705                 } else if ( mapping === EquirectangularRefractionMapping ) {
18706
18707                         texture.mapping = CubeRefractionMapping;
18708
18709                 }
18710
18711                 return texture;
18712
18713         }
18714
18715         function get( texture ) {
18716
18717                 if ( texture && texture.isTexture ) {
18718
18719                         const mapping = texture.mapping;
18720
18721                         if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
18722
18723                                 if ( cubemaps.has( texture ) ) {
18724
18725                                         const cubemap = cubemaps.get( texture ).texture;
18726                                         return mapTextureMapping( cubemap, texture.mapping );
18727
18728                                 } else {
18729
18730                                         const image = texture.image;
18731
18732                                         if ( image && image.height > 0 ) {
18733
18734                                                 const currentRenderList = renderer.getRenderList();
18735                                                 const currentRenderTarget = renderer.getRenderTarget();
18736
18737                                                 const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
18738                                                 renderTarget.fromEquirectangularTexture( renderer, texture );
18739                                                 cubemaps.set( texture, renderTarget );
18740
18741                                                 renderer.setRenderTarget( currentRenderTarget );
18742                                                 renderer.setRenderList( currentRenderList );
18743
18744                                                 texture.addEventListener( 'dispose', onTextureDispose );
18745
18746                                                 return mapTextureMapping( renderTarget.texture, texture.mapping );
18747
18748                                         } else {
18749
18750                                                 // image not yet ready. try the conversion next frame
18751
18752                                                 return null;
18753
18754                                         }
18755
18756                                 }
18757
18758                         }
18759
18760                 }
18761
18762                 return texture;
18763
18764         }
18765
18766         function onTextureDispose( event ) {
18767
18768                 const texture = event.target;
18769
18770                 texture.removeEventListener( 'dispose', onTextureDispose );
18771
18772                 const cubemap = cubemaps.get( texture );
18773
18774                 if ( cubemap !== undefined ) {
18775
18776                         cubemaps.delete( texture );
18777                         cubemap.dispose();
18778
18779                 }
18780
18781         }
18782
18783         function dispose() {
18784
18785                 cubemaps = new WeakMap();
18786
18787         }
18788
18789         return {
18790                 get: get,
18791                 dispose: dispose
18792         };
18793
18794     }
18795
18796     function WebGLExtensions( gl ) {
18797
18798         const extensions = {};
18799
18800         function getExtension( name ) {
18801
18802                 if ( extensions[ name ] !== undefined ) {
18803
18804                         return extensions[ name ];
18805
18806                 }
18807
18808                 let extension;
18809
18810                 switch ( name ) {
18811
18812                         case 'WEBGL_depth_texture':
18813                                 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
18814                                 break;
18815
18816                         case 'EXT_texture_filter_anisotropic':
18817                                 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
18818                                 break;
18819
18820                         case 'WEBGL_compressed_texture_s3tc':
18821                                 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
18822                                 break;
18823
18824                         case 'WEBGL_compressed_texture_pvrtc':
18825                                 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
18826                                 break;
18827
18828                         default:
18829                                 extension = gl.getExtension( name );
18830
18831                 }
18832
18833                 extensions[ name ] = extension;
18834
18835                 return extension;
18836
18837         }
18838
18839         return {
18840
18841                 has: function ( name ) {
18842
18843                         return getExtension( name ) !== null;
18844
18845                 },
18846
18847                 init: function ( capabilities ) {
18848
18849                         if ( capabilities.isWebGL2 ) {
18850
18851                                 getExtension( 'EXT_color_buffer_float' );
18852
18853                         } else {
18854
18855                                 getExtension( 'WEBGL_depth_texture' );
18856                                 getExtension( 'OES_texture_float' );
18857                                 getExtension( 'OES_texture_half_float' );
18858                                 getExtension( 'OES_texture_half_float_linear' );
18859                                 getExtension( 'OES_standard_derivatives' );
18860                                 getExtension( 'OES_element_index_uint' );
18861                                 getExtension( 'OES_vertex_array_object' );
18862                                 getExtension( 'ANGLE_instanced_arrays' );
18863
18864                         }
18865
18866                         getExtension( 'OES_texture_float_linear' );
18867                         getExtension( 'EXT_color_buffer_half_float' );
18868
18869                 },
18870
18871                 get: function ( name ) {
18872
18873                         const extension = getExtension( name );
18874
18875                         if ( extension === null ) {
18876
18877                                 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
18878
18879                         }
18880
18881                         return extension;
18882
18883                 }
18884
18885         };
18886
18887     }
18888
18889     function WebGLGeometries( gl, attributes, info, bindingStates ) {
18890
18891         const geometries = {};
18892         const wireframeAttributes = new WeakMap();
18893
18894         function onGeometryDispose( event ) {
18895
18896                 const geometry = event.target;
18897
18898                 if ( geometry.index !== null ) {
18899
18900                         attributes.remove( geometry.index );
18901
18902                 }
18903
18904                 for ( const name in geometry.attributes ) {
18905
18906                         attributes.remove( geometry.attributes[ name ] );
18907
18908                 }
18909
18910                 geometry.removeEventListener( 'dispose', onGeometryDispose );
18911
18912                 delete geometries[ geometry.id ];
18913
18914                 const attribute = wireframeAttributes.get( geometry );
18915
18916                 if ( attribute ) {
18917
18918                         attributes.remove( attribute );
18919                         wireframeAttributes.delete( geometry );
18920
18921                 }
18922
18923                 bindingStates.releaseStatesOfGeometry( geometry );
18924
18925                 if ( geometry.isInstancedBufferGeometry === true ) {
18926
18927                         delete geometry._maxInstanceCount;
18928
18929                 }
18930
18931                 //
18932
18933                 info.memory.geometries --;
18934
18935         }
18936
18937         function get( object, geometry ) {
18938
18939                 if ( geometries[ geometry.id ] === true ) return geometry;
18940
18941                 geometry.addEventListener( 'dispose', onGeometryDispose );
18942
18943                 geometries[ geometry.id ] = true;
18944
18945                 info.memory.geometries ++;
18946
18947                 return geometry;
18948
18949         }
18950
18951         function update( geometry ) {
18952
18953                 const geometryAttributes = geometry.attributes;
18954
18955                 // Updating index buffer in VAO now. See WebGLBindingStates.
18956
18957                 for ( const name in geometryAttributes ) {
18958
18959                         attributes.update( geometryAttributes[ name ], 34962 );
18960
18961                 }
18962
18963                 // morph targets
18964
18965                 const morphAttributes = geometry.morphAttributes;
18966
18967                 for ( const name in morphAttributes ) {
18968
18969                         const array = morphAttributes[ name ];
18970
18971                         for ( let i = 0, l = array.length; i < l; i ++ ) {
18972
18973                                 attributes.update( array[ i ], 34962 );
18974
18975                         }
18976
18977                 }
18978
18979         }
18980
18981         function updateWireframeAttribute( geometry ) {
18982
18983                 const indices = [];
18984
18985                 const geometryIndex = geometry.index;
18986                 const geometryPosition = geometry.attributes.position;
18987                 let version = 0;
18988
18989                 if ( geometryIndex !== null ) {
18990
18991                         const array = geometryIndex.array;
18992                         version = geometryIndex.version;
18993
18994                         for ( let i = 0, l = array.length; i < l; i += 3 ) {
18995
18996                                 const a = array[ i + 0 ];
18997                                 const b = array[ i + 1 ];
18998                                 const c = array[ i + 2 ];
18999
19000                                 indices.push( a, b, b, c, c, a );
19001
19002                         }
19003
19004                 } else {
19005
19006                         const array = geometryPosition.array;
19007                         version = geometryPosition.version;
19008
19009                         for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
19010
19011                                 const a = i + 0;
19012                                 const b = i + 1;
19013                                 const c = i + 2;
19014
19015                                 indices.push( a, b, b, c, c, a );
19016
19017                         }
19018
19019                 }
19020
19021                 const attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
19022                 attribute.version = version;
19023
19024                 // Updating index buffer in VAO now. See WebGLBindingStates
19025
19026                 //
19027
19028                 const previousAttribute = wireframeAttributes.get( geometry );
19029
19030                 if ( previousAttribute ) attributes.remove( previousAttribute );
19031
19032                 //
19033
19034                 wireframeAttributes.set( geometry, attribute );
19035
19036         }
19037
19038         function getWireframeAttribute( geometry ) {
19039
19040                 const currentAttribute = wireframeAttributes.get( geometry );
19041
19042                 if ( currentAttribute ) {
19043
19044                         const geometryIndex = geometry.index;
19045
19046                         if ( geometryIndex !== null ) {
19047
19048                                 // if the attribute is obsolete, create a new one
19049
19050                                 if ( currentAttribute.version < geometryIndex.version ) {
19051
19052                                         updateWireframeAttribute( geometry );
19053
19054                                 }
19055
19056                         }
19057
19058                 } else {
19059
19060                         updateWireframeAttribute( geometry );
19061
19062                 }
19063
19064                 return wireframeAttributes.get( geometry );
19065
19066         }
19067
19068         return {
19069
19070                 get: get,
19071                 update: update,
19072
19073                 getWireframeAttribute: getWireframeAttribute
19074
19075         };
19076
19077     }
19078
19079     function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
19080
19081         const isWebGL2 = capabilities.isWebGL2;
19082
19083         let mode;
19084
19085         function setMode( value ) {
19086
19087                 mode = value;
19088
19089         }
19090
19091         let type, bytesPerElement;
19092
19093         function setIndex( value ) {
19094
19095                 type = value.type;
19096                 bytesPerElement = value.bytesPerElement;
19097
19098         }
19099
19100         function render( start, count ) {
19101
19102                 gl.drawElements( mode, count, type, start * bytesPerElement );
19103
19104                 info.update( count, mode, 1 );
19105
19106         }
19107
19108         function renderInstances( start, count, primcount ) {
19109
19110                 if ( primcount === 0 ) return;
19111
19112                 let extension, methodName;
19113
19114                 if ( isWebGL2 ) {
19115
19116                         extension = gl;
19117                         methodName = 'drawElementsInstanced';
19118
19119                 } else {
19120
19121                         extension = extensions.get( 'ANGLE_instanced_arrays' );
19122                         methodName = 'drawElementsInstancedANGLE';
19123
19124                         if ( extension === null ) {
19125
19126                                 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
19127                                 return;
19128
19129                         }
19130
19131                 }
19132
19133                 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
19134
19135                 info.update( count, mode, primcount );
19136
19137         }
19138
19139         //
19140
19141         this.setMode = setMode;
19142         this.setIndex = setIndex;
19143         this.render = render;
19144         this.renderInstances = renderInstances;
19145
19146     }
19147
19148     function WebGLInfo( gl ) {
19149
19150         const memory = {
19151                 geometries: 0,
19152                 textures: 0
19153         };
19154
19155         const render = {
19156                 frame: 0,
19157                 calls: 0,
19158                 triangles: 0,
19159                 points: 0,
19160                 lines: 0
19161         };
19162
19163         function update( count, mode, instanceCount ) {
19164
19165                 render.calls ++;
19166
19167                 switch ( mode ) {
19168
19169                         case 4:
19170                                 render.triangles += instanceCount * ( count / 3 );
19171                                 break;
19172
19173                         case 1:
19174                                 render.lines += instanceCount * ( count / 2 );
19175                                 break;
19176
19177                         case 3:
19178                                 render.lines += instanceCount * ( count - 1 );
19179                                 break;
19180
19181                         case 2:
19182                                 render.lines += instanceCount * count;
19183                                 break;
19184
19185                         case 0:
19186                                 render.points += instanceCount * count;
19187                                 break;
19188
19189                         default:
19190                                 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
19191                                 break;
19192
19193                 }
19194
19195         }
19196
19197         function reset() {
19198
19199                 render.frame ++;
19200                 render.calls = 0;
19201                 render.triangles = 0;
19202                 render.points = 0;
19203                 render.lines = 0;
19204
19205         }
19206
19207         return {
19208                 memory: memory,
19209                 render: render,
19210                 programs: null,
19211                 autoReset: true,
19212                 reset: reset,
19213                 update: update
19214         };
19215
19216     }
19217
19218     function numericalSort( a, b ) {
19219
19220         return a[ 0 ] - b[ 0 ];
19221
19222     }
19223
19224     function absNumericalSort( a, b ) {
19225
19226         return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
19227
19228     }
19229
19230     function WebGLMorphtargets( gl ) {
19231
19232         const influencesList = {};
19233         const morphInfluences = new Float32Array( 8 );
19234
19235         const workInfluences = [];
19236
19237         for ( let i = 0; i < 8; i ++ ) {
19238
19239                 workInfluences[ i ] = [ i, 0 ];
19240
19241         }
19242
19243         function update( object, geometry, material, program ) {
19244
19245                 const objectInfluences = object.morphTargetInfluences;
19246
19247                 // When object doesn't have morph target influences defined, we treat it as a 0-length array
19248                 // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
19249
19250                 const length = objectInfluences === undefined ? 0 : objectInfluences.length;
19251
19252                 let influences = influencesList[ geometry.id ];
19253
19254                 if ( influences === undefined ) {
19255
19256                         // initialise list
19257
19258                         influences = [];
19259
19260                         for ( let i = 0; i < length; i ++ ) {
19261
19262                                 influences[ i ] = [ i, 0 ];
19263
19264                         }
19265
19266                         influencesList[ geometry.id ] = influences;
19267
19268                 }
19269
19270                 // Collect influences
19271
19272                 for ( let i = 0; i < length; i ++ ) {
19273
19274                         const influence = influences[ i ];
19275
19276                         influence[ 0 ] = i;
19277                         influence[ 1 ] = objectInfluences[ i ];
19278
19279                 }
19280
19281                 influences.sort( absNumericalSort );
19282
19283                 for ( let i = 0; i < 8; i ++ ) {
19284
19285                         if ( i < length && influences[ i ][ 1 ] ) {
19286
19287                                 workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
19288                                 workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
19289
19290                         } else {
19291
19292                                 workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
19293                                 workInfluences[ i ][ 1 ] = 0;
19294
19295                         }
19296
19297                 }
19298
19299                 workInfluences.sort( numericalSort );
19300
19301                 const morphTargets = material.morphTargets && geometry.morphAttributes.position;
19302                 const morphNormals = material.morphNormals && geometry.morphAttributes.normal;
19303
19304                 let morphInfluencesSum = 0;
19305
19306                 for ( let i = 0; i < 8; i ++ ) {
19307
19308                         const influence = workInfluences[ i ];
19309                         const index = influence[ 0 ];
19310                         const value = influence[ 1 ];
19311
19312                         if ( index !== Number.MAX_SAFE_INTEGER && value ) {
19313
19314                                 if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
19315
19316                                         geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
19317
19318                                 }
19319
19320                                 if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
19321
19322                                         geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
19323
19324                                 }
19325
19326                                 morphInfluences[ i ] = value;
19327                                 morphInfluencesSum += value;
19328
19329                         } else {
19330
19331                                 if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
19332
19333                                         geometry.deleteAttribute( 'morphTarget' + i );
19334
19335                                 }
19336
19337                                 if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
19338
19339                                         geometry.deleteAttribute( 'morphNormal' + i );
19340
19341                                 }
19342
19343                                 morphInfluences[ i ] = 0;
19344
19345                         }
19346
19347                 }
19348
19349                 // GLSL shader uses formula baseinfluence * base + sum(target * influence)
19350                 // This allows us to switch between absolute morphs and relative morphs without changing shader code
19351                 // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
19352                 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
19353
19354                 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
19355                 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
19356
19357         }
19358
19359         return {
19360
19361                 update: update
19362
19363         };
19364
19365     }
19366
19367     function WebGLObjects( gl, geometries, attributes, info ) {
19368
19369         let updateMap = new WeakMap();
19370
19371         function update( object ) {
19372
19373                 const frame = info.render.frame;
19374
19375                 const geometry = object.geometry;
19376                 const buffergeometry = geometries.get( object, geometry );
19377
19378                 // Update once per frame
19379
19380                 if ( updateMap.get( buffergeometry ) !== frame ) {
19381
19382                         geometries.update( buffergeometry );
19383
19384                         updateMap.set( buffergeometry, frame );
19385
19386                 }
19387
19388                 if ( object.isInstancedMesh ) {
19389
19390                         if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
19391
19392                                 object.addEventListener( 'dispose', onInstancedMeshDispose );
19393
19394                         }
19395
19396                         attributes.update( object.instanceMatrix, 34962 );
19397
19398                         if ( object.instanceColor !== null ) {
19399
19400                                 attributes.update( object.instanceColor, 34962 );
19401
19402                         }
19403
19404                 }
19405
19406                 return buffergeometry;
19407
19408         }
19409
19410         function dispose() {
19411
19412                 updateMap = new WeakMap();
19413
19414         }
19415
19416         function onInstancedMeshDispose( event ) {
19417
19418                 const instancedMesh = event.target;
19419
19420                 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
19421
19422                 attributes.remove( instancedMesh.instanceMatrix );
19423
19424                 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
19425
19426         }
19427
19428         return {
19429
19430                 update: update,
19431                 dispose: dispose
19432
19433         };
19434
19435     }
19436
19437     function DataTexture2DArray( data = null, width = 1, height = 1, depth = 1 ) {
19438
19439         Texture.call( this, null );
19440
19441         this.image = { data, width, height, depth };
19442
19443         this.magFilter = NearestFilter;
19444         this.minFilter = NearestFilter;
19445
19446         this.wrapR = ClampToEdgeWrapping;
19447
19448         this.generateMipmaps = false;
19449         this.flipY = false;
19450
19451         this.needsUpdate = true;
19452
19453     }
19454
19455     DataTexture2DArray.prototype = Object.create( Texture.prototype );
19456     DataTexture2DArray.prototype.constructor = DataTexture2DArray;
19457     DataTexture2DArray.prototype.isDataTexture2DArray = true;
19458
19459     function DataTexture3D( data = null, width = 1, height = 1, depth = 1 ) {
19460
19461         // We're going to add .setXXX() methods for setting properties later.
19462         // Users can still set in DataTexture3D directly.
19463         //
19464         //      const texture = new THREE.DataTexture3D( data, width, height, depth );
19465         //      texture.anisotropy = 16;
19466         //
19467         // See #14839
19468
19469         Texture.call( this, null );
19470
19471         this.image = { data, width, height, depth };
19472
19473         this.magFilter = NearestFilter;
19474         this.minFilter = NearestFilter;
19475
19476         this.wrapR = ClampToEdgeWrapping;
19477
19478         this.generateMipmaps = false;
19479         this.flipY = false;
19480
19481         this.needsUpdate = true;
19482
19483
19484     }
19485
19486     DataTexture3D.prototype = Object.create( Texture.prototype );
19487     DataTexture3D.prototype.constructor = DataTexture3D;
19488     DataTexture3D.prototype.isDataTexture3D = true;
19489
19490     /**
19491      * Uniforms of a program.
19492      * Those form a tree structure with a special top-level container for the root,
19493      * which you get by calling 'new WebGLUniforms( gl, program )'.
19494      *
19495      *
19496      * Properties of inner nodes including the top-level container:
19497      *
19498      * .seq - array of nested uniforms
19499      * .map - nested uniforms by name
19500      *
19501      *
19502      * Methods of all nodes except the top-level container:
19503      *
19504      * .setValue( gl, value, [textures] )
19505      *
19506      *          uploads a uniform value(s)
19507      *          the 'textures' parameter is needed for sampler uniforms
19508      *
19509      *
19510      * Static methods of the top-level container (textures factorizations):
19511      *
19512      * .upload( gl, seq, values, textures )
19513      *
19514      *          sets uniforms in 'seq' to 'values[id].value'
19515      *
19516      * .seqWithValue( seq, values ) : filteredSeq
19517      *
19518      *          filters 'seq' entries with corresponding entry in values
19519      *
19520      *
19521      * Methods of the top-level container (textures factorizations):
19522      *
19523      * .setValue( gl, name, value, textures )
19524      *
19525      *          sets uniform with  name 'name' to 'value'
19526      *
19527      * .setOptional( gl, obj, prop )
19528      *
19529      *          like .set for an optional property of the object
19530      *
19531      */
19532
19533     const emptyTexture = new Texture();
19534     const emptyTexture2dArray = new DataTexture2DArray();
19535     const emptyTexture3d = new DataTexture3D();
19536     const emptyCubeTexture = new CubeTexture();
19537
19538     // --- Utilities ---
19539
19540     // Array Caches (provide typed arrays for temporary by size)
19541
19542     const arrayCacheF32 = [];
19543     const arrayCacheI32 = [];
19544
19545     // Float32Array caches used for uploading Matrix uniforms
19546
19547     const mat4array = new Float32Array( 16 );
19548     const mat3array = new Float32Array( 9 );
19549     const mat2array = new Float32Array( 4 );
19550
19551     // Flattening for arrays of vectors and matrices
19552
19553     function flatten( array, nBlocks, blockSize ) {
19554
19555         const firstElem = array[ 0 ];
19556
19557         if ( firstElem <= 0 || firstElem > 0 ) return array;
19558         // unoptimized: ! isNaN( firstElem )
19559         // see http://jacksondunstan.com/articles/983
19560
19561         const n = nBlocks * blockSize;
19562         let r = arrayCacheF32[ n ];
19563
19564         if ( r === undefined ) {
19565
19566                 r = new Float32Array( n );
19567                 arrayCacheF32[ n ] = r;
19568
19569         }
19570
19571         if ( nBlocks !== 0 ) {
19572
19573                 firstElem.toArray( r, 0 );
19574
19575                 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
19576
19577                         offset += blockSize;
19578                         array[ i ].toArray( r, offset );
19579
19580                 }
19581
19582         }
19583
19584         return r;
19585
19586     }
19587
19588     function arraysEqual( a, b ) {
19589
19590         if ( a.length !== b.length ) return false;
19591
19592         for ( let i = 0, l = a.length; i < l; i ++ ) {
19593
19594                 if ( a[ i ] !== b[ i ] ) return false;
19595
19596         }
19597
19598         return true;
19599
19600     }
19601
19602     function copyArray( a, b ) {
19603
19604         for ( let i = 0, l = b.length; i < l; i ++ ) {
19605
19606                 a[ i ] = b[ i ];
19607
19608         }
19609
19610     }
19611
19612     // Texture unit allocation
19613
19614     function allocTexUnits( textures, n ) {
19615
19616         let r = arrayCacheI32[ n ];
19617
19618         if ( r === undefined ) {
19619
19620                 r = new Int32Array( n );
19621                 arrayCacheI32[ n ] = r;
19622
19623         }
19624
19625         for ( let i = 0; i !== n; ++ i ) {
19626
19627                 r[ i ] = textures.allocateTextureUnit();
19628
19629         }
19630
19631         return r;
19632
19633     }
19634
19635     // --- Setters ---
19636
19637     // Note: Defining these methods externally, because they come in a bunch
19638     // and this way their names minify.
19639
19640     // Single scalar
19641
19642     function setValueV1f( gl, v ) {
19643
19644         const cache = this.cache;
19645
19646         if ( cache[ 0 ] === v ) return;
19647
19648         gl.uniform1f( this.addr, v );
19649
19650         cache[ 0 ] = v;
19651
19652     }
19653
19654     // Single float vector (from flat array or THREE.VectorN)
19655
19656     function setValueV2f( gl, v ) {
19657
19658         const cache = this.cache;
19659
19660         if ( v.x !== undefined ) {
19661
19662                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
19663
19664                         gl.uniform2f( this.addr, v.x, v.y );
19665
19666                         cache[ 0 ] = v.x;
19667                         cache[ 1 ] = v.y;
19668
19669                 }
19670
19671         } else {
19672
19673                 if ( arraysEqual( cache, v ) ) return;
19674
19675                 gl.uniform2fv( this.addr, v );
19676
19677                 copyArray( cache, v );
19678
19679         }
19680
19681     }
19682
19683     function setValueV3f( gl, v ) {
19684
19685         const cache = this.cache;
19686
19687         if ( v.x !== undefined ) {
19688
19689                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
19690
19691                         gl.uniform3f( this.addr, v.x, v.y, v.z );
19692
19693                         cache[ 0 ] = v.x;
19694                         cache[ 1 ] = v.y;
19695                         cache[ 2 ] = v.z;
19696
19697                 }
19698
19699         } else if ( v.r !== undefined ) {
19700
19701                 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
19702
19703                         gl.uniform3f( this.addr, v.r, v.g, v.b );
19704
19705                         cache[ 0 ] = v.r;
19706                         cache[ 1 ] = v.g;
19707                         cache[ 2 ] = v.b;
19708
19709                 }
19710
19711         } else {
19712
19713                 if ( arraysEqual( cache, v ) ) return;
19714
19715                 gl.uniform3fv( this.addr, v );
19716
19717                 copyArray( cache, v );
19718
19719         }
19720
19721     }
19722
19723     function setValueV4f( gl, v ) {
19724
19725         const cache = this.cache;
19726
19727         if ( v.x !== undefined ) {
19728
19729                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
19730
19731                         gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
19732
19733                         cache[ 0 ] = v.x;
19734                         cache[ 1 ] = v.y;
19735                         cache[ 2 ] = v.z;
19736                         cache[ 3 ] = v.w;
19737
19738                 }
19739
19740         } else {
19741
19742                 if ( arraysEqual( cache, v ) ) return;
19743
19744                 gl.uniform4fv( this.addr, v );
19745
19746                 copyArray( cache, v );
19747
19748         }
19749
19750     }
19751
19752     // Single matrix (from flat array or MatrixN)
19753
19754     function setValueM2( gl, v ) {
19755
19756         const cache = this.cache;
19757         const elements = v.elements;
19758
19759         if ( elements === undefined ) {
19760
19761                 if ( arraysEqual( cache, v ) ) return;
19762
19763                 gl.uniformMatrix2fv( this.addr, false, v );
19764
19765                 copyArray( cache, v );
19766
19767         } else {
19768
19769                 if ( arraysEqual( cache, elements ) ) return;
19770
19771                 mat2array.set( elements );
19772
19773                 gl.uniformMatrix2fv( this.addr, false, mat2array );
19774
19775                 copyArray( cache, elements );
19776
19777         }
19778
19779     }
19780
19781     function setValueM3( gl, v ) {
19782
19783         const cache = this.cache;
19784         const elements = v.elements;
19785
19786         if ( elements === undefined ) {
19787
19788                 if ( arraysEqual( cache, v ) ) return;
19789
19790                 gl.uniformMatrix3fv( this.addr, false, v );
19791
19792                 copyArray( cache, v );
19793
19794         } else {
19795
19796                 if ( arraysEqual( cache, elements ) ) return;
19797
19798                 mat3array.set( elements );
19799
19800                 gl.uniformMatrix3fv( this.addr, false, mat3array );
19801
19802                 copyArray( cache, elements );
19803
19804         }
19805
19806     }
19807
19808     function setValueM4( gl, v ) {
19809
19810         const cache = this.cache;
19811         const elements = v.elements;
19812
19813         if ( elements === undefined ) {
19814
19815                 if ( arraysEqual( cache, v ) ) return;
19816
19817                 gl.uniformMatrix4fv( this.addr, false, v );
19818
19819                 copyArray( cache, v );
19820
19821         } else {
19822
19823                 if ( arraysEqual( cache, elements ) ) return;
19824
19825                 mat4array.set( elements );
19826
19827                 gl.uniformMatrix4fv( this.addr, false, mat4array );
19828
19829                 copyArray( cache, elements );
19830
19831         }
19832
19833     }
19834
19835     // Single texture (2D / Cube)
19836
19837     function setValueT1( gl, v, textures ) {
19838
19839         const cache = this.cache;
19840         const unit = textures.allocateTextureUnit();
19841
19842         if ( cache[ 0 ] !== unit ) {
19843
19844                 gl.uniform1i( this.addr, unit );
19845                 cache[ 0 ] = unit;
19846
19847         }
19848
19849         textures.safeSetTexture2D( v || emptyTexture, unit );
19850
19851     }
19852
19853     function setValueT2DArray1( gl, v, textures ) {
19854
19855         const cache = this.cache;
19856         const unit = textures.allocateTextureUnit();
19857
19858         if ( cache[ 0 ] !== unit ) {
19859
19860                 gl.uniform1i( this.addr, unit );
19861                 cache[ 0 ] = unit;
19862
19863         }
19864
19865         textures.setTexture2DArray( v || emptyTexture2dArray, unit );
19866
19867     }
19868
19869     function setValueT3D1( gl, v, textures ) {
19870
19871         const cache = this.cache;
19872         const unit = textures.allocateTextureUnit();
19873
19874         if ( cache[ 0 ] !== unit ) {
19875
19876                 gl.uniform1i( this.addr, unit );
19877                 cache[ 0 ] = unit;
19878
19879         }
19880
19881         textures.setTexture3D( v || emptyTexture3d, unit );
19882
19883     }
19884
19885     function setValueT6( gl, v, textures ) {
19886
19887         const cache = this.cache;
19888         const unit = textures.allocateTextureUnit();
19889
19890         if ( cache[ 0 ] !== unit ) {
19891
19892                 gl.uniform1i( this.addr, unit );
19893                 cache[ 0 ] = unit;
19894
19895         }
19896
19897         textures.safeSetTextureCube( v || emptyCubeTexture, unit );
19898
19899     }
19900
19901     // Integer / Boolean vectors or arrays thereof (always flat arrays)
19902
19903     function setValueV1i( gl, v ) {
19904
19905         const cache = this.cache;
19906
19907         if ( cache[ 0 ] === v ) return;
19908
19909         gl.uniform1i( this.addr, v );
19910
19911         cache[ 0 ] = v;
19912
19913     }
19914
19915     function setValueV2i( gl, v ) {
19916
19917         const cache = this.cache;
19918
19919         if ( arraysEqual( cache, v ) ) return;
19920
19921         gl.uniform2iv( this.addr, v );
19922
19923         copyArray( cache, v );
19924
19925     }
19926
19927     function setValueV3i( gl, v ) {
19928
19929         const cache = this.cache;
19930
19931         if ( arraysEqual( cache, v ) ) return;
19932
19933         gl.uniform3iv( this.addr, v );
19934
19935         copyArray( cache, v );
19936
19937     }
19938
19939     function setValueV4i( gl, v ) {
19940
19941         const cache = this.cache;
19942
19943         if ( arraysEqual( cache, v ) ) return;
19944
19945         gl.uniform4iv( this.addr, v );
19946
19947         copyArray( cache, v );
19948
19949     }
19950
19951     // uint
19952
19953     function setValueV1ui( gl, v ) {
19954
19955         const cache = this.cache;
19956
19957         if ( cache[ 0 ] === v ) return;
19958
19959         gl.uniform1ui( this.addr, v );
19960
19961         cache[ 0 ] = v;
19962
19963     }
19964
19965     // Helper to pick the right setter for the singular case
19966
19967     function getSingularSetter( type ) {
19968
19969         switch ( type ) {
19970
19971                 case 0x1406: return setValueV1f; // FLOAT
19972                 case 0x8b50: return setValueV2f; // _VEC2
19973                 case 0x8b51: return setValueV3f; // _VEC3
19974                 case 0x8b52: return setValueV4f; // _VEC4
19975
19976                 case 0x8b5a: return setValueM2; // _MAT2
19977                 case 0x8b5b: return setValueM3; // _MAT3
19978                 case 0x8b5c: return setValueM4; // _MAT4
19979
19980                 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
19981                 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
19982                 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
19983                 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
19984
19985                 case 0x1405: return setValueV1ui; // UINT
19986
19987                 case 0x8b5e: // SAMPLER_2D
19988                 case 0x8d66: // SAMPLER_EXTERNAL_OES
19989                 case 0x8dca: // INT_SAMPLER_2D
19990                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
19991                 case 0x8b62: // SAMPLER_2D_SHADOW
19992                         return setValueT1;
19993
19994                 case 0x8b5f: // SAMPLER_3D
19995                 case 0x8dcb: // INT_SAMPLER_3D
19996                 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
19997                         return setValueT3D1;
19998
19999                 case 0x8b60: // SAMPLER_CUBE
20000                 case 0x8dcc: // INT_SAMPLER_CUBE
20001                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
20002                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
20003                         return setValueT6;
20004
20005                 case 0x8dc1: // SAMPLER_2D_ARRAY
20006                 case 0x8dcf: // INT_SAMPLER_2D_ARRAY
20007                 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
20008                 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
20009                         return setValueT2DArray1;
20010
20011         }
20012
20013     }
20014
20015     // Array of scalars
20016     function setValueV1fArray( gl, v ) {
20017
20018         gl.uniform1fv( this.addr, v );
20019
20020     }
20021
20022     // Integer / Boolean vectors or arrays thereof (always flat arrays)
20023     function setValueV1iArray( gl, v ) {
20024
20025         gl.uniform1iv( this.addr, v );
20026
20027     }
20028
20029     function setValueV2iArray( gl, v ) {
20030
20031         gl.uniform2iv( this.addr, v );
20032
20033     }
20034
20035     function setValueV3iArray( gl, v ) {
20036
20037         gl.uniform3iv( this.addr, v );
20038
20039     }
20040
20041     function setValueV4iArray( gl, v ) {
20042
20043         gl.uniform4iv( this.addr, v );
20044
20045     }
20046
20047
20048     // Array of vectors (flat or from THREE classes)
20049
20050     function setValueV2fArray( gl, v ) {
20051
20052         const data = flatten( v, this.size, 2 );
20053
20054         gl.uniform2fv( this.addr, data );
20055
20056     }
20057
20058     function setValueV3fArray( gl, v ) {
20059
20060         const data = flatten( v, this.size, 3 );
20061
20062         gl.uniform3fv( this.addr, data );
20063
20064     }
20065
20066     function setValueV4fArray( gl, v ) {
20067
20068         const data = flatten( v, this.size, 4 );
20069
20070         gl.uniform4fv( this.addr, data );
20071
20072     }
20073
20074     // Array of matrices (flat or from THREE clases)
20075
20076     function setValueM2Array( gl, v ) {
20077
20078         const data = flatten( v, this.size, 4 );
20079
20080         gl.uniformMatrix2fv( this.addr, false, data );
20081
20082     }
20083
20084     function setValueM3Array( gl, v ) {
20085
20086         const data = flatten( v, this.size, 9 );
20087
20088         gl.uniformMatrix3fv( this.addr, false, data );
20089
20090     }
20091
20092     function setValueM4Array( gl, v ) {
20093
20094         const data = flatten( v, this.size, 16 );
20095
20096         gl.uniformMatrix4fv( this.addr, false, data );
20097
20098     }
20099
20100     // Array of textures (2D / Cube)
20101
20102     function setValueT1Array( gl, v, textures ) {
20103
20104         const n = v.length;
20105
20106         const units = allocTexUnits( textures, n );
20107
20108         gl.uniform1iv( this.addr, units );
20109
20110         for ( let i = 0; i !== n; ++ i ) {
20111
20112                 textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
20113
20114         }
20115
20116     }
20117
20118     function setValueT6Array( gl, v, textures ) {
20119
20120         const n = v.length;
20121
20122         const units = allocTexUnits( textures, n );
20123
20124         gl.uniform1iv( this.addr, units );
20125
20126         for ( let i = 0; i !== n; ++ i ) {
20127
20128                 textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
20129
20130         }
20131
20132     }
20133
20134     // Helper to pick the right setter for a pure (bottom-level) array
20135
20136     function getPureArraySetter( type ) {
20137
20138         switch ( type ) {
20139
20140                 case 0x1406: return setValueV1fArray; // FLOAT
20141                 case 0x8b50: return setValueV2fArray; // _VEC2
20142                 case 0x8b51: return setValueV3fArray; // _VEC3
20143                 case 0x8b52: return setValueV4fArray; // _VEC4
20144
20145                 case 0x8b5a: return setValueM2Array; // _MAT2
20146                 case 0x8b5b: return setValueM3Array; // _MAT3
20147                 case 0x8b5c: return setValueM4Array; // _MAT4
20148
20149                 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
20150                 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
20151                 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
20152                 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
20153
20154                 case 0x8b5e: // SAMPLER_2D
20155                 case 0x8d66: // SAMPLER_EXTERNAL_OES
20156                 case 0x8dca: // INT_SAMPLER_2D
20157                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
20158                 case 0x8b62: // SAMPLER_2D_SHADOW
20159                         return setValueT1Array;
20160
20161                 case 0x8b60: // SAMPLER_CUBE
20162                 case 0x8dcc: // INT_SAMPLER_CUBE
20163                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
20164                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
20165                         return setValueT6Array;
20166
20167         }
20168
20169     }
20170
20171     // --- Uniform Classes ---
20172
20173     function SingleUniform( id, activeInfo, addr ) {
20174
20175         this.id = id;
20176         this.addr = addr;
20177         this.cache = [];
20178         this.setValue = getSingularSetter( activeInfo.type );
20179
20180         // this.path = activeInfo.name; // DEBUG
20181
20182     }
20183
20184     function PureArrayUniform( id, activeInfo, addr ) {
20185
20186         this.id = id;
20187         this.addr = addr;
20188         this.cache = [];
20189         this.size = activeInfo.size;
20190         this.setValue = getPureArraySetter( activeInfo.type );
20191
20192         // this.path = activeInfo.name; // DEBUG
20193
20194     }
20195
20196     PureArrayUniform.prototype.updateCache = function ( data ) {
20197
20198         const cache = this.cache;
20199
20200         if ( data instanceof Float32Array && cache.length !== data.length ) {
20201
20202                 this.cache = new Float32Array( data.length );
20203
20204         }
20205
20206         copyArray( cache, data );
20207
20208     };
20209
20210     function StructuredUniform( id ) {
20211
20212         this.id = id;
20213
20214         this.seq = [];
20215         this.map = {};
20216
20217     }
20218
20219     StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
20220
20221         const seq = this.seq;
20222
20223         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20224
20225                 const u = seq[ i ];
20226                 u.setValue( gl, value[ u.id ], textures );
20227
20228         }
20229
20230     };
20231
20232     // --- Top-level ---
20233
20234     // Parser - builds up the property tree from the path strings
20235
20236     const RePathPart = /(\w+)(\])?(\[|\.)?/g;
20237
20238     // extracts
20239     //  - the identifier (member name or array index)
20240     //  - followed by an optional right bracket (found when array index)
20241     //  - followed by an optional left bracket or dot (type of subscript)
20242     //
20243     // Note: These portions can be read in a non-overlapping fashion and
20244     // allow straightforward parsing of the hierarchy that WebGL encodes
20245     // in the uniform names.
20246
20247     function addUniform( container, uniformObject ) {
20248
20249         container.seq.push( uniformObject );
20250         container.map[ uniformObject.id ] = uniformObject;
20251
20252     }
20253
20254     function parseUniform( activeInfo, addr, container ) {
20255
20256         const path = activeInfo.name,
20257                 pathLength = path.length;
20258
20259         // reset RegExp object, because of the early exit of a previous run
20260         RePathPart.lastIndex = 0;
20261
20262         while ( true ) {
20263
20264                 const match = RePathPart.exec( path ),
20265                         matchEnd = RePathPart.lastIndex;
20266
20267                 let id = match[ 1 ];
20268                 const idIsIndex = match[ 2 ] === ']',
20269                         subscript = match[ 3 ];
20270
20271                 if ( idIsIndex ) id = id | 0; // convert to integer
20272
20273                 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
20274
20275                         // bare name or "pure" bottom-level array "[0]" suffix
20276
20277                         addUniform( container, subscript === undefined ?
20278                                 new SingleUniform( id, activeInfo, addr ) :
20279                                 new PureArrayUniform( id, activeInfo, addr ) );
20280
20281                         break;
20282
20283                 } else {
20284
20285                         // step into inner node / create it in case it doesn't exist
20286
20287                         const map = container.map;
20288                         let next = map[ id ];
20289
20290                         if ( next === undefined ) {
20291
20292                                 next = new StructuredUniform( id );
20293                                 addUniform( container, next );
20294
20295                         }
20296
20297                         container = next;
20298
20299                 }
20300
20301         }
20302
20303     }
20304
20305     // Root Container
20306
20307     function WebGLUniforms( gl, program ) {
20308
20309         this.seq = [];
20310         this.map = {};
20311
20312         const n = gl.getProgramParameter( program, 35718 );
20313
20314         for ( let i = 0; i < n; ++ i ) {
20315
20316                 const info = gl.getActiveUniform( program, i ),
20317                         addr = gl.getUniformLocation( program, info.name );
20318
20319                 parseUniform( info, addr, this );
20320
20321         }
20322
20323     }
20324
20325     WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
20326
20327         const u = this.map[ name ];
20328
20329         if ( u !== undefined ) u.setValue( gl, value, textures );
20330
20331     };
20332
20333     WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
20334
20335         const v = object[ name ];
20336
20337         if ( v !== undefined ) this.setValue( gl, name, v );
20338
20339     };
20340
20341
20342     // Static interface
20343
20344     WebGLUniforms.upload = function ( gl, seq, values, textures ) {
20345
20346         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20347
20348                 const u = seq[ i ],
20349                         v = values[ u.id ];
20350
20351                 if ( v.needsUpdate !== false ) {
20352
20353                         // note: always updating when .needsUpdate is undefined
20354                         u.setValue( gl, v.value, textures );
20355
20356                 }
20357
20358         }
20359
20360     };
20361
20362     WebGLUniforms.seqWithValue = function ( seq, values ) {
20363
20364         const r = [];
20365
20366         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20367
20368                 const u = seq[ i ];
20369                 if ( u.id in values ) r.push( u );
20370
20371         }
20372
20373         return r;
20374
20375     };
20376
20377     function WebGLShader( gl, type, string ) {
20378
20379         const shader = gl.createShader( type );
20380
20381         gl.shaderSource( shader, string );
20382         gl.compileShader( shader );
20383
20384         return shader;
20385
20386     }
20387
20388     let programIdCount = 0;
20389
20390     function addLineNumbers( string ) {
20391
20392         const lines = string.split( '\n' );
20393
20394         for ( let i = 0; i < lines.length; i ++ ) {
20395
20396                 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
20397
20398         }
20399
20400         return lines.join( '\n' );
20401
20402     }
20403
20404     function getEncodingComponents( encoding ) {
20405
20406         switch ( encoding ) {
20407
20408                 case LinearEncoding:
20409                         return [ 'Linear', '( value )' ];
20410                 case sRGBEncoding:
20411                         return [ 'sRGB', '( value )' ];
20412                 case RGBEEncoding:
20413                         return [ 'RGBE', '( value )' ];
20414                 case RGBM7Encoding:
20415                         return [ 'RGBM', '( value, 7.0 )' ];
20416                 case RGBM16Encoding:
20417                         return [ 'RGBM', '( value, 16.0 )' ];
20418                 case RGBDEncoding:
20419                         return [ 'RGBD', '( value, 256.0 )' ];
20420                 case GammaEncoding:
20421                         return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
20422                 case LogLuvEncoding:
20423                         return [ 'LogLuv', '( value )' ];
20424                 default:
20425                         console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
20426                         return [ 'Linear', '( value )' ];
20427
20428         }
20429
20430     }
20431
20432     function getShaderErrors( gl, shader, type ) {
20433
20434         const status = gl.getShaderParameter( shader, 35713 );
20435         const log = gl.getShaderInfoLog( shader ).trim();
20436
20437         if ( status && log === '' ) return '';
20438
20439         // --enable-privileged-webgl-extension
20440         // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
20441
20442         const source = gl.getShaderSource( shader );
20443
20444         return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
20445
20446     }
20447
20448     function getTexelDecodingFunction( functionName, encoding ) {
20449
20450         const components = getEncodingComponents( encoding );
20451         return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
20452
20453     }
20454
20455     function getTexelEncodingFunction( functionName, encoding ) {
20456
20457         const components = getEncodingComponents( encoding );
20458         return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
20459
20460     }
20461
20462     function getToneMappingFunction( functionName, toneMapping ) {
20463
20464         let toneMappingName;
20465
20466         switch ( toneMapping ) {
20467
20468                 case LinearToneMapping:
20469                         toneMappingName = 'Linear';
20470                         break;
20471
20472                 case ReinhardToneMapping:
20473                         toneMappingName = 'Reinhard';
20474                         break;
20475
20476                 case CineonToneMapping:
20477                         toneMappingName = 'OptimizedCineon';
20478                         break;
20479
20480                 case ACESFilmicToneMapping:
20481                         toneMappingName = 'ACESFilmic';
20482                         break;
20483
20484                 case CustomToneMapping:
20485                         toneMappingName = 'Custom';
20486                         break;
20487
20488                 default:
20489                         console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
20490                         toneMappingName = 'Linear';
20491
20492         }
20493
20494         return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
20495
20496     }
20497
20498     function generateExtensions( parameters ) {
20499
20500         const chunks = [
20501                 ( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
20502                 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
20503                 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
20504                 ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
20505         ];
20506
20507         return chunks.filter( filterEmptyLine ).join( '\n' );
20508
20509     }
20510
20511     function generateDefines( defines ) {
20512
20513         const chunks = [];
20514
20515         for ( const name in defines ) {
20516
20517                 const value = defines[ name ];
20518
20519                 if ( value === false ) continue;
20520
20521                 chunks.push( '#define ' + name + ' ' + value );
20522
20523         }
20524
20525         return chunks.join( '\n' );
20526
20527     }
20528
20529     function fetchAttributeLocations( gl, program ) {
20530
20531         const attributes = {};
20532
20533         const n = gl.getProgramParameter( program, 35721 );
20534
20535         for ( let i = 0; i < n; i ++ ) {
20536
20537                 const info = gl.getActiveAttrib( program, i );
20538                 const name = info.name;
20539
20540                 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
20541
20542                 attributes[ name ] = gl.getAttribLocation( program, name );
20543
20544         }
20545
20546         return attributes;
20547
20548     }
20549
20550     function filterEmptyLine( string ) {
20551
20552         return string !== '';
20553
20554     }
20555
20556     function replaceLightNums( string, parameters ) {
20557
20558         return string
20559                 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
20560                 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
20561                 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
20562                 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
20563                 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
20564                 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
20565                 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
20566                 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
20567
20568     }
20569
20570     function replaceClippingPlaneNums( string, parameters ) {
20571
20572         return string
20573                 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
20574                 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
20575
20576     }
20577
20578     // Resolve Includes
20579
20580     const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
20581
20582     function resolveIncludes( string ) {
20583
20584         return string.replace( includePattern, includeReplacer );
20585
20586     }
20587
20588     function includeReplacer( match, include ) {
20589
20590         const string = ShaderChunk[ include ];
20591
20592         if ( string === undefined ) {
20593
20594                 throw new Error( 'Can not resolve #include <' + include + '>' );
20595
20596         }
20597
20598         return resolveIncludes( string );
20599
20600     }
20601
20602     // Unroll Loops
20603
20604     const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
20605     const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;
20606
20607     function unrollLoops( string ) {
20608
20609         return string
20610                 .replace( unrollLoopPattern, loopReplacer )
20611                 .replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
20612
20613     }
20614
20615     function deprecatedLoopReplacer( match, start, end, snippet ) {
20616
20617         console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
20618         return loopReplacer( match, start, end, snippet );
20619
20620     }
20621
20622     function loopReplacer( match, start, end, snippet ) {
20623
20624         let string = '';
20625
20626         for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
20627
20628                 string += snippet
20629                         .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
20630                         .replace( /UNROLLED_LOOP_INDEX/g, i );
20631
20632         }
20633
20634         return string;
20635
20636     }
20637
20638     //
20639
20640     function generatePrecision( parameters ) {
20641
20642         let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
20643
20644         if ( parameters.precision === 'highp' ) {
20645
20646                 precisionstring += '\n#define HIGH_PRECISION';
20647
20648         } else if ( parameters.precision === 'mediump' ) {
20649
20650                 precisionstring += '\n#define MEDIUM_PRECISION';
20651
20652         } else if ( parameters.precision === 'lowp' ) {
20653
20654                 precisionstring += '\n#define LOW_PRECISION';
20655
20656         }
20657
20658         return precisionstring;
20659
20660     }
20661
20662     function generateShadowMapTypeDefine( parameters ) {
20663
20664         let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
20665
20666         if ( parameters.shadowMapType === PCFShadowMap ) {
20667
20668                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
20669
20670         } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
20671
20672                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
20673
20674         } else if ( parameters.shadowMapType === VSMShadowMap ) {
20675
20676                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
20677
20678         }
20679
20680         return shadowMapTypeDefine;
20681
20682     }
20683
20684     function generateEnvMapTypeDefine( parameters ) {
20685
20686         let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
20687
20688         if ( parameters.envMap ) {
20689
20690                 switch ( parameters.envMapMode ) {
20691
20692                         case CubeReflectionMapping:
20693                         case CubeRefractionMapping:
20694                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
20695                                 break;
20696
20697                         case CubeUVReflectionMapping:
20698                         case CubeUVRefractionMapping:
20699                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
20700                                 break;
20701
20702                 }
20703
20704         }
20705
20706         return envMapTypeDefine;
20707
20708     }
20709
20710     function generateEnvMapModeDefine( parameters ) {
20711
20712         let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
20713
20714         if ( parameters.envMap ) {
20715
20716                 switch ( parameters.envMapMode ) {
20717
20718                         case CubeRefractionMapping:
20719                         case CubeUVRefractionMapping:
20720
20721                                 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
20722                                 break;
20723
20724                 }
20725
20726         }
20727
20728         return envMapModeDefine;
20729
20730     }
20731
20732     function generateEnvMapBlendingDefine( parameters ) {
20733
20734         let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
20735
20736         if ( parameters.envMap ) {
20737
20738                 switch ( parameters.combine ) {
20739
20740                         case MultiplyOperation:
20741                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
20742                                 break;
20743
20744                         case MixOperation:
20745                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
20746                                 break;
20747
20748                         case AddOperation:
20749                                 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
20750                                 break;
20751
20752                 }
20753
20754         }
20755
20756         return envMapBlendingDefine;
20757
20758     }
20759
20760     function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
20761
20762         const gl = renderer.getContext();
20763
20764         const defines = parameters.defines;
20765
20766         let vertexShader = parameters.vertexShader;
20767         let fragmentShader = parameters.fragmentShader;
20768
20769         const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
20770         const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
20771         const envMapModeDefine = generateEnvMapModeDefine( parameters );
20772         const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
20773
20774
20775         const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
20776
20777         const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
20778
20779         const customDefines = generateDefines( defines );
20780
20781         const program = gl.createProgram();
20782
20783         let prefixVertex, prefixFragment;
20784         let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
20785
20786         if ( parameters.isRawShaderMaterial ) {
20787
20788                 prefixVertex = [
20789
20790                         customDefines
20791
20792                 ].filter( filterEmptyLine ).join( '\n' );
20793
20794                 if ( prefixVertex.length > 0 ) {
20795
20796                         prefixVertex += '\n';
20797
20798                 }
20799
20800                 prefixFragment = [
20801
20802                         customExtensions,
20803                         customDefines
20804
20805                 ].filter( filterEmptyLine ).join( '\n' );
20806
20807                 if ( prefixFragment.length > 0 ) {
20808
20809                         prefixFragment += '\n';
20810
20811                 }
20812
20813         } else {
20814
20815                 prefixVertex = [
20816
20817                         generatePrecision( parameters ),
20818
20819                         '#define SHADER_NAME ' + parameters.shaderName,
20820
20821                         customDefines,
20822
20823                         parameters.instancing ? '#define USE_INSTANCING' : '',
20824                         parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
20825
20826                         parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
20827
20828                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
20829
20830                         '#define MAX_BONES ' + parameters.maxBones,
20831                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
20832                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
20833
20834                         parameters.map ? '#define USE_MAP' : '',
20835                         parameters.envMap ? '#define USE_ENVMAP' : '',
20836                         parameters.envMap ? '#define ' + envMapModeDefine : '',
20837                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
20838                         parameters.aoMap ? '#define USE_AOMAP' : '',
20839                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
20840                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
20841                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
20842                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
20843                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
20844
20845                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
20846                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
20847                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
20848                         parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
20849                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
20850                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
20851                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
20852                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
20853                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
20854
20855                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
20856                         parameters.vertexColors ? '#define USE_COLOR' : '',
20857                         parameters.vertexUvs ? '#define USE_UV' : '',
20858                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
20859
20860                         parameters.flatShading ? '#define FLAT_SHADED' : '',
20861
20862                         parameters.skinning ? '#define USE_SKINNING' : '',
20863                         parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
20864
20865                         parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
20866                         parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
20867                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
20868                         parameters.flipSided ? '#define FLIP_SIDED' : '',
20869
20870                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
20871                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
20872
20873                         parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
20874
20875                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
20876                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
20877
20878                         'uniform mat4 modelMatrix;',
20879                         'uniform mat4 modelViewMatrix;',
20880                         'uniform mat4 projectionMatrix;',
20881                         'uniform mat4 viewMatrix;',
20882                         'uniform mat3 normalMatrix;',
20883                         'uniform vec3 cameraPosition;',
20884                         'uniform bool isOrthographic;',
20885
20886                         '#ifdef USE_INSTANCING',
20887
20888                         '       attribute mat4 instanceMatrix;',
20889
20890                         '#endif',
20891
20892                         '#ifdef USE_INSTANCING_COLOR',
20893
20894                         '       attribute vec3 instanceColor;',
20895
20896                         '#endif',
20897
20898                         'attribute vec3 position;',
20899                         'attribute vec3 normal;',
20900                         'attribute vec2 uv;',
20901
20902                         '#ifdef USE_TANGENT',
20903
20904                         '       attribute vec4 tangent;',
20905
20906                         '#endif',
20907
20908                         '#ifdef USE_COLOR',
20909
20910                         '       attribute vec3 color;',
20911
20912                         '#endif',
20913
20914                         '#ifdef USE_MORPHTARGETS',
20915
20916                         '       attribute vec3 morphTarget0;',
20917                         '       attribute vec3 morphTarget1;',
20918                         '       attribute vec3 morphTarget2;',
20919                         '       attribute vec3 morphTarget3;',
20920
20921                         '       #ifdef USE_MORPHNORMALS',
20922
20923                         '               attribute vec3 morphNormal0;',
20924                         '               attribute vec3 morphNormal1;',
20925                         '               attribute vec3 morphNormal2;',
20926                         '               attribute vec3 morphNormal3;',
20927
20928                         '       #else',
20929
20930                         '               attribute vec3 morphTarget4;',
20931                         '               attribute vec3 morphTarget5;',
20932                         '               attribute vec3 morphTarget6;',
20933                         '               attribute vec3 morphTarget7;',
20934
20935                         '       #endif',
20936
20937                         '#endif',
20938
20939                         '#ifdef USE_SKINNING',
20940
20941                         '       attribute vec4 skinIndex;',
20942                         '       attribute vec4 skinWeight;',
20943
20944                         '#endif',
20945
20946                         '\n'
20947
20948                 ].filter( filterEmptyLine ).join( '\n' );
20949
20950                 prefixFragment = [
20951
20952                         customExtensions,
20953
20954                         generatePrecision( parameters ),
20955
20956                         '#define SHADER_NAME ' + parameters.shaderName,
20957
20958                         customDefines,
20959
20960                         parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
20961
20962                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
20963
20964                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
20965                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
20966
20967                         parameters.map ? '#define USE_MAP' : '',
20968                         parameters.matcap ? '#define USE_MATCAP' : '',
20969                         parameters.envMap ? '#define USE_ENVMAP' : '',
20970                         parameters.envMap ? '#define ' + envMapTypeDefine : '',
20971                         parameters.envMap ? '#define ' + envMapModeDefine : '',
20972                         parameters.envMap ? '#define ' + envMapBlendingDefine : '',
20973                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
20974                         parameters.aoMap ? '#define USE_AOMAP' : '',
20975                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
20976                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
20977                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
20978                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
20979                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
20980                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
20981                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
20982                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
20983                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
20984                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
20985                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
20986                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
20987
20988                         parameters.sheen ? '#define USE_SHEEN' : '',
20989                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
20990
20991                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
20992                         parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
20993                         parameters.vertexUvs ? '#define USE_UV' : '',
20994                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
20995
20996                         parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
20997
20998                         parameters.flatShading ? '#define FLAT_SHADED' : '',
20999
21000                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
21001                         parameters.flipSided ? '#define FLIP_SIDED' : '',
21002
21003                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
21004                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
21005
21006                         parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
21007
21008                         parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
21009
21010                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
21011                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
21012
21013                         ( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
21014
21015                         'uniform mat4 viewMatrix;',
21016                         'uniform vec3 cameraPosition;',
21017                         'uniform bool isOrthographic;',
21018
21019                         ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
21020                         ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
21021                         ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
21022
21023                         parameters.dithering ? '#define DITHERING' : '',
21024
21025                         ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
21026                         parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
21027                         parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
21028                         parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
21029                         parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
21030                         parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
21031                         getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
21032
21033                         parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
21034
21035                         '\n'
21036
21037                 ].filter( filterEmptyLine ).join( '\n' );
21038
21039         }
21040
21041         vertexShader = resolveIncludes( vertexShader );
21042         vertexShader = replaceLightNums( vertexShader, parameters );
21043         vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
21044
21045         fragmentShader = resolveIncludes( fragmentShader );
21046         fragmentShader = replaceLightNums( fragmentShader, parameters );
21047         fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
21048
21049         vertexShader = unrollLoops( vertexShader );
21050         fragmentShader = unrollLoops( fragmentShader );
21051
21052         if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
21053
21054                 // GLSL 3.0 conversion for built-in materials and ShaderMaterial
21055
21056                 versionString = '#version 300 es\n';
21057
21058                 prefixVertex = [
21059                         '#define attribute in',
21060                         '#define varying out',
21061                         '#define texture2D texture'
21062                 ].join( '\n' ) + '\n' + prefixVertex;
21063
21064                 prefixFragment = [
21065                         '#define varying in',
21066                         ( parameters.glslVersion === GLSL3 ) ? '' : 'out highp vec4 pc_fragColor;',
21067                         ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
21068                         '#define gl_FragDepthEXT gl_FragDepth',
21069                         '#define texture2D texture',
21070                         '#define textureCube texture',
21071                         '#define texture2DProj textureProj',
21072                         '#define texture2DLodEXT textureLod',
21073                         '#define texture2DProjLodEXT textureProjLod',
21074                         '#define textureCubeLodEXT textureLod',
21075                         '#define texture2DGradEXT textureGrad',
21076                         '#define texture2DProjGradEXT textureProjGrad',
21077                         '#define textureCubeGradEXT textureGrad'
21078                 ].join( '\n' ) + '\n' + prefixFragment;
21079
21080         }
21081
21082         const vertexGlsl = versionString + prefixVertex + vertexShader;
21083         const fragmentGlsl = versionString + prefixFragment + fragmentShader;
21084
21085         // console.log( '*VERTEX*', vertexGlsl );
21086         // console.log( '*FRAGMENT*', fragmentGlsl );
21087
21088         const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
21089         const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
21090
21091         gl.attachShader( program, glVertexShader );
21092         gl.attachShader( program, glFragmentShader );
21093
21094         // Force a particular attribute to index 0.
21095
21096         if ( parameters.index0AttributeName !== undefined ) {
21097
21098                 gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
21099
21100         } else if ( parameters.morphTargets === true ) {
21101
21102                 // programs with morphTargets displace position out of attribute 0
21103                 gl.bindAttribLocation( program, 0, 'position' );
21104
21105         }
21106
21107         gl.linkProgram( program );
21108
21109         // check for link errors
21110         if ( renderer.debug.checkShaderErrors ) {
21111
21112                 const programLog = gl.getProgramInfoLog( program ).trim();
21113                 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
21114                 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
21115
21116                 let runnable = true;
21117                 let haveDiagnostics = true;
21118
21119                 if ( gl.getProgramParameter( program, 35714 ) === false ) {
21120
21121                         runnable = false;
21122
21123                         const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
21124                         const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
21125
21126                         console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
21127
21128                 } else if ( programLog !== '' ) {
21129
21130                         console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
21131
21132                 } else if ( vertexLog === '' || fragmentLog === '' ) {
21133
21134                         haveDiagnostics = false;
21135
21136                 }
21137
21138                 if ( haveDiagnostics ) {
21139
21140                         this.diagnostics = {
21141
21142                                 runnable: runnable,
21143
21144                                 programLog: programLog,
21145
21146                                 vertexShader: {
21147
21148                                         log: vertexLog,
21149                                         prefix: prefixVertex
21150
21151                                 },
21152
21153                                 fragmentShader: {
21154
21155                                         log: fragmentLog,
21156                                         prefix: prefixFragment
21157
21158                                 }
21159
21160                         };
21161
21162                 }
21163
21164         }
21165
21166         // Clean up
21167
21168         // Crashes in iOS9 and iOS10. #18402
21169         // gl.detachShader( program, glVertexShader );
21170         // gl.detachShader( program, glFragmentShader );
21171
21172         gl.deleteShader( glVertexShader );
21173         gl.deleteShader( glFragmentShader );
21174
21175         // set up caching for uniform locations
21176
21177         let cachedUniforms;
21178
21179         this.getUniforms = function () {
21180
21181                 if ( cachedUniforms === undefined ) {
21182
21183                         cachedUniforms = new WebGLUniforms( gl, program );
21184
21185                 }
21186
21187                 return cachedUniforms;
21188
21189         };
21190
21191         // set up caching for attribute locations
21192
21193         let cachedAttributes;
21194
21195         this.getAttributes = function () {
21196
21197                 if ( cachedAttributes === undefined ) {
21198
21199                         cachedAttributes = fetchAttributeLocations( gl, program );
21200
21201                 }
21202
21203                 return cachedAttributes;
21204
21205         };
21206
21207         // free resource
21208
21209         this.destroy = function () {
21210
21211                 bindingStates.releaseStatesOfProgram( this );
21212
21213                 gl.deleteProgram( program );
21214                 this.program = undefined;
21215
21216         };
21217
21218         //
21219
21220         this.name = parameters.shaderName;
21221         this.id = programIdCount ++;
21222         this.cacheKey = cacheKey;
21223         this.usedTimes = 1;
21224         this.program = program;
21225         this.vertexShader = glVertexShader;
21226         this.fragmentShader = glFragmentShader;
21227
21228         return this;
21229
21230     }
21231
21232     function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
21233
21234         const programs = [];
21235
21236         const isWebGL2 = capabilities.isWebGL2;
21237         const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
21238         const floatVertexTextures = capabilities.floatVertexTextures;
21239         const maxVertexUniforms = capabilities.maxVertexUniforms;
21240         const vertexTextures = capabilities.vertexTextures;
21241
21242         let precision = capabilities.precision;
21243
21244         const shaderIDs = {
21245                 MeshDepthMaterial: 'depth',
21246                 MeshDistanceMaterial: 'distanceRGBA',
21247                 MeshNormalMaterial: 'normal',
21248                 MeshBasicMaterial: 'basic',
21249                 MeshLambertMaterial: 'lambert',
21250                 MeshPhongMaterial: 'phong',
21251                 MeshToonMaterial: 'toon',
21252                 MeshStandardMaterial: 'physical',
21253                 MeshPhysicalMaterial: 'physical',
21254                 MeshMatcapMaterial: 'matcap',
21255                 LineBasicMaterial: 'basic',
21256                 LineDashedMaterial: 'dashed',
21257                 PointsMaterial: 'points',
21258                 ShadowMaterial: 'shadow',
21259                 SpriteMaterial: 'sprite'
21260         };
21261
21262         const parameterNames = [
21263                 'precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor',
21264                 'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV',
21265                 'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap', 'objectSpaceNormalMap', 'tangentSpaceNormalMap', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap', 'displacementMap', 'specularMap',
21266                 'roughnessMap', 'metalnessMap', 'gradientMap',
21267                 'alphaMap', 'combine', 'vertexColors', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
21268                 'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
21269                 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals',
21270                 'maxMorphTargets', 'maxMorphNormals', 'premultipliedAlpha',
21271                 'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
21272                 'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
21273                 'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
21274                 'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering',
21275                 'sheen', 'transmissionMap'
21276         ];
21277
21278         function getMaxBones( object ) {
21279
21280                 const skeleton = object.skeleton;
21281                 const bones = skeleton.bones;
21282
21283                 if ( floatVertexTextures ) {
21284
21285                         return 1024;
21286
21287                 } else {
21288
21289                         // default for when object is not specified
21290                         // ( for example when prebuilding shader to be used with multiple objects )
21291                         //
21292                         //  - leave some extra space for other uniforms
21293                         //  - limit here is ANGLE's 254 max uniform vectors
21294                         //    (up to 54 should be safe)
21295
21296                         const nVertexUniforms = maxVertexUniforms;
21297                         const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
21298
21299                         const maxBones = Math.min( nVertexMatrices, bones.length );
21300
21301                         if ( maxBones < bones.length ) {
21302
21303                                 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
21304                                 return 0;
21305
21306                         }
21307
21308                         return maxBones;
21309
21310                 }
21311
21312         }
21313
21314         function getTextureEncodingFromMap( map ) {
21315
21316                 let encoding;
21317
21318                 if ( map && map.isTexture ) {
21319
21320                         encoding = map.encoding;
21321
21322                 } else if ( map && map.isWebGLRenderTarget ) {
21323
21324                         console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
21325                         encoding = map.texture.encoding;
21326
21327                 } else {
21328
21329                         encoding = LinearEncoding;
21330
21331                 }
21332
21333                 return encoding;
21334
21335         }
21336
21337         function getParameters( material, lights, shadows, scene, object ) {
21338
21339                 const fog = scene.fog;
21340                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
21341
21342                 const envMap = cubemaps.get( material.envMap || environment );
21343
21344                 const shaderID = shaderIDs[ material.type ];
21345
21346                 // heuristics to create shader parameters according to lights in the scene
21347                 // (not to blow over maxLights budget)
21348
21349                 const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
21350
21351                 if ( material.precision !== null ) {
21352
21353                         precision = capabilities.getMaxPrecision( material.precision );
21354
21355                         if ( precision !== material.precision ) {
21356
21357                                 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
21358
21359                         }
21360
21361                 }
21362
21363                 let vertexShader, fragmentShader;
21364
21365                 if ( shaderID ) {
21366
21367                         const shader = ShaderLib[ shaderID ];
21368
21369                         vertexShader = shader.vertexShader;
21370                         fragmentShader = shader.fragmentShader;
21371
21372                 } else {
21373
21374                         vertexShader = material.vertexShader;
21375                         fragmentShader = material.fragmentShader;
21376
21377                 }
21378
21379                 const currentRenderTarget = renderer.getRenderTarget();
21380
21381                 const parameters = {
21382
21383                         isWebGL2: isWebGL2,
21384
21385                         shaderID: shaderID,
21386                         shaderName: material.type,
21387
21388                         vertexShader: vertexShader,
21389                         fragmentShader: fragmentShader,
21390                         defines: material.defines,
21391
21392                         isRawShaderMaterial: material.isRawShaderMaterial === true,
21393                         glslVersion: material.glslVersion,
21394
21395                         precision: precision,
21396
21397                         instancing: object.isInstancedMesh === true,
21398                         instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
21399
21400                         supportsVertexTextures: vertexTextures,
21401                         outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
21402                         map: !! material.map,
21403                         mapEncoding: getTextureEncodingFromMap( material.map ),
21404                         matcap: !! material.matcap,
21405                         matcapEncoding: getTextureEncodingFromMap( material.matcap ),
21406                         envMap: !! envMap,
21407                         envMapMode: envMap && envMap.mapping,
21408                         envMapEncoding: getTextureEncodingFromMap( envMap ),
21409                         envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
21410                         lightMap: !! material.lightMap,
21411                         lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
21412                         aoMap: !! material.aoMap,
21413                         emissiveMap: !! material.emissiveMap,
21414                         emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
21415                         bumpMap: !! material.bumpMap,
21416                         normalMap: !! material.normalMap,
21417                         objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
21418                         tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
21419                         clearcoatMap: !! material.clearcoatMap,
21420                         clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
21421                         clearcoatNormalMap: !! material.clearcoatNormalMap,
21422                         displacementMap: !! material.displacementMap,
21423                         roughnessMap: !! material.roughnessMap,
21424                         metalnessMap: !! material.metalnessMap,
21425                         specularMap: !! material.specularMap,
21426                         alphaMap: !! material.alphaMap,
21427
21428                         gradientMap: !! material.gradientMap,
21429
21430                         sheen: !! material.sheen,
21431
21432                         transmissionMap: !! material.transmissionMap,
21433
21434                         combine: material.combine,
21435
21436                         vertexTangents: ( material.normalMap && material.vertexTangents ),
21437                         vertexColors: material.vertexColors,
21438                         vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap,
21439                         uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
21440
21441                         fog: !! fog,
21442                         useFog: material.fog,
21443                         fogExp2: ( fog && fog.isFogExp2 ),
21444
21445                         flatShading: material.flatShading,
21446
21447                         sizeAttenuation: material.sizeAttenuation,
21448                         logarithmicDepthBuffer: logarithmicDepthBuffer,
21449
21450                         skinning: material.skinning && maxBones > 0,
21451                         maxBones: maxBones,
21452                         useVertexTexture: floatVertexTextures,
21453
21454                         morphTargets: material.morphTargets,
21455                         morphNormals: material.morphNormals,
21456                         maxMorphTargets: renderer.maxMorphTargets,
21457                         maxMorphNormals: renderer.maxMorphNormals,
21458
21459                         numDirLights: lights.directional.length,
21460                         numPointLights: lights.point.length,
21461                         numSpotLights: lights.spot.length,
21462                         numRectAreaLights: lights.rectArea.length,
21463                         numHemiLights: lights.hemi.length,
21464
21465                         numDirLightShadows: lights.directionalShadowMap.length,
21466                         numPointLightShadows: lights.pointShadowMap.length,
21467                         numSpotLightShadows: lights.spotShadowMap.length,
21468
21469                         numClippingPlanes: clipping.numPlanes,
21470                         numClipIntersection: clipping.numIntersection,
21471
21472                         dithering: material.dithering,
21473
21474                         shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
21475                         shadowMapType: renderer.shadowMap.type,
21476
21477                         toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
21478                         physicallyCorrectLights: renderer.physicallyCorrectLights,
21479
21480                         premultipliedAlpha: material.premultipliedAlpha,
21481
21482                         alphaTest: material.alphaTest,
21483                         doubleSided: material.side === DoubleSide,
21484                         flipSided: material.side === BackSide,
21485
21486                         depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
21487
21488                         index0AttributeName: material.index0AttributeName,
21489
21490                         extensionDerivatives: material.extensions && material.extensions.derivatives,
21491                         extensionFragDepth: material.extensions && material.extensions.fragDepth,
21492                         extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
21493                         extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
21494
21495                         rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
21496                         rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
21497                         rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
21498
21499                         customProgramCacheKey: material.customProgramCacheKey()
21500
21501                 };
21502
21503                 return parameters;
21504
21505         }
21506
21507         function getProgramCacheKey( parameters ) {
21508
21509                 const array = [];
21510
21511                 if ( parameters.shaderID ) {
21512
21513                         array.push( parameters.shaderID );
21514
21515                 } else {
21516
21517                         array.push( parameters.fragmentShader );
21518                         array.push( parameters.vertexShader );
21519
21520                 }
21521
21522                 if ( parameters.defines !== undefined ) {
21523
21524                         for ( const name in parameters.defines ) {
21525
21526                                 array.push( name );
21527                                 array.push( parameters.defines[ name ] );
21528
21529                         }
21530
21531                 }
21532
21533                 if ( parameters.isRawShaderMaterial === false ) {
21534
21535                         for ( let i = 0; i < parameterNames.length; i ++ ) {
21536
21537                                 array.push( parameters[ parameterNames[ i ] ] );
21538
21539                         }
21540
21541                         array.push( renderer.outputEncoding );
21542                         array.push( renderer.gammaFactor );
21543
21544                 }
21545
21546                 array.push( parameters.customProgramCacheKey );
21547
21548                 return array.join();
21549
21550         }
21551
21552         function getUniforms( material ) {
21553
21554                 const shaderID = shaderIDs[ material.type ];
21555                 let uniforms;
21556
21557                 if ( shaderID ) {
21558
21559                         const shader = ShaderLib[ shaderID ];
21560                         uniforms = UniformsUtils.clone( shader.uniforms );
21561
21562                 } else {
21563
21564                         uniforms = material.uniforms;
21565
21566                 }
21567
21568                 return uniforms;
21569
21570         }
21571
21572         function acquireProgram( parameters, cacheKey ) {
21573
21574                 let program;
21575
21576                 // Check if code has been already compiled
21577                 for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
21578
21579                         const preexistingProgram = programs[ p ];
21580
21581                         if ( preexistingProgram.cacheKey === cacheKey ) {
21582
21583                                 program = preexistingProgram;
21584                                 ++ program.usedTimes;
21585
21586                                 break;
21587
21588                         }
21589
21590                 }
21591
21592                 if ( program === undefined ) {
21593
21594                         program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
21595                         programs.push( program );
21596
21597                 }
21598
21599                 return program;
21600
21601         }
21602
21603         function releaseProgram( program ) {
21604
21605                 if ( -- program.usedTimes === 0 ) {
21606
21607                         // Remove from unordered set
21608                         const i = programs.indexOf( program );
21609                         programs[ i ] = programs[ programs.length - 1 ];
21610                         programs.pop();
21611
21612                         // Free WebGL resources
21613                         program.destroy();
21614
21615                 }
21616
21617         }
21618
21619         return {
21620                 getParameters: getParameters,
21621                 getProgramCacheKey: getProgramCacheKey,
21622                 getUniforms: getUniforms,
21623                 acquireProgram: acquireProgram,
21624                 releaseProgram: releaseProgram,
21625                 // Exposed for resource monitoring & error feedback via renderer.info:
21626                 programs: programs
21627         };
21628
21629     }
21630
21631     function WebGLProperties() {
21632
21633         let properties = new WeakMap();
21634
21635         function get( object ) {
21636
21637                 let map = properties.get( object );
21638
21639                 if ( map === undefined ) {
21640
21641                         map = {};
21642                         properties.set( object, map );
21643
21644                 }
21645
21646                 return map;
21647
21648         }
21649
21650         function remove( object ) {
21651
21652                 properties.delete( object );
21653
21654         }
21655
21656         function update( object, key, value ) {
21657
21658                 properties.get( object )[ key ] = value;
21659
21660         }
21661
21662         function dispose() {
21663
21664                 properties = new WeakMap();
21665
21666         }
21667
21668         return {
21669                 get: get,
21670                 remove: remove,
21671                 update: update,
21672                 dispose: dispose
21673         };
21674
21675     }
21676
21677     function painterSortStable( a, b ) {
21678
21679         if ( a.groupOrder !== b.groupOrder ) {
21680
21681                 return a.groupOrder - b.groupOrder;
21682
21683         } else if ( a.renderOrder !== b.renderOrder ) {
21684
21685                 return a.renderOrder - b.renderOrder;
21686
21687         } else if ( a.program !== b.program ) {
21688
21689                 return a.program.id - b.program.id;
21690
21691         } else if ( a.material.id !== b.material.id ) {
21692
21693                 return a.material.id - b.material.id;
21694
21695         } else if ( a.z !== b.z ) {
21696
21697                 return a.z - b.z;
21698
21699         } else {
21700
21701                 return a.id - b.id;
21702
21703         }
21704
21705     }
21706
21707     function reversePainterSortStable( a, b ) {
21708
21709         if ( a.groupOrder !== b.groupOrder ) {
21710
21711                 return a.groupOrder - b.groupOrder;
21712
21713         } else if ( a.renderOrder !== b.renderOrder ) {
21714
21715                 return a.renderOrder - b.renderOrder;
21716
21717         } else if ( a.z !== b.z ) {
21718
21719                 return b.z - a.z;
21720
21721         } else {
21722
21723                 return a.id - b.id;
21724
21725         }
21726
21727     }
21728
21729
21730     function WebGLRenderList( properties ) {
21731
21732         const renderItems = [];
21733         let renderItemsIndex = 0;
21734
21735         const opaque = [];
21736         const transparent = [];
21737
21738         const defaultProgram = { id: - 1 };
21739
21740         function init() {
21741
21742                 renderItemsIndex = 0;
21743
21744                 opaque.length = 0;
21745                 transparent.length = 0;
21746
21747         }
21748
21749         function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
21750
21751                 let renderItem = renderItems[ renderItemsIndex ];
21752                 const materialProperties = properties.get( material );
21753
21754                 if ( renderItem === undefined ) {
21755
21756                         renderItem = {
21757                                 id: object.id,
21758                                 object: object,
21759                                 geometry: geometry,
21760                                 material: material,
21761                                 program: materialProperties.program || defaultProgram,
21762                                 groupOrder: groupOrder,
21763                                 renderOrder: object.renderOrder,
21764                                 z: z,
21765                                 group: group
21766                         };
21767
21768                         renderItems[ renderItemsIndex ] = renderItem;
21769
21770                 } else {
21771
21772                         renderItem.id = object.id;
21773                         renderItem.object = object;
21774                         renderItem.geometry = geometry;
21775                         renderItem.material = material;
21776                         renderItem.program = materialProperties.program || defaultProgram;
21777                         renderItem.groupOrder = groupOrder;
21778                         renderItem.renderOrder = object.renderOrder;
21779                         renderItem.z = z;
21780                         renderItem.group = group;
21781
21782                 }
21783
21784                 renderItemsIndex ++;
21785
21786                 return renderItem;
21787
21788         }
21789
21790         function push( object, geometry, material, groupOrder, z, group ) {
21791
21792                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21793
21794                 ( material.transparent === true ? transparent : opaque ).push( renderItem );
21795
21796         }
21797
21798         function unshift( object, geometry, material, groupOrder, z, group ) {
21799
21800                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21801
21802                 ( material.transparent === true ? transparent : opaque ).unshift( renderItem );
21803
21804         }
21805
21806         function sort( customOpaqueSort, customTransparentSort ) {
21807
21808                 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
21809                 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
21810
21811         }
21812
21813         function finish() {
21814
21815                 // Clear references from inactive renderItems in the list
21816
21817                 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
21818
21819                         const renderItem = renderItems[ i ];
21820
21821                         if ( renderItem.id === null ) break;
21822
21823                         renderItem.id = null;
21824                         renderItem.object = null;
21825                         renderItem.geometry = null;
21826                         renderItem.material = null;
21827                         renderItem.program = null;
21828                         renderItem.group = null;
21829
21830                 }
21831
21832         }
21833
21834         return {
21835
21836                 opaque: opaque,
21837                 transparent: transparent,
21838
21839                 init: init,
21840                 push: push,
21841                 unshift: unshift,
21842                 finish: finish,
21843
21844                 sort: sort
21845         };
21846
21847     }
21848
21849     function WebGLRenderLists( properties ) {
21850
21851         let lists = new WeakMap();
21852
21853         function get( scene, camera ) {
21854
21855                 const cameras = lists.get( scene );
21856                 let list;
21857
21858                 if ( cameras === undefined ) {
21859
21860                         list = new WebGLRenderList( properties );
21861                         lists.set( scene, new WeakMap() );
21862                         lists.get( scene ).set( camera, list );
21863
21864                 } else {
21865
21866                         list = cameras.get( camera );
21867                         if ( list === undefined ) {
21868
21869                                 list = new WebGLRenderList( properties );
21870                                 cameras.set( camera, list );
21871
21872                         }
21873
21874                 }
21875
21876                 return list;
21877
21878         }
21879
21880         function dispose() {
21881
21882                 lists = new WeakMap();
21883
21884         }
21885
21886         return {
21887                 get: get,
21888                 dispose: dispose
21889         };
21890
21891     }
21892
21893     function UniformsCache() {
21894
21895         const lights = {};
21896
21897         return {
21898
21899                 get: function ( light ) {
21900
21901                         if ( lights[ light.id ] !== undefined ) {
21902
21903                                 return lights[ light.id ];
21904
21905                         }
21906
21907                         let uniforms;
21908
21909                         switch ( light.type ) {
21910
21911                                 case 'DirectionalLight':
21912                                         uniforms = {
21913                                                 direction: new Vector3(),
21914                                                 color: new Color()
21915                                         };
21916                                         break;
21917
21918                                 case 'SpotLight':
21919                                         uniforms = {
21920                                                 position: new Vector3(),
21921                                                 direction: new Vector3(),
21922                                                 color: new Color(),
21923                                                 distance: 0,
21924                                                 coneCos: 0,
21925                                                 penumbraCos: 0,
21926                                                 decay: 0
21927                                         };
21928                                         break;
21929
21930                                 case 'PointLight':
21931                                         uniforms = {
21932                                                 position: new Vector3(),
21933                                                 color: new Color(),
21934                                                 distance: 0,
21935                                                 decay: 0
21936                                         };
21937                                         break;
21938
21939                                 case 'HemisphereLight':
21940                                         uniforms = {
21941                                                 direction: new Vector3(),
21942                                                 skyColor: new Color(),
21943                                                 groundColor: new Color()
21944                                         };
21945                                         break;
21946
21947                                 case 'RectAreaLight':
21948                                         uniforms = {
21949                                                 color: new Color(),
21950                                                 position: new Vector3(),
21951                                                 halfWidth: new Vector3(),
21952                                                 halfHeight: new Vector3()
21953                                         };
21954                                         break;
21955
21956                         }
21957
21958                         lights[ light.id ] = uniforms;
21959
21960                         return uniforms;
21961
21962                 }
21963
21964         };
21965
21966     }
21967
21968     function ShadowUniformsCache() {
21969
21970         const lights = {};
21971
21972         return {
21973
21974                 get: function ( light ) {
21975
21976                         if ( lights[ light.id ] !== undefined ) {
21977
21978                                 return lights[ light.id ];
21979
21980                         }
21981
21982                         let uniforms;
21983
21984                         switch ( light.type ) {
21985
21986                                 case 'DirectionalLight':
21987                                         uniforms = {
21988                                                 shadowBias: 0,
21989                                                 shadowNormalBias: 0,
21990                                                 shadowRadius: 1,
21991                                                 shadowMapSize: new Vector2()
21992                                         };
21993                                         break;
21994
21995                                 case 'SpotLight':
21996                                         uniforms = {
21997                                                 shadowBias: 0,
21998                                                 shadowNormalBias: 0,
21999                                                 shadowRadius: 1,
22000                                                 shadowMapSize: new Vector2()
22001                                         };
22002                                         break;
22003
22004                                 case 'PointLight':
22005                                         uniforms = {
22006                                                 shadowBias: 0,
22007                                                 shadowNormalBias: 0,
22008                                                 shadowRadius: 1,
22009                                                 shadowMapSize: new Vector2(),
22010                                                 shadowCameraNear: 1,
22011                                                 shadowCameraFar: 1000
22012                                         };
22013                                         break;
22014
22015                                 // TODO (abelnation): set RectAreaLight shadow uniforms
22016
22017                         }
22018
22019                         lights[ light.id ] = uniforms;
22020
22021                         return uniforms;
22022
22023                 }
22024
22025         };
22026
22027     }
22028
22029
22030
22031     let nextVersion = 0;
22032
22033     function shadowCastingLightsFirst( lightA, lightB ) {
22034
22035         return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
22036
22037     }
22038
22039     function WebGLLights( extensions, capabilities ) {
22040
22041         const cache = new UniformsCache();
22042
22043         const shadowCache = ShadowUniformsCache();
22044
22045         const state = {
22046
22047                 version: 0,
22048
22049                 hash: {
22050                         directionalLength: - 1,
22051                         pointLength: - 1,
22052                         spotLength: - 1,
22053                         rectAreaLength: - 1,
22054                         hemiLength: - 1,
22055
22056                         numDirectionalShadows: - 1,
22057                         numPointShadows: - 1,
22058                         numSpotShadows: - 1
22059                 },
22060
22061                 ambient: [ 0, 0, 0 ],
22062                 probe: [],
22063                 directional: [],
22064                 directionalShadow: [],
22065                 directionalShadowMap: [],
22066                 directionalShadowMatrix: [],
22067                 spot: [],
22068                 spotShadow: [],
22069                 spotShadowMap: [],
22070                 spotShadowMatrix: [],
22071                 rectArea: [],
22072                 rectAreaLTC1: null,
22073                 rectAreaLTC2: null,
22074                 point: [],
22075                 pointShadow: [],
22076                 pointShadowMap: [],
22077                 pointShadowMatrix: [],
22078                 hemi: []
22079
22080         };
22081
22082         for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
22083
22084         const vector3 = new Vector3();
22085         const matrix4 = new Matrix4();
22086         const matrix42 = new Matrix4();
22087
22088         function setup( lights ) {
22089
22090                 let r = 0, g = 0, b = 0;
22091
22092                 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
22093
22094                 let directionalLength = 0;
22095                 let pointLength = 0;
22096                 let spotLength = 0;
22097                 let rectAreaLength = 0;
22098                 let hemiLength = 0;
22099
22100                 let numDirectionalShadows = 0;
22101                 let numPointShadows = 0;
22102                 let numSpotShadows = 0;
22103
22104                 lights.sort( shadowCastingLightsFirst );
22105
22106                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
22107
22108                         const light = lights[ i ];
22109
22110                         const color = light.color;
22111                         const intensity = light.intensity;
22112                         const distance = light.distance;
22113
22114                         const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
22115
22116                         if ( light.isAmbientLight ) {
22117
22118                                 r += color.r * intensity;
22119                                 g += color.g * intensity;
22120                                 b += color.b * intensity;
22121
22122                         } else if ( light.isLightProbe ) {
22123
22124                                 for ( let j = 0; j < 9; j ++ ) {
22125
22126                                         state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
22127
22128                                 }
22129
22130                         } else if ( light.isDirectionalLight ) {
22131
22132                                 const uniforms = cache.get( light );
22133
22134                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
22135
22136                                 if ( light.castShadow ) {
22137
22138                                         const shadow = light.shadow;
22139
22140                                         const shadowUniforms = shadowCache.get( light );
22141
22142                                         shadowUniforms.shadowBias = shadow.bias;
22143                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22144                                         shadowUniforms.shadowRadius = shadow.radius;
22145                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22146
22147                                         state.directionalShadow[ directionalLength ] = shadowUniforms;
22148                                         state.directionalShadowMap[ directionalLength ] = shadowMap;
22149                                         state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
22150
22151                                         numDirectionalShadows ++;
22152
22153                                 }
22154
22155                                 state.directional[ directionalLength ] = uniforms;
22156
22157                                 directionalLength ++;
22158
22159                         } else if ( light.isSpotLight ) {
22160
22161                                 const uniforms = cache.get( light );
22162
22163                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22164
22165                                 uniforms.color.copy( color ).multiplyScalar( intensity );
22166                                 uniforms.distance = distance;
22167
22168                                 uniforms.coneCos = Math.cos( light.angle );
22169                                 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
22170                                 uniforms.decay = light.decay;
22171
22172                                 if ( light.castShadow ) {
22173
22174                                         const shadow = light.shadow;
22175
22176                                         const shadowUniforms = shadowCache.get( light );
22177
22178                                         shadowUniforms.shadowBias = shadow.bias;
22179                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22180                                         shadowUniforms.shadowRadius = shadow.radius;
22181                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22182
22183                                         state.spotShadow[ spotLength ] = shadowUniforms;
22184                                         state.spotShadowMap[ spotLength ] = shadowMap;
22185                                         state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
22186
22187                                         numSpotShadows ++;
22188
22189                                 }
22190
22191                                 state.spot[ spotLength ] = uniforms;
22192
22193                                 spotLength ++;
22194
22195                         } else if ( light.isRectAreaLight ) {
22196
22197                                 const uniforms = cache.get( light );
22198
22199                                 // (a) intensity is the total visible light emitted
22200                                 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
22201
22202                                 // (b) intensity is the brightness of the light
22203                                 uniforms.color.copy( color ).multiplyScalar( intensity );
22204
22205                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
22206                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
22207
22208                                 state.rectArea[ rectAreaLength ] = uniforms;
22209
22210                                 rectAreaLength ++;
22211
22212                         } else if ( light.isPointLight ) {
22213
22214                                 const uniforms = cache.get( light );
22215
22216                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
22217                                 uniforms.distance = light.distance;
22218                                 uniforms.decay = light.decay;
22219
22220                                 if ( light.castShadow ) {
22221
22222                                         const shadow = light.shadow;
22223
22224                                         const shadowUniforms = shadowCache.get( light );
22225
22226                                         shadowUniforms.shadowBias = shadow.bias;
22227                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22228                                         shadowUniforms.shadowRadius = shadow.radius;
22229                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22230                                         shadowUniforms.shadowCameraNear = shadow.camera.near;
22231                                         shadowUniforms.shadowCameraFar = shadow.camera.far;
22232
22233                                         state.pointShadow[ pointLength ] = shadowUniforms;
22234                                         state.pointShadowMap[ pointLength ] = shadowMap;
22235                                         state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
22236
22237                                         numPointShadows ++;
22238
22239                                 }
22240
22241                                 state.point[ pointLength ] = uniforms;
22242
22243                                 pointLength ++;
22244
22245                         } else if ( light.isHemisphereLight ) {
22246
22247                                 const uniforms = cache.get( light );
22248
22249                                 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
22250                                 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
22251
22252                                 state.hemi[ hemiLength ] = uniforms;
22253
22254                                 hemiLength ++;
22255
22256                         }
22257
22258                 }
22259
22260                 if ( rectAreaLength > 0 ) {
22261
22262                         if ( capabilities.isWebGL2 ) {
22263
22264                                 // WebGL 2
22265
22266                                 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
22267                                 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
22268
22269                         } else {
22270
22271                                 // WebGL 1
22272
22273                                 if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
22274
22275                                         state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
22276                                         state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
22277
22278                                 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
22279
22280                                         state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
22281                                         state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
22282
22283                                 } else {
22284
22285                                         console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
22286
22287                                 }
22288
22289                         }
22290
22291                 }
22292
22293                 state.ambient[ 0 ] = r;
22294                 state.ambient[ 1 ] = g;
22295                 state.ambient[ 2 ] = b;
22296
22297                 const hash = state.hash;
22298
22299                 if ( hash.directionalLength !== directionalLength ||
22300                         hash.pointLength !== pointLength ||
22301                         hash.spotLength !== spotLength ||
22302                         hash.rectAreaLength !== rectAreaLength ||
22303                         hash.hemiLength !== hemiLength ||
22304                         hash.numDirectionalShadows !== numDirectionalShadows ||
22305                         hash.numPointShadows !== numPointShadows ||
22306                         hash.numSpotShadows !== numSpotShadows ) {
22307
22308                         state.directional.length = directionalLength;
22309                         state.spot.length = spotLength;
22310                         state.rectArea.length = rectAreaLength;
22311                         state.point.length = pointLength;
22312                         state.hemi.length = hemiLength;
22313
22314                         state.directionalShadow.length = numDirectionalShadows;
22315                         state.directionalShadowMap.length = numDirectionalShadows;
22316                         state.pointShadow.length = numPointShadows;
22317                         state.pointShadowMap.length = numPointShadows;
22318                         state.spotShadow.length = numSpotShadows;
22319                         state.spotShadowMap.length = numSpotShadows;
22320                         state.directionalShadowMatrix.length = numDirectionalShadows;
22321                         state.pointShadowMatrix.length = numPointShadows;
22322                         state.spotShadowMatrix.length = numSpotShadows;
22323
22324                         hash.directionalLength = directionalLength;
22325                         hash.pointLength = pointLength;
22326                         hash.spotLength = spotLength;
22327                         hash.rectAreaLength = rectAreaLength;
22328                         hash.hemiLength = hemiLength;
22329
22330                         hash.numDirectionalShadows = numDirectionalShadows;
22331                         hash.numPointShadows = numPointShadows;
22332                         hash.numSpotShadows = numSpotShadows;
22333
22334                         state.version = nextVersion ++;
22335
22336                 }
22337
22338         }
22339
22340         function setupView( lights, camera ) {
22341
22342                 let directionalLength = 0;
22343                 let pointLength = 0;
22344                 let spotLength = 0;
22345                 let rectAreaLength = 0;
22346                 let hemiLength = 0;
22347
22348                 const viewMatrix = camera.matrixWorldInverse;
22349
22350                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
22351
22352                         const light = lights[ i ];
22353
22354                         if ( light.isDirectionalLight ) {
22355
22356                                 const uniforms = state.directional[ directionalLength ];
22357
22358                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22359                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
22360                                 uniforms.direction.sub( vector3 );
22361                                 uniforms.direction.transformDirection( viewMatrix );
22362
22363                                 directionalLength ++;
22364
22365                         } else if ( light.isSpotLight ) {
22366
22367                                 const uniforms = state.spot[ spotLength ];
22368
22369                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22370                                 uniforms.position.applyMatrix4( viewMatrix );
22371
22372                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22373                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
22374                                 uniforms.direction.sub( vector3 );
22375                                 uniforms.direction.transformDirection( viewMatrix );
22376
22377                                 spotLength ++;
22378
22379                         } else if ( light.isRectAreaLight ) {
22380
22381                                 const uniforms = state.rectArea[ rectAreaLength ];
22382
22383                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22384                                 uniforms.position.applyMatrix4( viewMatrix );
22385
22386                                 // extract local rotation of light to derive width/height half vectors
22387                                 matrix42.identity();
22388                                 matrix4.copy( light.matrixWorld );
22389                                 matrix4.premultiply( viewMatrix );
22390                                 matrix42.extractRotation( matrix4 );
22391
22392                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
22393                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
22394
22395                                 uniforms.halfWidth.applyMatrix4( matrix42 );
22396                                 uniforms.halfHeight.applyMatrix4( matrix42 );
22397
22398                                 rectAreaLength ++;
22399
22400                         } else if ( light.isPointLight ) {
22401
22402                                 const uniforms = state.point[ pointLength ];
22403
22404                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22405                                 uniforms.position.applyMatrix4( viewMatrix );
22406
22407                                 pointLength ++;
22408
22409                         } else if ( light.isHemisphereLight ) {
22410
22411                                 const uniforms = state.hemi[ hemiLength ];
22412
22413                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22414                                 uniforms.direction.transformDirection( viewMatrix );
22415                                 uniforms.direction.normalize();
22416
22417                                 hemiLength ++;
22418
22419                         }
22420
22421                 }
22422
22423         }
22424
22425         return {
22426                 setup: setup,
22427                 setupView: setupView,
22428                 state: state
22429         };
22430
22431     }
22432
22433     function WebGLRenderState( extensions, capabilities ) {
22434
22435         const lights = new WebGLLights( extensions, capabilities );
22436
22437         const lightsArray = [];
22438         const shadowsArray = [];
22439
22440         function init() {
22441
22442                 lightsArray.length = 0;
22443                 shadowsArray.length = 0;
22444
22445         }
22446
22447         function pushLight( light ) {
22448
22449                 lightsArray.push( light );
22450
22451         }
22452
22453         function pushShadow( shadowLight ) {
22454
22455                 shadowsArray.push( shadowLight );
22456
22457         }
22458
22459         function setupLights() {
22460
22461                 lights.setup( lightsArray );
22462
22463         }
22464
22465         function setupLightsView( camera ) {
22466
22467                 lights.setupView( lightsArray, camera );
22468
22469         }
22470
22471         const state = {
22472                 lightsArray: lightsArray,
22473                 shadowsArray: shadowsArray,
22474
22475                 lights: lights
22476         };
22477
22478         return {
22479                 init: init,
22480                 state: state,
22481                 setupLights: setupLights,
22482                 setupLightsView: setupLightsView,
22483
22484                 pushLight: pushLight,
22485                 pushShadow: pushShadow
22486         };
22487
22488     }
22489
22490     function WebGLRenderStates( extensions, capabilities ) {
22491
22492         let renderStates = new WeakMap();
22493
22494         function get( scene, renderCallDepth = 0 ) {
22495
22496                 let renderState;
22497
22498                 if ( renderStates.has( scene ) === false ) {
22499
22500                         renderState = new WebGLRenderState( extensions, capabilities );
22501                         renderStates.set( scene, [] );
22502                         renderStates.get( scene ).push( renderState );
22503
22504                 } else {
22505
22506                         if ( renderCallDepth >= renderStates.get( scene ).length ) {
22507
22508                                 renderState = new WebGLRenderState( extensions, capabilities );
22509                                 renderStates.get( scene ).push( renderState );
22510
22511                         } else {
22512
22513                                 renderState = renderStates.get( scene )[ renderCallDepth ];
22514
22515                         }
22516
22517                 }
22518
22519                 return renderState;
22520
22521         }
22522
22523         function dispose() {
22524
22525                 renderStates = new WeakMap();
22526
22527         }
22528
22529         return {
22530                 get: get,
22531                 dispose: dispose
22532         };
22533
22534     }
22535
22536     /**
22537      * parameters = {
22538      *
22539      *  opacity: <float>,
22540      *
22541      *  map: new THREE.Texture( <Image> ),
22542      *
22543      *  alphaMap: new THREE.Texture( <Image> ),
22544      *
22545      *  displacementMap: new THREE.Texture( <Image> ),
22546      *  displacementScale: <float>,
22547      *  displacementBias: <float>,
22548      *
22549      *  wireframe: <boolean>,
22550      *  wireframeLinewidth: <float>
22551      * }
22552      */
22553
22554     function MeshDepthMaterial( parameters ) {
22555
22556         Material.call( this );
22557
22558         this.type = 'MeshDepthMaterial';
22559
22560         this.depthPacking = BasicDepthPacking;
22561
22562         this.skinning = false;
22563         this.morphTargets = false;
22564
22565         this.map = null;
22566
22567         this.alphaMap = null;
22568
22569         this.displacementMap = null;
22570         this.displacementScale = 1;
22571         this.displacementBias = 0;
22572
22573         this.wireframe = false;
22574         this.wireframeLinewidth = 1;
22575
22576         this.fog = false;
22577
22578         this.setValues( parameters );
22579
22580     }
22581
22582     MeshDepthMaterial.prototype = Object.create( Material.prototype );
22583     MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
22584
22585     MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
22586
22587     MeshDepthMaterial.prototype.copy = function ( source ) {
22588
22589         Material.prototype.copy.call( this, source );
22590
22591         this.depthPacking = source.depthPacking;
22592
22593         this.skinning = source.skinning;
22594         this.morphTargets = source.morphTargets;
22595
22596         this.map = source.map;
22597
22598         this.alphaMap = source.alphaMap;
22599
22600         this.displacementMap = source.displacementMap;
22601         this.displacementScale = source.displacementScale;
22602         this.displacementBias = source.displacementBias;
22603
22604         this.wireframe = source.wireframe;
22605         this.wireframeLinewidth = source.wireframeLinewidth;
22606
22607         return this;
22608
22609     };
22610
22611     /**
22612      * parameters = {
22613      *
22614      *  referencePosition: <float>,
22615      *  nearDistance: <float>,
22616      *  farDistance: <float>,
22617      *
22618      *  skinning: <bool>,
22619      *  morphTargets: <bool>,
22620      *
22621      *  map: new THREE.Texture( <Image> ),
22622      *
22623      *  alphaMap: new THREE.Texture( <Image> ),
22624      *
22625      *  displacementMap: new THREE.Texture( <Image> ),
22626      *  displacementScale: <float>,
22627      *  displacementBias: <float>
22628      *
22629      * }
22630      */
22631
22632     function MeshDistanceMaterial( parameters ) {
22633
22634         Material.call( this );
22635
22636         this.type = 'MeshDistanceMaterial';
22637
22638         this.referencePosition = new Vector3();
22639         this.nearDistance = 1;
22640         this.farDistance = 1000;
22641
22642         this.skinning = false;
22643         this.morphTargets = false;
22644
22645         this.map = null;
22646
22647         this.alphaMap = null;
22648
22649         this.displacementMap = null;
22650         this.displacementScale = 1;
22651         this.displacementBias = 0;
22652
22653         this.fog = false;
22654
22655         this.setValues( parameters );
22656
22657     }
22658
22659     MeshDistanceMaterial.prototype = Object.create( Material.prototype );
22660     MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
22661
22662     MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
22663
22664     MeshDistanceMaterial.prototype.copy = function ( source ) {
22665
22666         Material.prototype.copy.call( this, source );
22667
22668         this.referencePosition.copy( source.referencePosition );
22669         this.nearDistance = source.nearDistance;
22670         this.farDistance = source.farDistance;
22671
22672         this.skinning = source.skinning;
22673         this.morphTargets = source.morphTargets;
22674
22675         this.map = source.map;
22676
22677         this.alphaMap = source.alphaMap;
22678
22679         this.displacementMap = source.displacementMap;
22680         this.displacementScale = source.displacementScale;
22681         this.displacementBias = source.displacementBias;
22682
22683         return this;
22684
22685     };
22686
22687     var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
22688
22689     var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
22690
22691     function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
22692
22693         let _frustum = new Frustum();
22694
22695         const _shadowMapSize = new Vector2(),
22696                 _viewportSize = new Vector2(),
22697
22698                 _viewport = new Vector4(),
22699
22700                 _depthMaterials = [],
22701                 _distanceMaterials = [],
22702
22703                 _materialCache = {};
22704
22705         const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
22706
22707         const shadowMaterialVertical = new ShaderMaterial( {
22708
22709                 defines: {
22710                         SAMPLE_RATE: 2.0 / 8.0,
22711                         HALF_SAMPLE_RATE: 1.0 / 8.0
22712                 },
22713
22714                 uniforms: {
22715                         shadow_pass: { value: null },
22716                         resolution: { value: new Vector2() },
22717                         radius: { value: 4.0 }
22718                 },
22719
22720                 vertexShader: vsm_vert,
22721
22722                 fragmentShader: vsm_frag
22723
22724         } );
22725
22726         const shadowMaterialHorizontal = shadowMaterialVertical.clone();
22727         shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
22728
22729         const fullScreenTri = new BufferGeometry();
22730         fullScreenTri.setAttribute(
22731                 'position',
22732                 new BufferAttribute(
22733                         new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
22734                         3
22735                 )
22736         );
22737
22738         const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
22739
22740         const scope = this;
22741
22742         this.enabled = false;
22743
22744         this.autoUpdate = true;
22745         this.needsUpdate = false;
22746
22747         this.type = PCFShadowMap;
22748
22749         this.render = function ( lights, scene, camera ) {
22750
22751                 if ( scope.enabled === false ) return;
22752                 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
22753
22754                 if ( lights.length === 0 ) return;
22755
22756                 const currentRenderTarget = _renderer.getRenderTarget();
22757                 const activeCubeFace = _renderer.getActiveCubeFace();
22758                 const activeMipmapLevel = _renderer.getActiveMipmapLevel();
22759
22760                 const _state = _renderer.state;
22761
22762                 // Set GL state for depth map.
22763                 _state.setBlending( NoBlending );
22764                 _state.buffers.color.setClear( 1, 1, 1, 1 );
22765                 _state.buffers.depth.setTest( true );
22766                 _state.setScissorTest( false );
22767
22768                 // render depth map
22769
22770                 for ( let i = 0, il = lights.length; i < il; i ++ ) {
22771
22772                         const light = lights[ i ];
22773                         const shadow = light.shadow;
22774
22775                         if ( shadow === undefined ) {
22776
22777                                 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
22778                                 continue;
22779
22780                         }
22781
22782                         if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
22783
22784                         _shadowMapSize.copy( shadow.mapSize );
22785
22786                         const shadowFrameExtents = shadow.getFrameExtents();
22787
22788                         _shadowMapSize.multiply( shadowFrameExtents );
22789
22790                         _viewportSize.copy( shadow.mapSize );
22791
22792                         if ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {
22793
22794                                 if ( _shadowMapSize.x > maxTextureSize ) {
22795
22796                                         _viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );
22797                                         _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
22798                                         shadow.mapSize.x = _viewportSize.x;
22799
22800                                 }
22801
22802                                 if ( _shadowMapSize.y > maxTextureSize ) {
22803
22804                                         _viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );
22805                                         _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
22806                                         shadow.mapSize.y = _viewportSize.y;
22807
22808                                 }
22809
22810                         }
22811
22812                         if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
22813
22814                                 const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
22815
22816                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22817                                 shadow.map.texture.name = light.name + '.shadowMap';
22818
22819                                 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22820
22821                                 shadow.camera.updateProjectionMatrix();
22822
22823                         }
22824
22825                         if ( shadow.map === null ) {
22826
22827                                 const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
22828
22829                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22830                                 shadow.map.texture.name = light.name + '.shadowMap';
22831
22832                                 shadow.camera.updateProjectionMatrix();
22833
22834                         }
22835
22836                         _renderer.setRenderTarget( shadow.map );
22837                         _renderer.clear();
22838
22839                         const viewportCount = shadow.getViewportCount();
22840
22841                         for ( let vp = 0; vp < viewportCount; vp ++ ) {
22842
22843                                 const viewport = shadow.getViewport( vp );
22844
22845                                 _viewport.set(
22846                                         _viewportSize.x * viewport.x,
22847                                         _viewportSize.y * viewport.y,
22848                                         _viewportSize.x * viewport.z,
22849                                         _viewportSize.y * viewport.w
22850                                 );
22851
22852                                 _state.viewport( _viewport );
22853
22854                                 shadow.updateMatrices( light, vp );
22855
22856                                 _frustum = shadow.getFrustum();
22857
22858                                 renderObject( scene, camera, shadow.camera, light, this.type );
22859
22860                         }
22861
22862                         // do blur pass for VSM
22863
22864                         if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
22865
22866                                 VSMPass( shadow, camera );
22867
22868                         }
22869
22870                         shadow.needsUpdate = false;
22871
22872                 }
22873
22874                 scope.needsUpdate = false;
22875
22876                 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
22877
22878         };
22879
22880         function VSMPass( shadow, camera ) {
22881
22882                 const geometry = _objects.update( fullScreenMesh );
22883
22884                 // vertical pass
22885
22886                 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
22887                 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
22888                 shadowMaterialVertical.uniforms.radius.value = shadow.radius;
22889                 _renderer.setRenderTarget( shadow.mapPass );
22890                 _renderer.clear();
22891                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
22892
22893                 // horizontal pass
22894
22895                 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
22896                 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
22897                 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
22898                 _renderer.setRenderTarget( shadow.map );
22899                 _renderer.clear();
22900                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
22901
22902         }
22903
22904         function getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {
22905
22906                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
22907
22908                 let material = _depthMaterials[ index ];
22909
22910                 if ( material === undefined ) {
22911
22912                         material = new MeshDepthMaterial( {
22913
22914                                 depthPacking: RGBADepthPacking,
22915
22916                                 morphTargets: useMorphing,
22917                                 skinning: useSkinning
22918
22919                         } );
22920
22921                         _depthMaterials[ index ] = material;
22922
22923                 }
22924
22925                 return material;
22926
22927         }
22928
22929         function getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {
22930
22931                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
22932
22933                 let material = _distanceMaterials[ index ];
22934
22935                 if ( material === undefined ) {
22936
22937                         material = new MeshDistanceMaterial( {
22938
22939                                 morphTargets: useMorphing,
22940                                 skinning: useSkinning
22941
22942                         } );
22943
22944                         _distanceMaterials[ index ] = material;
22945
22946                 }
22947
22948                 return material;
22949
22950         }
22951
22952         function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
22953
22954                 let result = null;
22955
22956                 let getMaterialVariant = getDepthMaterialVariant;
22957                 let customMaterial = object.customDepthMaterial;
22958
22959                 if ( light.isPointLight === true ) {
22960
22961                         getMaterialVariant = getDistanceMaterialVariant;
22962                         customMaterial = object.customDistanceMaterial;
22963
22964                 }
22965
22966                 if ( customMaterial === undefined ) {
22967
22968                         let useMorphing = false;
22969
22970                         if ( material.morphTargets === true ) {
22971
22972                                 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
22973
22974                         }
22975
22976                         let useSkinning = false;
22977
22978                         if ( object.isSkinnedMesh === true ) {
22979
22980                                 if ( material.skinning === true ) {
22981
22982                                         useSkinning = true;
22983
22984                                 } else {
22985
22986                                         console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
22987
22988                                 }
22989
22990                         }
22991
22992                         const useInstancing = object.isInstancedMesh === true;
22993
22994                         result = getMaterialVariant( useMorphing, useSkinning, useInstancing );
22995
22996                 } else {
22997
22998                         result = customMaterial;
22999
23000                 }
23001
23002                 if ( _renderer.localClippingEnabled &&
23003                                 material.clipShadows === true &&
23004                                 material.clippingPlanes.length !== 0 ) {
23005
23006                         // in this case we need a unique material instance reflecting the
23007                         // appropriate state
23008
23009                         const keyA = result.uuid, keyB = material.uuid;
23010
23011                         let materialsForVariant = _materialCache[ keyA ];
23012
23013                         if ( materialsForVariant === undefined ) {
23014
23015                                 materialsForVariant = {};
23016                                 _materialCache[ keyA ] = materialsForVariant;
23017
23018                         }
23019
23020                         let cachedMaterial = materialsForVariant[ keyB ];
23021
23022                         if ( cachedMaterial === undefined ) {
23023
23024                                 cachedMaterial = result.clone();
23025                                 materialsForVariant[ keyB ] = cachedMaterial;
23026
23027                         }
23028
23029                         result = cachedMaterial;
23030
23031                 }
23032
23033                 result.visible = material.visible;
23034                 result.wireframe = material.wireframe;
23035
23036                 if ( type === VSMShadowMap ) {
23037
23038                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
23039
23040                 } else {
23041
23042                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
23043
23044                 }
23045
23046                 result.clipShadows = material.clipShadows;
23047                 result.clippingPlanes = material.clippingPlanes;
23048                 result.clipIntersection = material.clipIntersection;
23049
23050                 result.wireframeLinewidth = material.wireframeLinewidth;
23051                 result.linewidth = material.linewidth;
23052
23053                 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
23054
23055                         result.referencePosition.setFromMatrixPosition( light.matrixWorld );
23056                         result.nearDistance = shadowCameraNear;
23057                         result.farDistance = shadowCameraFar;
23058
23059                 }
23060
23061                 return result;
23062
23063         }
23064
23065         function renderObject( object, camera, shadowCamera, light, type ) {
23066
23067                 if ( object.visible === false ) return;
23068
23069                 const visible = object.layers.test( camera.layers );
23070
23071                 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
23072
23073                         if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
23074
23075                                 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
23076
23077                                 const geometry = _objects.update( object );
23078                                 const material = object.material;
23079
23080                                 if ( Array.isArray( material ) ) {
23081
23082                                         const groups = geometry.groups;
23083
23084                                         for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
23085
23086                                                 const group = groups[ k ];
23087                                                 const groupMaterial = material[ group.materialIndex ];
23088
23089                                                 if ( groupMaterial && groupMaterial.visible ) {
23090
23091                                                         const depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
23092
23093                                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
23094
23095                                                 }
23096
23097                                         }
23098
23099                                 } else if ( material.visible ) {
23100
23101                                         const depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
23102
23103                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
23104
23105                                 }
23106
23107                         }
23108
23109                 }
23110
23111                 const children = object.children;
23112
23113                 for ( let i = 0, l = children.length; i < l; i ++ ) {
23114
23115                         renderObject( children[ i ], camera, shadowCamera, light, type );
23116
23117                 }
23118
23119         }
23120
23121     }
23122
23123     function WebGLState( gl, extensions, capabilities ) {
23124
23125         const isWebGL2 = capabilities.isWebGL2;
23126
23127         function ColorBuffer() {
23128
23129                 let locked = false;
23130
23131                 const color = new Vector4();
23132                 let currentColorMask = null;
23133                 const currentColorClear = new Vector4( 0, 0, 0, 0 );
23134
23135                 return {
23136
23137                         setMask: function ( colorMask ) {
23138
23139                                 if ( currentColorMask !== colorMask && ! locked ) {
23140
23141                                         gl.colorMask( colorMask, colorMask, colorMask, colorMask );
23142                                         currentColorMask = colorMask;
23143
23144                                 }
23145
23146                         },
23147
23148                         setLocked: function ( lock ) {
23149
23150                                 locked = lock;
23151
23152                         },
23153
23154                         setClear: function ( r, g, b, a, premultipliedAlpha ) {
23155
23156                                 if ( premultipliedAlpha === true ) {
23157
23158                                         r *= a; g *= a; b *= a;
23159
23160                                 }
23161
23162                                 color.set( r, g, b, a );
23163
23164                                 if ( currentColorClear.equals( color ) === false ) {
23165
23166                                         gl.clearColor( r, g, b, a );
23167                                         currentColorClear.copy( color );
23168
23169                                 }
23170
23171                         },
23172
23173                         reset: function () {
23174
23175                                 locked = false;
23176
23177                                 currentColorMask = null;
23178                                 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
23179
23180                         }
23181
23182                 };
23183
23184         }
23185
23186         function DepthBuffer() {
23187
23188                 let locked = false;
23189
23190                 let currentDepthMask = null;
23191                 let currentDepthFunc = null;
23192                 let currentDepthClear = null;
23193
23194                 return {
23195
23196                         setTest: function ( depthTest ) {
23197
23198                                 if ( depthTest ) {
23199
23200                                         enable( 2929 );
23201
23202                                 } else {
23203
23204                                         disable( 2929 );
23205
23206                                 }
23207
23208                         },
23209
23210                         setMask: function ( depthMask ) {
23211
23212                                 if ( currentDepthMask !== depthMask && ! locked ) {
23213
23214                                         gl.depthMask( depthMask );
23215                                         currentDepthMask = depthMask;
23216
23217                                 }
23218
23219                         },
23220
23221                         setFunc: function ( depthFunc ) {
23222
23223                                 if ( currentDepthFunc !== depthFunc ) {
23224
23225                                         if ( depthFunc ) {
23226
23227                                                 switch ( depthFunc ) {
23228
23229                                                         case NeverDepth:
23230
23231                                                                 gl.depthFunc( 512 );
23232                                                                 break;
23233
23234                                                         case AlwaysDepth:
23235
23236                                                                 gl.depthFunc( 519 );
23237                                                                 break;
23238
23239                                                         case LessDepth:
23240
23241                                                                 gl.depthFunc( 513 );
23242                                                                 break;
23243
23244                                                         case LessEqualDepth:
23245
23246                                                                 gl.depthFunc( 515 );
23247                                                                 break;
23248
23249                                                         case EqualDepth:
23250
23251                                                                 gl.depthFunc( 514 );
23252                                                                 break;
23253
23254                                                         case GreaterEqualDepth:
23255
23256                                                                 gl.depthFunc( 518 );
23257                                                                 break;
23258
23259                                                         case GreaterDepth:
23260
23261                                                                 gl.depthFunc( 516 );
23262                                                                 break;
23263
23264                                                         case NotEqualDepth:
23265
23266                                                                 gl.depthFunc( 517 );
23267                                                                 break;
23268
23269                                                         default:
23270
23271                                                                 gl.depthFunc( 515 );
23272
23273                                                 }
23274
23275                                         } else {
23276
23277                                                 gl.depthFunc( 515 );
23278
23279                                         }
23280
23281                                         currentDepthFunc = depthFunc;
23282
23283                                 }
23284
23285                         },
23286
23287                         setLocked: function ( lock ) {
23288
23289                                 locked = lock;
23290
23291                         },
23292
23293                         setClear: function ( depth ) {
23294
23295                                 if ( currentDepthClear !== depth ) {
23296
23297                                         gl.clearDepth( depth );
23298                                         currentDepthClear = depth;
23299
23300                                 }
23301
23302                         },
23303
23304                         reset: function () {
23305
23306                                 locked = false;
23307
23308                                 currentDepthMask = null;
23309                                 currentDepthFunc = null;
23310                                 currentDepthClear = null;
23311
23312                         }
23313
23314                 };
23315
23316         }
23317
23318         function StencilBuffer() {
23319
23320                 let locked = false;
23321
23322                 let currentStencilMask = null;
23323                 let currentStencilFunc = null;
23324                 let currentStencilRef = null;
23325                 let currentStencilFuncMask = null;
23326                 let currentStencilFail = null;
23327                 let currentStencilZFail = null;
23328                 let currentStencilZPass = null;
23329                 let currentStencilClear = null;
23330
23331                 return {
23332
23333                         setTest: function ( stencilTest ) {
23334
23335                                 if ( ! locked ) {
23336
23337                                         if ( stencilTest ) {
23338
23339                                                 enable( 2960 );
23340
23341                                         } else {
23342
23343                                                 disable( 2960 );
23344
23345                                         }
23346
23347                                 }
23348
23349                         },
23350
23351                         setMask: function ( stencilMask ) {
23352
23353                                 if ( currentStencilMask !== stencilMask && ! locked ) {
23354
23355                                         gl.stencilMask( stencilMask );
23356                                         currentStencilMask = stencilMask;
23357
23358                                 }
23359
23360                         },
23361
23362                         setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
23363
23364                                 if ( currentStencilFunc !== stencilFunc ||
23365                                      currentStencilRef !== stencilRef ||
23366                                      currentStencilFuncMask !== stencilMask ) {
23367
23368                                         gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
23369
23370                                         currentStencilFunc = stencilFunc;
23371                                         currentStencilRef = stencilRef;
23372                                         currentStencilFuncMask = stencilMask;
23373
23374                                 }
23375
23376                         },
23377
23378                         setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
23379
23380                                 if ( currentStencilFail !== stencilFail ||
23381                                      currentStencilZFail !== stencilZFail ||
23382                                      currentStencilZPass !== stencilZPass ) {
23383
23384                                         gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
23385
23386                                         currentStencilFail = stencilFail;
23387                                         currentStencilZFail = stencilZFail;
23388                                         currentStencilZPass = stencilZPass;
23389
23390                                 }
23391
23392                         },
23393
23394                         setLocked: function ( lock ) {
23395
23396                                 locked = lock;
23397
23398                         },
23399
23400                         setClear: function ( stencil ) {
23401
23402                                 if ( currentStencilClear !== stencil ) {
23403
23404                                         gl.clearStencil( stencil );
23405                                         currentStencilClear = stencil;
23406
23407                                 }
23408
23409                         },
23410
23411                         reset: function () {
23412
23413                                 locked = false;
23414
23415                                 currentStencilMask = null;
23416                                 currentStencilFunc = null;
23417                                 currentStencilRef = null;
23418                                 currentStencilFuncMask = null;
23419                                 currentStencilFail = null;
23420                                 currentStencilZFail = null;
23421                                 currentStencilZPass = null;
23422                                 currentStencilClear = null;
23423
23424                         }
23425
23426                 };
23427
23428         }
23429
23430         //
23431
23432         const colorBuffer = new ColorBuffer();
23433         const depthBuffer = new DepthBuffer();
23434         const stencilBuffer = new StencilBuffer();
23435
23436         let enabledCapabilities = {};
23437
23438         let currentProgram = null;
23439
23440         let currentBlendingEnabled = null;
23441         let currentBlending = null;
23442         let currentBlendEquation = null;
23443         let currentBlendSrc = null;
23444         let currentBlendDst = null;
23445         let currentBlendEquationAlpha = null;
23446         let currentBlendSrcAlpha = null;
23447         let currentBlendDstAlpha = null;
23448         let currentPremultipledAlpha = false;
23449
23450         let currentFlipSided = null;
23451         let currentCullFace = null;
23452
23453         let currentLineWidth = null;
23454
23455         let currentPolygonOffsetFactor = null;
23456         let currentPolygonOffsetUnits = null;
23457
23458         const maxTextures = gl.getParameter( 35661 );
23459
23460         let lineWidthAvailable = false;
23461         let version = 0;
23462         const glVersion = gl.getParameter( 7938 );
23463
23464         if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
23465
23466                 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
23467                 lineWidthAvailable = ( version >= 1.0 );
23468
23469         } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
23470
23471                 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
23472                 lineWidthAvailable = ( version >= 2.0 );
23473
23474         }
23475
23476         let currentTextureSlot = null;
23477         let currentBoundTextures = {};
23478
23479         const currentScissor = new Vector4();
23480         const currentViewport = new Vector4();
23481
23482         function createTexture( type, target, count ) {
23483
23484                 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
23485                 const texture = gl.createTexture();
23486
23487                 gl.bindTexture( type, texture );
23488                 gl.texParameteri( type, 10241, 9728 );
23489                 gl.texParameteri( type, 10240, 9728 );
23490
23491                 for ( let i = 0; i < count; i ++ ) {
23492
23493                         gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
23494
23495                 }
23496
23497                 return texture;
23498
23499         }
23500
23501         const emptyTextures = {};
23502         emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
23503         emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
23504
23505         // init
23506
23507         colorBuffer.setClear( 0, 0, 0, 1 );
23508         depthBuffer.setClear( 1 );
23509         stencilBuffer.setClear( 0 );
23510
23511         enable( 2929 );
23512         depthBuffer.setFunc( LessEqualDepth );
23513
23514         setFlipSided( false );
23515         setCullFace( CullFaceBack );
23516         enable( 2884 );
23517
23518         setBlending( NoBlending );
23519
23520         //
23521
23522         function enable( id ) {
23523
23524                 if ( enabledCapabilities[ id ] !== true ) {
23525
23526                         gl.enable( id );
23527                         enabledCapabilities[ id ] = true;
23528
23529                 }
23530
23531         }
23532
23533         function disable( id ) {
23534
23535                 if ( enabledCapabilities[ id ] !== false ) {
23536
23537                         gl.disable( id );
23538                         enabledCapabilities[ id ] = false;
23539
23540                 }
23541
23542         }
23543
23544         function useProgram( program ) {
23545
23546                 if ( currentProgram !== program ) {
23547
23548                         gl.useProgram( program );
23549
23550                         currentProgram = program;
23551
23552                         return true;
23553
23554                 }
23555
23556                 return false;
23557
23558         }
23559
23560         const equationToGL = {
23561                 [ AddEquation ]: 32774,
23562                 [ SubtractEquation ]: 32778,
23563                 [ ReverseSubtractEquation ]: 32779
23564         };
23565
23566         if ( isWebGL2 ) {
23567
23568                 equationToGL[ MinEquation ] = 32775;
23569                 equationToGL[ MaxEquation ] = 32776;
23570
23571         } else {
23572
23573                 const extension = extensions.get( 'EXT_blend_minmax' );
23574
23575                 if ( extension !== null ) {
23576
23577                         equationToGL[ MinEquation ] = extension.MIN_EXT;
23578                         equationToGL[ MaxEquation ] = extension.MAX_EXT;
23579
23580                 }
23581
23582         }
23583
23584         const factorToGL = {
23585                 [ ZeroFactor ]: 0,
23586                 [ OneFactor ]: 1,
23587                 [ SrcColorFactor ]: 768,
23588                 [ SrcAlphaFactor ]: 770,
23589                 [ SrcAlphaSaturateFactor ]: 776,
23590                 [ DstColorFactor ]: 774,
23591                 [ DstAlphaFactor ]: 772,
23592                 [ OneMinusSrcColorFactor ]: 769,
23593                 [ OneMinusSrcAlphaFactor ]: 771,
23594                 [ OneMinusDstColorFactor ]: 775,
23595                 [ OneMinusDstAlphaFactor ]: 773
23596         };
23597
23598         function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
23599
23600                 if ( blending === NoBlending ) {
23601
23602                         if ( currentBlendingEnabled ) {
23603
23604                                 disable( 3042 );
23605                                 currentBlendingEnabled = false;
23606
23607                         }
23608
23609                         return;
23610
23611                 }
23612
23613                 if ( ! currentBlendingEnabled ) {
23614
23615                         enable( 3042 );
23616                         currentBlendingEnabled = true;
23617
23618                 }
23619
23620                 if ( blending !== CustomBlending ) {
23621
23622                         if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
23623
23624                                 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
23625
23626                                         gl.blendEquation( 32774 );
23627
23628                                         currentBlendEquation = AddEquation;
23629                                         currentBlendEquationAlpha = AddEquation;
23630
23631                                 }
23632
23633                                 if ( premultipliedAlpha ) {
23634
23635                                         switch ( blending ) {
23636
23637                                                 case NormalBlending:
23638                                                         gl.blendFuncSeparate( 1, 771, 1, 771 );
23639                                                         break;
23640
23641                                                 case AdditiveBlending:
23642                                                         gl.blendFunc( 1, 1 );
23643                                                         break;
23644
23645                                                 case SubtractiveBlending:
23646                                                         gl.blendFuncSeparate( 0, 0, 769, 771 );
23647                                                         break;
23648
23649                                                 case MultiplyBlending:
23650                                                         gl.blendFuncSeparate( 0, 768, 0, 770 );
23651                                                         break;
23652
23653                                                 default:
23654                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23655                                                         break;
23656
23657                                         }
23658
23659                                 } else {
23660
23661                                         switch ( blending ) {
23662
23663                                                 case NormalBlending:
23664                                                         gl.blendFuncSeparate( 770, 771, 1, 771 );
23665                                                         break;
23666
23667                                                 case AdditiveBlending:
23668                                                         gl.blendFunc( 770, 1 );
23669                                                         break;
23670
23671                                                 case SubtractiveBlending:
23672                                                         gl.blendFunc( 0, 769 );
23673                                                         break;
23674
23675                                                 case MultiplyBlending:
23676                                                         gl.blendFunc( 0, 768 );
23677                                                         break;
23678
23679                                                 default:
23680                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23681                                                         break;
23682
23683                                         }
23684
23685                                 }
23686
23687                                 currentBlendSrc = null;
23688                                 currentBlendDst = null;
23689                                 currentBlendSrcAlpha = null;
23690                                 currentBlendDstAlpha = null;
23691
23692                                 currentBlending = blending;
23693                                 currentPremultipledAlpha = premultipliedAlpha;
23694
23695                         }
23696
23697                         return;
23698
23699                 }
23700
23701                 // custom blending
23702
23703                 blendEquationAlpha = blendEquationAlpha || blendEquation;
23704                 blendSrcAlpha = blendSrcAlpha || blendSrc;
23705                 blendDstAlpha = blendDstAlpha || blendDst;
23706
23707                 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
23708
23709                         gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
23710
23711                         currentBlendEquation = blendEquation;
23712                         currentBlendEquationAlpha = blendEquationAlpha;
23713
23714                 }
23715
23716                 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
23717
23718                         gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
23719
23720                         currentBlendSrc = blendSrc;
23721                         currentBlendDst = blendDst;
23722                         currentBlendSrcAlpha = blendSrcAlpha;
23723                         currentBlendDstAlpha = blendDstAlpha;
23724
23725                 }
23726
23727                 currentBlending = blending;
23728                 currentPremultipledAlpha = null;
23729
23730         }
23731
23732         function setMaterial( material, frontFaceCW ) {
23733
23734                 material.side === DoubleSide
23735                         ? disable( 2884 )
23736                         : enable( 2884 );
23737
23738                 let flipSided = ( material.side === BackSide );
23739                 if ( frontFaceCW ) flipSided = ! flipSided;
23740
23741                 setFlipSided( flipSided );
23742
23743                 ( material.blending === NormalBlending && material.transparent === false )
23744                         ? setBlending( NoBlending )
23745                         : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
23746
23747                 depthBuffer.setFunc( material.depthFunc );
23748                 depthBuffer.setTest( material.depthTest );
23749                 depthBuffer.setMask( material.depthWrite );
23750                 colorBuffer.setMask( material.colorWrite );
23751
23752                 const stencilWrite = material.stencilWrite;
23753                 stencilBuffer.setTest( stencilWrite );
23754                 if ( stencilWrite ) {
23755
23756                         stencilBuffer.setMask( material.stencilWriteMask );
23757                         stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
23758                         stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
23759
23760                 }
23761
23762                 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
23763
23764         }
23765
23766         //
23767
23768         function setFlipSided( flipSided ) {
23769
23770                 if ( currentFlipSided !== flipSided ) {
23771
23772                         if ( flipSided ) {
23773
23774                                 gl.frontFace( 2304 );
23775
23776                         } else {
23777
23778                                 gl.frontFace( 2305 );
23779
23780                         }
23781
23782                         currentFlipSided = flipSided;
23783
23784                 }
23785
23786         }
23787
23788         function setCullFace( cullFace ) {
23789
23790                 if ( cullFace !== CullFaceNone ) {
23791
23792                         enable( 2884 );
23793
23794                         if ( cullFace !== currentCullFace ) {
23795
23796                                 if ( cullFace === CullFaceBack ) {
23797
23798                                         gl.cullFace( 1029 );
23799
23800                                 } else if ( cullFace === CullFaceFront ) {
23801
23802                                         gl.cullFace( 1028 );
23803
23804                                 } else {
23805
23806                                         gl.cullFace( 1032 );
23807
23808                                 }
23809
23810                         }
23811
23812                 } else {
23813
23814                         disable( 2884 );
23815
23816                 }
23817
23818                 currentCullFace = cullFace;
23819
23820         }
23821
23822         function setLineWidth( width ) {
23823
23824                 if ( width !== currentLineWidth ) {
23825
23826                         if ( lineWidthAvailable ) gl.lineWidth( width );
23827
23828                         currentLineWidth = width;
23829
23830                 }
23831
23832         }
23833
23834         function setPolygonOffset( polygonOffset, factor, units ) {
23835
23836                 if ( polygonOffset ) {
23837
23838                         enable( 32823 );
23839
23840                         if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
23841
23842                                 gl.polygonOffset( factor, units );
23843
23844                                 currentPolygonOffsetFactor = factor;
23845                                 currentPolygonOffsetUnits = units;
23846
23847                         }
23848
23849                 } else {
23850
23851                         disable( 32823 );
23852
23853                 }
23854
23855         }
23856
23857         function setScissorTest( scissorTest ) {
23858
23859                 if ( scissorTest ) {
23860
23861                         enable( 3089 );
23862
23863                 } else {
23864
23865                         disable( 3089 );
23866
23867                 }
23868
23869         }
23870
23871         // texture
23872
23873         function activeTexture( webglSlot ) {
23874
23875                 if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
23876
23877                 if ( currentTextureSlot !== webglSlot ) {
23878
23879                         gl.activeTexture( webglSlot );
23880                         currentTextureSlot = webglSlot;
23881
23882                 }
23883
23884         }
23885
23886         function bindTexture( webglType, webglTexture ) {
23887
23888                 if ( currentTextureSlot === null ) {
23889
23890                         activeTexture();
23891
23892                 }
23893
23894                 let boundTexture = currentBoundTextures[ currentTextureSlot ];
23895
23896                 if ( boundTexture === undefined ) {
23897
23898                         boundTexture = { type: undefined, texture: undefined };
23899                         currentBoundTextures[ currentTextureSlot ] = boundTexture;
23900
23901                 }
23902
23903                 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
23904
23905                         gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
23906
23907                         boundTexture.type = webglType;
23908                         boundTexture.texture = webglTexture;
23909
23910                 }
23911
23912         }
23913
23914         function unbindTexture() {
23915
23916                 const boundTexture = currentBoundTextures[ currentTextureSlot ];
23917
23918                 if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
23919
23920                         gl.bindTexture( boundTexture.type, null );
23921
23922                         boundTexture.type = undefined;
23923                         boundTexture.texture = undefined;
23924
23925                 }
23926
23927         }
23928
23929         function compressedTexImage2D() {
23930
23931                 try {
23932
23933                         gl.compressedTexImage2D.apply( gl, arguments );
23934
23935                 } catch ( error ) {
23936
23937                         console.error( 'THREE.WebGLState:', error );
23938
23939                 }
23940
23941         }
23942
23943         function texImage2D() {
23944
23945                 try {
23946
23947                         gl.texImage2D.apply( gl, arguments );
23948
23949                 } catch ( error ) {
23950
23951                         console.error( 'THREE.WebGLState:', error );
23952
23953                 }
23954
23955         }
23956
23957         function texImage3D() {
23958
23959                 try {
23960
23961                         gl.texImage3D.apply( gl, arguments );
23962
23963                 } catch ( error ) {
23964
23965                         console.error( 'THREE.WebGLState:', error );
23966
23967                 }
23968
23969         }
23970
23971         //
23972
23973         function scissor( scissor ) {
23974
23975                 if ( currentScissor.equals( scissor ) === false ) {
23976
23977                         gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
23978                         currentScissor.copy( scissor );
23979
23980                 }
23981
23982         }
23983
23984         function viewport( viewport ) {
23985
23986                 if ( currentViewport.equals( viewport ) === false ) {
23987
23988                         gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
23989                         currentViewport.copy( viewport );
23990
23991                 }
23992
23993         }
23994
23995         //
23996
23997         function reset() {
23998
23999                 enabledCapabilities = {};
24000
24001                 currentTextureSlot = null;
24002                 currentBoundTextures = {};
24003
24004                 currentProgram = null;
24005
24006                 currentBlendingEnabled = null;
24007                 currentBlending = null;
24008                 currentBlendEquation = null;
24009                 currentBlendSrc = null;
24010                 currentBlendDst = null;
24011                 currentBlendEquationAlpha = null;
24012                 currentBlendSrcAlpha = null;
24013                 currentBlendDstAlpha = null;
24014                 currentPremultipledAlpha = false;
24015
24016                 currentFlipSided = null;
24017                 currentCullFace = null;
24018
24019                 currentLineWidth = null;
24020
24021                 currentPolygonOffsetFactor = null;
24022                 currentPolygonOffsetUnits = null;
24023
24024                 colorBuffer.reset();
24025                 depthBuffer.reset();
24026                 stencilBuffer.reset();
24027
24028         }
24029
24030         return {
24031
24032                 buffers: {
24033                         color: colorBuffer,
24034                         depth: depthBuffer,
24035                         stencil: stencilBuffer
24036                 },
24037
24038                 enable: enable,
24039                 disable: disable,
24040
24041                 useProgram: useProgram,
24042
24043                 setBlending: setBlending,
24044                 setMaterial: setMaterial,
24045
24046                 setFlipSided: setFlipSided,
24047                 setCullFace: setCullFace,
24048
24049                 setLineWidth: setLineWidth,
24050                 setPolygonOffset: setPolygonOffset,
24051
24052                 setScissorTest: setScissorTest,
24053
24054                 activeTexture: activeTexture,
24055                 bindTexture: bindTexture,
24056                 unbindTexture: unbindTexture,
24057                 compressedTexImage2D: compressedTexImage2D,
24058                 texImage2D: texImage2D,
24059                 texImage3D: texImage3D,
24060
24061                 scissor: scissor,
24062                 viewport: viewport,
24063
24064                 reset: reset
24065
24066         };
24067
24068     }
24069
24070     function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
24071
24072         const isWebGL2 = capabilities.isWebGL2;
24073         const maxTextures = capabilities.maxTextures;
24074         const maxCubemapSize = capabilities.maxCubemapSize;
24075         const maxTextureSize = capabilities.maxTextureSize;
24076         const maxSamples = capabilities.maxSamples;
24077
24078         const _videoTextures = new WeakMap();
24079         let _canvas;
24080
24081         // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
24082         // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
24083         // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
24084
24085         let useOffscreenCanvas = false;
24086
24087         try {
24088
24089                 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
24090                         && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
24091
24092         } catch ( err ) {
24093
24094                 // Ignore any errors
24095
24096         }
24097
24098         function createCanvas( width, height ) {
24099
24100                 // Use OffscreenCanvas when available. Specially needed in web workers
24101
24102                 return useOffscreenCanvas ?
24103                         new OffscreenCanvas( width, height ) :
24104                         document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
24105
24106         }
24107
24108         function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
24109
24110                 let scale = 1;
24111
24112                 // handle case if texture exceeds max size
24113
24114                 if ( image.width > maxSize || image.height > maxSize ) {
24115
24116                         scale = maxSize / Math.max( image.width, image.height );
24117
24118                 }
24119
24120                 // only perform resize if necessary
24121
24122                 if ( scale < 1 || needsPowerOfTwo === true ) {
24123
24124                         // only perform resize for certain image types
24125
24126                         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
24127                                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
24128                                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
24129
24130                                 const floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;
24131
24132                                 const width = floor( scale * image.width );
24133                                 const height = floor( scale * image.height );
24134
24135                                 if ( _canvas === undefined ) _canvas = createCanvas( width, height );
24136
24137                                 // cube textures can't reuse the same canvas
24138
24139                                 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
24140
24141                                 canvas.width = width;
24142                                 canvas.height = height;
24143
24144                                 const context = canvas.getContext( '2d' );
24145                                 context.drawImage( image, 0, 0, width, height );
24146
24147                                 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
24148
24149                                 return canvas;
24150
24151                         } else {
24152
24153                                 if ( 'data' in image ) {
24154
24155                                         console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
24156
24157                                 }
24158
24159                                 return image;
24160
24161                         }
24162
24163                 }
24164
24165                 return image;
24166
24167         }
24168
24169         function isPowerOfTwo( image ) {
24170
24171                 return MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );
24172
24173         }
24174
24175         function textureNeedsPowerOfTwo( texture ) {
24176
24177                 if ( isWebGL2 ) return false;
24178
24179                 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
24180                         ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
24181
24182         }
24183
24184         function textureNeedsGenerateMipmaps( texture, supportsMips ) {
24185
24186                 return texture.generateMipmaps && supportsMips &&
24187                         texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
24188
24189         }
24190
24191         function generateMipmap( target, texture, width, height ) {
24192
24193                 _gl.generateMipmap( target );
24194
24195                 const textureProperties = properties.get( texture );
24196
24197                 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
24198                 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
24199
24200         }
24201
24202         function getInternalFormat( internalFormatName, glFormat, glType ) {
24203
24204                 if ( isWebGL2 === false ) return glFormat;
24205
24206                 if ( internalFormatName !== null ) {
24207
24208                         if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
24209
24210                         console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
24211
24212                 }
24213
24214                 let internalFormat = glFormat;
24215
24216                 if ( glFormat === 6403 ) {
24217
24218                         if ( glType === 5126 ) internalFormat = 33326;
24219                         if ( glType === 5131 ) internalFormat = 33325;
24220                         if ( glType === 5121 ) internalFormat = 33321;
24221
24222                 }
24223
24224                 if ( glFormat === 6407 ) {
24225
24226                         if ( glType === 5126 ) internalFormat = 34837;
24227                         if ( glType === 5131 ) internalFormat = 34843;
24228                         if ( glType === 5121 ) internalFormat = 32849;
24229
24230                 }
24231
24232                 if ( glFormat === 6408 ) {
24233
24234                         if ( glType === 5126 ) internalFormat = 34836;
24235                         if ( glType === 5131 ) internalFormat = 34842;
24236                         if ( glType === 5121 ) internalFormat = 32856;
24237
24238                 }
24239
24240                 if ( internalFormat === 33325 || internalFormat === 33326 ||
24241                         internalFormat === 34842 || internalFormat === 34836 ) {
24242
24243                         extensions.get( 'EXT_color_buffer_float' );
24244
24245                 }
24246
24247                 return internalFormat;
24248
24249         }
24250
24251         // Fallback filters for non-power-of-2 textures
24252
24253         function filterFallback( f ) {
24254
24255                 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
24256
24257                         return 9728;
24258
24259                 }
24260
24261                 return 9729;
24262
24263         }
24264
24265         //
24266
24267         function onTextureDispose( event ) {
24268
24269                 const texture = event.target;
24270
24271                 texture.removeEventListener( 'dispose', onTextureDispose );
24272
24273                 deallocateTexture( texture );
24274
24275                 if ( texture.isVideoTexture ) {
24276
24277                         _videoTextures.delete( texture );
24278
24279                 }
24280
24281                 info.memory.textures --;
24282
24283         }
24284
24285         function onRenderTargetDispose( event ) {
24286
24287                 const renderTarget = event.target;
24288
24289                 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
24290
24291                 deallocateRenderTarget( renderTarget );
24292
24293                 info.memory.textures --;
24294
24295         }
24296
24297         //
24298
24299         function deallocateTexture( texture ) {
24300
24301                 const textureProperties = properties.get( texture );
24302
24303                 if ( textureProperties.__webglInit === undefined ) return;
24304
24305                 _gl.deleteTexture( textureProperties.__webglTexture );
24306
24307                 properties.remove( texture );
24308
24309         }
24310
24311         function deallocateRenderTarget( renderTarget ) {
24312
24313                 const renderTargetProperties = properties.get( renderTarget );
24314                 const textureProperties = properties.get( renderTarget.texture );
24315
24316                 if ( ! renderTarget ) return;
24317
24318                 if ( textureProperties.__webglTexture !== undefined ) {
24319
24320                         _gl.deleteTexture( textureProperties.__webglTexture );
24321
24322                 }
24323
24324                 if ( renderTarget.depthTexture ) {
24325
24326                         renderTarget.depthTexture.dispose();
24327
24328                 }
24329
24330                 if ( renderTarget.isWebGLCubeRenderTarget ) {
24331
24332                         for ( let i = 0; i < 6; i ++ ) {
24333
24334                                 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
24335                                 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
24336
24337                         }
24338
24339                 } else {
24340
24341                         _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
24342                         if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
24343                         if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
24344                         if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
24345                         if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
24346
24347                 }
24348
24349                 properties.remove( renderTarget.texture );
24350                 properties.remove( renderTarget );
24351
24352         }
24353
24354         //
24355
24356         let textureUnits = 0;
24357
24358         function resetTextureUnits() {
24359
24360                 textureUnits = 0;
24361
24362         }
24363
24364         function allocateTextureUnit() {
24365
24366                 const textureUnit = textureUnits;
24367
24368                 if ( textureUnit >= maxTextures ) {
24369
24370                         console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
24371
24372                 }
24373
24374                 textureUnits += 1;
24375
24376                 return textureUnit;
24377
24378         }
24379
24380         //
24381
24382         function setTexture2D( texture, slot ) {
24383
24384                 const textureProperties = properties.get( texture );
24385
24386                 if ( texture.isVideoTexture ) updateVideoTexture( texture );
24387
24388                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24389
24390                         const image = texture.image;
24391
24392                         if ( image === undefined ) {
24393
24394                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
24395
24396                         } else if ( image.complete === false ) {
24397
24398                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
24399
24400                         } else {
24401
24402                                 uploadTexture( textureProperties, texture, slot );
24403                                 return;
24404
24405                         }
24406
24407                 }
24408
24409                 state.activeTexture( 33984 + slot );
24410                 state.bindTexture( 3553, textureProperties.__webglTexture );
24411
24412         }
24413
24414         function setTexture2DArray( texture, slot ) {
24415
24416                 const textureProperties = properties.get( texture );
24417
24418                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24419
24420                         uploadTexture( textureProperties, texture, slot );
24421                         return;
24422
24423                 }
24424
24425                 state.activeTexture( 33984 + slot );
24426                 state.bindTexture( 35866, textureProperties.__webglTexture );
24427
24428         }
24429
24430         function setTexture3D( texture, slot ) {
24431
24432                 const textureProperties = properties.get( texture );
24433
24434                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24435
24436                         uploadTexture( textureProperties, texture, slot );
24437                         return;
24438
24439                 }
24440
24441                 state.activeTexture( 33984 + slot );
24442                 state.bindTexture( 32879, textureProperties.__webglTexture );
24443
24444         }
24445
24446         function setTextureCube( texture, slot ) {
24447
24448                 const textureProperties = properties.get( texture );
24449
24450                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24451
24452                         uploadCubeTexture( textureProperties, texture, slot );
24453                         return;
24454
24455                 }
24456
24457                 state.activeTexture( 33984 + slot );
24458                 state.bindTexture( 34067, textureProperties.__webglTexture );
24459
24460         }
24461
24462         const wrappingToGL = {
24463                 [ RepeatWrapping ]: 10497,
24464                 [ ClampToEdgeWrapping ]: 33071,
24465                 [ MirroredRepeatWrapping ]: 33648
24466         };
24467
24468         const filterToGL = {
24469                 [ NearestFilter ]: 9728,
24470                 [ NearestMipmapNearestFilter ]: 9984,
24471                 [ NearestMipmapLinearFilter ]: 9986,
24472
24473                 [ LinearFilter ]: 9729,
24474                 [ LinearMipmapNearestFilter ]: 9985,
24475                 [ LinearMipmapLinearFilter ]: 9987
24476         };
24477
24478         function setTextureParameters( textureType, texture, supportsMips ) {
24479
24480                 if ( supportsMips ) {
24481
24482                         _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
24483                         _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
24484
24485                         if ( textureType === 32879 || textureType === 35866 ) {
24486
24487                                 _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
24488
24489                         }
24490
24491                         _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
24492                         _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
24493
24494                 } else {
24495
24496                         _gl.texParameteri( textureType, 10242, 33071 );
24497                         _gl.texParameteri( textureType, 10243, 33071 );
24498
24499                         if ( textureType === 32879 || textureType === 35866 ) {
24500
24501                                 _gl.texParameteri( textureType, 32882, 33071 );
24502
24503                         }
24504
24505                         if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
24506
24507                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
24508
24509                         }
24510
24511                         _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
24512                         _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
24513
24514                         if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
24515
24516                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
24517
24518                         }
24519
24520                 }
24521
24522                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
24523
24524                 if ( extension ) {
24525
24526                         if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
24527                         if ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
24528
24529                         if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
24530
24531                                 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
24532                                 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
24533
24534                         }
24535
24536                 }
24537
24538         }
24539
24540         function initTexture( textureProperties, texture ) {
24541
24542                 if ( textureProperties.__webglInit === undefined ) {
24543
24544                         textureProperties.__webglInit = true;
24545
24546                         texture.addEventListener( 'dispose', onTextureDispose );
24547
24548                         textureProperties.__webglTexture = _gl.createTexture();
24549
24550                         info.memory.textures ++;
24551
24552                 }
24553
24554         }
24555
24556         function uploadTexture( textureProperties, texture, slot ) {
24557
24558                 let textureType = 3553;
24559
24560                 if ( texture.isDataTexture2DArray ) textureType = 35866;
24561                 if ( texture.isDataTexture3D ) textureType = 32879;
24562
24563                 initTexture( textureProperties, texture );
24564
24565                 state.activeTexture( 33984 + slot );
24566                 state.bindTexture( textureType, textureProperties.__webglTexture );
24567
24568                 _gl.pixelStorei( 37440, texture.flipY );
24569                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
24570                 _gl.pixelStorei( 3317, texture.unpackAlignment );
24571
24572                 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
24573                 const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
24574
24575                 const supportsMips = isPowerOfTwo( image ) || isWebGL2,
24576                         glFormat = utils.convert( texture.format );
24577
24578                 let glType = utils.convert( texture.type ),
24579                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
24580
24581                 setTextureParameters( textureType, texture, supportsMips );
24582
24583                 let mipmap;
24584                 const mipmaps = texture.mipmaps;
24585
24586                 if ( texture.isDepthTexture ) {
24587
24588                         // populate depth texture with dummy data
24589
24590                         glInternalFormat = 6402;
24591
24592                         if ( isWebGL2 ) {
24593
24594                                 if ( texture.type === FloatType ) {
24595
24596                                         glInternalFormat = 36012;
24597
24598                                 } else if ( texture.type === UnsignedIntType ) {
24599
24600                                         glInternalFormat = 33190;
24601
24602                                 } else if ( texture.type === UnsignedInt248Type ) {
24603
24604                                         glInternalFormat = 35056;
24605
24606                                 } else {
24607
24608                                         glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
24609
24610                                 }
24611
24612                         } else {
24613
24614                                 if ( texture.type === FloatType ) {
24615
24616                                         console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
24617
24618                                 }
24619
24620                         }
24621
24622                         // validation checks for WebGL 1
24623
24624                         if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
24625
24626                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
24627                                 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
24628                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24629                                 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
24630
24631                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
24632
24633                                         texture.type = UnsignedShortType;
24634                                         glType = utils.convert( texture.type );
24635
24636                                 }
24637
24638                         }
24639
24640                         if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
24641
24642                                 // Depth stencil textures need the DEPTH_STENCIL internal format
24643                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24644                                 glInternalFormat = 34041;
24645
24646                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
24647                                 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
24648                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24649                                 if ( texture.type !== UnsignedInt248Type ) {
24650
24651                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
24652
24653                                         texture.type = UnsignedInt248Type;
24654                                         glType = utils.convert( texture.type );
24655
24656                                 }
24657
24658                         }
24659
24660                         //
24661
24662                         state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
24663
24664                 } else if ( texture.isDataTexture ) {
24665
24666                         // use manually created mipmaps if available
24667                         // if there are no manual mipmaps
24668                         // set 0 level mipmap and then use GL to generate other mipmap levels
24669
24670                         if ( mipmaps.length > 0 && supportsMips ) {
24671
24672                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24673
24674                                         mipmap = mipmaps[ i ];
24675                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24676
24677                                 }
24678
24679                                 texture.generateMipmaps = false;
24680                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
24681
24682                         } else {
24683
24684                                 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
24685                                 textureProperties.__maxMipLevel = 0;
24686
24687                         }
24688
24689                 } else if ( texture.isCompressedTexture ) {
24690
24691                         for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24692
24693                                 mipmap = mipmaps[ i ];
24694
24695                                 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
24696
24697                                         if ( glFormat !== null ) {
24698
24699                                                 state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24700
24701                                         } else {
24702
24703                                                 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24704
24705                                         }
24706
24707                                 } else {
24708
24709                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24710
24711                                 }
24712
24713                         }
24714
24715                         textureProperties.__maxMipLevel = mipmaps.length - 1;
24716
24717                 } else if ( texture.isDataTexture2DArray ) {
24718
24719                         state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24720                         textureProperties.__maxMipLevel = 0;
24721
24722                 } else if ( texture.isDataTexture3D ) {
24723
24724                         state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24725                         textureProperties.__maxMipLevel = 0;
24726
24727                 } else {
24728
24729                         // regular Texture (image, video, canvas)
24730
24731                         // use manually created mipmaps if available
24732                         // if there are no manual mipmaps
24733                         // set 0 level mipmap and then use GL to generate other mipmap levels
24734
24735                         if ( mipmaps.length > 0 && supportsMips ) {
24736
24737                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24738
24739                                         mipmap = mipmaps[ i ];
24740                                         state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
24741
24742                                 }
24743
24744                                 texture.generateMipmaps = false;
24745                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
24746
24747                         } else {
24748
24749                                 state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
24750                                 textureProperties.__maxMipLevel = 0;
24751
24752                         }
24753
24754                 }
24755
24756                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
24757
24758                         generateMipmap( textureType, texture, image.width, image.height );
24759
24760                 }
24761
24762                 textureProperties.__version = texture.version;
24763
24764                 if ( texture.onUpdate ) texture.onUpdate( texture );
24765
24766         }
24767
24768         function uploadCubeTexture( textureProperties, texture, slot ) {
24769
24770                 if ( texture.image.length !== 6 ) return;
24771
24772                 initTexture( textureProperties, texture );
24773
24774                 state.activeTexture( 33984 + slot );
24775                 state.bindTexture( 34067, textureProperties.__webglTexture );
24776
24777                 _gl.pixelStorei( 37440, texture.flipY );
24778                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
24779                 _gl.pixelStorei( 3317, texture.unpackAlignment );
24780
24781                 const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
24782                 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
24783
24784                 const cubeImage = [];
24785
24786                 for ( let i = 0; i < 6; i ++ ) {
24787
24788                         if ( ! isCompressed && ! isDataTexture ) {
24789
24790                                 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
24791
24792                         } else {
24793
24794                                 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
24795
24796                         }
24797
24798                 }
24799
24800                 const image = cubeImage[ 0 ],
24801                         supportsMips = isPowerOfTwo( image ) || isWebGL2,
24802                         glFormat = utils.convert( texture.format ),
24803                         glType = utils.convert( texture.type ),
24804                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
24805
24806                 setTextureParameters( 34067, texture, supportsMips );
24807
24808                 let mipmaps;
24809
24810                 if ( isCompressed ) {
24811
24812                         for ( let i = 0; i < 6; i ++ ) {
24813
24814                                 mipmaps = cubeImage[ i ].mipmaps;
24815
24816                                 for ( let j = 0; j < mipmaps.length; j ++ ) {
24817
24818                                         const mipmap = mipmaps[ j ];
24819
24820                                         if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
24821
24822                                                 if ( glFormat !== null ) {
24823
24824                                                         state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24825
24826                                                 } else {
24827
24828                                                         console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
24829
24830                                                 }
24831
24832                                         } else {
24833
24834                                                 state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24835
24836                                         }
24837
24838                                 }
24839
24840                         }
24841
24842                         textureProperties.__maxMipLevel = mipmaps.length - 1;
24843
24844                 } else {
24845
24846                         mipmaps = texture.mipmaps;
24847
24848                         for ( let i = 0; i < 6; i ++ ) {
24849
24850                                 if ( isDataTexture ) {
24851
24852                                         state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
24853
24854                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
24855
24856                                                 const mipmap = mipmaps[ j ];
24857                                                 const mipmapImage = mipmap.image[ i ].image;
24858
24859                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
24860
24861                                         }
24862
24863                                 } else {
24864
24865                                         state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
24866
24867                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
24868
24869                                                 const mipmap = mipmaps[ j ];
24870
24871                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
24872
24873                                         }
24874
24875                                 }
24876
24877                         }
24878
24879                         textureProperties.__maxMipLevel = mipmaps.length;
24880
24881                 }
24882
24883                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
24884
24885                         // We assume images for cube map have the same size.
24886                         generateMipmap( 34067, texture, image.width, image.height );
24887
24888                 }
24889
24890                 textureProperties.__version = texture.version;
24891
24892                 if ( texture.onUpdate ) texture.onUpdate( texture );
24893
24894         }
24895
24896         // Render targets
24897
24898         // Setup storage for target texture and bind it to correct framebuffer
24899         function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
24900
24901                 const glFormat = utils.convert( renderTarget.texture.format );
24902                 const glType = utils.convert( renderTarget.texture.type );
24903                 const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
24904                 state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
24905                 _gl.bindFramebuffer( 36160, framebuffer );
24906                 _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
24907                 _gl.bindFramebuffer( 36160, null );
24908
24909         }
24910
24911         // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
24912         function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
24913
24914                 _gl.bindRenderbuffer( 36161, renderbuffer );
24915
24916                 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
24917
24918                         let glInternalFormat = 33189;
24919
24920                         if ( isMultisample ) {
24921
24922                                 const depthTexture = renderTarget.depthTexture;
24923
24924                                 if ( depthTexture && depthTexture.isDepthTexture ) {
24925
24926                                         if ( depthTexture.type === FloatType ) {
24927
24928                                                 glInternalFormat = 36012;
24929
24930                                         } else if ( depthTexture.type === UnsignedIntType ) {
24931
24932                                                 glInternalFormat = 33190;
24933
24934                                         }
24935
24936                                 }
24937
24938                                 const samples = getRenderTargetSamples( renderTarget );
24939
24940                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
24941
24942                         } else {
24943
24944                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
24945
24946                         }
24947
24948                         _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
24949
24950                 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
24951
24952                         if ( isMultisample ) {
24953
24954                                 const samples = getRenderTargetSamples( renderTarget );
24955
24956                                 _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
24957
24958                         } else {
24959
24960                                 _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
24961
24962                         }
24963
24964
24965                         _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
24966
24967                 } else {
24968
24969                         const glFormat = utils.convert( renderTarget.texture.format );
24970                         const glType = utils.convert( renderTarget.texture.type );
24971                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
24972
24973                         if ( isMultisample ) {
24974
24975                                 const samples = getRenderTargetSamples( renderTarget );
24976
24977                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
24978
24979                         } else {
24980
24981                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
24982
24983                         }
24984
24985                 }
24986
24987                 _gl.bindRenderbuffer( 36161, null );
24988
24989         }
24990
24991         // Setup resources for a Depth Texture for a FBO (needs an extension)
24992         function setupDepthTexture( framebuffer, renderTarget ) {
24993
24994                 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
24995                 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
24996
24997                 _gl.bindFramebuffer( 36160, framebuffer );
24998
24999                 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
25000
25001                         throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
25002
25003                 }
25004
25005                 // upload an empty depth texture with framebuffer size
25006                 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
25007                                 renderTarget.depthTexture.image.width !== renderTarget.width ||
25008                                 renderTarget.depthTexture.image.height !== renderTarget.height ) {
25009
25010                         renderTarget.depthTexture.image.width = renderTarget.width;
25011                         renderTarget.depthTexture.image.height = renderTarget.height;
25012                         renderTarget.depthTexture.needsUpdate = true;
25013
25014                 }
25015
25016                 setTexture2D( renderTarget.depthTexture, 0 );
25017
25018                 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
25019
25020                 if ( renderTarget.depthTexture.format === DepthFormat ) {
25021
25022                         _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
25023
25024                 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
25025
25026                         _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
25027
25028                 } else {
25029
25030                         throw new Error( 'Unknown depthTexture format' );
25031
25032                 }
25033
25034         }
25035
25036         // Setup GL resources for a non-texture depth buffer
25037         function setupDepthRenderbuffer( renderTarget ) {
25038
25039                 const renderTargetProperties = properties.get( renderTarget );
25040
25041                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25042
25043                 if ( renderTarget.depthTexture ) {
25044
25045                         if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
25046
25047                         setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
25048
25049                 } else {
25050
25051                         if ( isCube ) {
25052
25053                                 renderTargetProperties.__webglDepthbuffer = [];
25054
25055                                 for ( let i = 0; i < 6; i ++ ) {
25056
25057                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
25058                                         renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
25059                                         setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
25060
25061                                 }
25062
25063                         } else {
25064
25065                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
25066                                 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25067                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
25068
25069                         }
25070
25071                 }
25072
25073                 _gl.bindFramebuffer( 36160, null );
25074
25075         }
25076
25077         // Set up GL resources for the render target
25078         function setupRenderTarget( renderTarget ) {
25079
25080                 const renderTargetProperties = properties.get( renderTarget );
25081                 const textureProperties = properties.get( renderTarget.texture );
25082
25083                 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
25084
25085                 textureProperties.__webglTexture = _gl.createTexture();
25086
25087                 info.memory.textures ++;
25088
25089                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25090                 const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
25091                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
25092
25093                 // Handles WebGL2 RGBFormat fallback - #18858
25094
25095                 if ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {
25096
25097                         renderTarget.texture.format = RGBAFormat;
25098
25099                         console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
25100
25101                 }
25102
25103                 // Setup framebuffer
25104
25105                 if ( isCube ) {
25106
25107                         renderTargetProperties.__webglFramebuffer = [];
25108
25109                         for ( let i = 0; i < 6; i ++ ) {
25110
25111                                 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
25112
25113                         }
25114
25115                 } else {
25116
25117                         renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25118
25119                         if ( isMultisample ) {
25120
25121                                 if ( isWebGL2 ) {
25122
25123                                         renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
25124                                         renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
25125
25126                                         _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
25127
25128                                         const glFormat = utils.convert( renderTarget.texture.format );
25129                                         const glType = utils.convert( renderTarget.texture.type );
25130                                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
25131                                         const samples = getRenderTargetSamples( renderTarget );
25132                                         _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25133
25134                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
25135                                         _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
25136                                         _gl.bindRenderbuffer( 36161, null );
25137
25138                                         if ( renderTarget.depthBuffer ) {
25139
25140                                                 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25141                                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
25142
25143                                         }
25144
25145                                         _gl.bindFramebuffer( 36160, null );
25146
25147
25148                                 } else {
25149
25150                                         console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
25151
25152                                 }
25153
25154                         }
25155
25156                 }
25157
25158                 // Setup color buffer
25159
25160                 if ( isCube ) {
25161
25162                         state.bindTexture( 34067, textureProperties.__webglTexture );
25163                         setTextureParameters( 34067, renderTarget.texture, supportsMips );
25164
25165                         for ( let i = 0; i < 6; i ++ ) {
25166
25167                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
25168
25169                         }
25170
25171                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
25172
25173                                 generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
25174
25175                         }
25176
25177                         state.bindTexture( 34067, null );
25178
25179                 } else {
25180
25181                         state.bindTexture( 3553, textureProperties.__webglTexture );
25182                         setTextureParameters( 3553, renderTarget.texture, supportsMips );
25183                         setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
25184
25185                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
25186
25187                                 generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
25188
25189                         }
25190
25191                         state.bindTexture( 3553, null );
25192
25193                 }
25194
25195                 // Setup depth and stencil buffers
25196
25197                 if ( renderTarget.depthBuffer ) {
25198
25199                         setupDepthRenderbuffer( renderTarget );
25200
25201                 }
25202
25203         }
25204
25205         function updateRenderTargetMipmap( renderTarget ) {
25206
25207                 const texture = renderTarget.texture;
25208                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
25209
25210                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25211
25212                         const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
25213                         const webglTexture = properties.get( texture ).__webglTexture;
25214
25215                         state.bindTexture( target, webglTexture );
25216                         generateMipmap( target, texture, renderTarget.width, renderTarget.height );
25217                         state.bindTexture( target, null );
25218
25219                 }
25220
25221         }
25222
25223         function updateMultisampleRenderTarget( renderTarget ) {
25224
25225                 if ( renderTarget.isWebGLMultisampleRenderTarget ) {
25226
25227                         if ( isWebGL2 ) {
25228
25229                                 const renderTargetProperties = properties.get( renderTarget );
25230
25231                                 _gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
25232                                 _gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
25233
25234                                 const width = renderTarget.width;
25235                                 const height = renderTarget.height;
25236                                 let mask = 16384;
25237
25238                                 if ( renderTarget.depthBuffer ) mask |= 256;
25239                                 if ( renderTarget.stencilBuffer ) mask |= 1024;
25240
25241                                 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
25242
25243                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905
25244
25245                         } else {
25246
25247                                 console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
25248
25249                         }
25250
25251                 }
25252
25253         }
25254
25255         function getRenderTargetSamples( renderTarget ) {
25256
25257                 return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
25258                         Math.min( maxSamples, renderTarget.samples ) : 0;
25259
25260         }
25261
25262         function updateVideoTexture( texture ) {
25263
25264                 const frame = info.render.frame;
25265
25266                 // Check the last frame we updated the VideoTexture
25267
25268                 if ( _videoTextures.get( texture ) !== frame ) {
25269
25270                         _videoTextures.set( texture, frame );
25271                         texture.update();
25272
25273                 }
25274
25275         }
25276
25277         // backwards compatibility
25278
25279         let warnedTexture2D = false;
25280         let warnedTextureCube = false;
25281
25282         function safeSetTexture2D( texture, slot ) {
25283
25284                 if ( texture && texture.isWebGLRenderTarget ) {
25285
25286                         if ( warnedTexture2D === false ) {
25287
25288                                 console.warn( 'THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.' );
25289                                 warnedTexture2D = true;
25290
25291                         }
25292
25293                         texture = texture.texture;
25294
25295                 }
25296
25297                 setTexture2D( texture, slot );
25298
25299         }
25300
25301         function safeSetTextureCube( texture, slot ) {
25302
25303                 if ( texture && texture.isWebGLCubeRenderTarget ) {
25304
25305                         if ( warnedTextureCube === false ) {
25306
25307                                 console.warn( 'THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.' );
25308                                 warnedTextureCube = true;
25309
25310                         }
25311
25312                         texture = texture.texture;
25313
25314                 }
25315
25316
25317                 setTextureCube( texture, slot );
25318
25319         }
25320
25321         //
25322
25323         this.allocateTextureUnit = allocateTextureUnit;
25324         this.resetTextureUnits = resetTextureUnits;
25325
25326         this.setTexture2D = setTexture2D;
25327         this.setTexture2DArray = setTexture2DArray;
25328         this.setTexture3D = setTexture3D;
25329         this.setTextureCube = setTextureCube;
25330         this.setupRenderTarget = setupRenderTarget;
25331         this.updateRenderTargetMipmap = updateRenderTargetMipmap;
25332         this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
25333
25334         this.safeSetTexture2D = safeSetTexture2D;
25335         this.safeSetTextureCube = safeSetTextureCube;
25336
25337     }
25338
25339     function WebGLUtils( gl, extensions, capabilities ) {
25340
25341         const isWebGL2 = capabilities.isWebGL2;
25342
25343         function convert( p ) {
25344
25345                 let extension;
25346
25347                 if ( p === UnsignedByteType ) return 5121;
25348                 if ( p === UnsignedShort4444Type ) return 32819;
25349                 if ( p === UnsignedShort5551Type ) return 32820;
25350                 if ( p === UnsignedShort565Type ) return 33635;
25351
25352                 if ( p === ByteType ) return 5120;
25353                 if ( p === ShortType ) return 5122;
25354                 if ( p === UnsignedShortType ) return 5123;
25355                 if ( p === IntType ) return 5124;
25356                 if ( p === UnsignedIntType ) return 5125;
25357                 if ( p === FloatType ) return 5126;
25358
25359                 if ( p === HalfFloatType ) {
25360
25361                         if ( isWebGL2 ) return 5131;
25362
25363                         extension = extensions.get( 'OES_texture_half_float' );
25364
25365                         if ( extension !== null ) {
25366
25367                                 return extension.HALF_FLOAT_OES;
25368
25369                         } else {
25370
25371                                 return null;
25372
25373                         }
25374
25375                 }
25376
25377                 if ( p === AlphaFormat ) return 6406;
25378                 if ( p === RGBFormat ) return 6407;
25379                 if ( p === RGBAFormat ) return 6408;
25380                 if ( p === LuminanceFormat ) return 6409;
25381                 if ( p === LuminanceAlphaFormat ) return 6410;
25382                 if ( p === DepthFormat ) return 6402;
25383                 if ( p === DepthStencilFormat ) return 34041;
25384                 if ( p === RedFormat ) return 6403;
25385
25386                 // WebGL2 formats.
25387
25388                 if ( p === RedIntegerFormat ) return 36244;
25389                 if ( p === RGFormat ) return 33319;
25390                 if ( p === RGIntegerFormat ) return 33320;
25391                 if ( p === RGBIntegerFormat ) return 36248;
25392                 if ( p === RGBAIntegerFormat ) return 36249;
25393
25394                 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
25395                         p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
25396
25397                         extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
25398
25399                         if ( extension !== null ) {
25400
25401                                 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
25402                                 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
25403                                 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
25404                                 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
25405
25406                         } else {
25407
25408                                 return null;
25409
25410                         }
25411
25412                 }
25413
25414                 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
25415                         p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
25416
25417                         extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
25418
25419                         if ( extension !== null ) {
25420
25421                                 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
25422                                 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
25423                                 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
25424                                 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
25425
25426                         } else {
25427
25428                                 return null;
25429
25430                         }
25431
25432                 }
25433
25434                 if ( p === RGB_ETC1_Format ) {
25435
25436                         extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
25437
25438                         if ( extension !== null ) {
25439
25440                                 return extension.COMPRESSED_RGB_ETC1_WEBGL;
25441
25442                         } else {
25443
25444                                 return null;
25445
25446                         }
25447
25448                 }
25449
25450                 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
25451
25452                         extension = extensions.get( 'WEBGL_compressed_texture_etc' );
25453
25454                         if ( extension !== null ) {
25455
25456                                 if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
25457                                 if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
25458
25459                         }
25460
25461                 }
25462
25463                 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
25464                         p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
25465                         p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
25466                         p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
25467                         p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
25468                         p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
25469                         p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
25470                         p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
25471                         p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
25472                         p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
25473
25474                         extension = extensions.get( 'WEBGL_compressed_texture_astc' );
25475
25476                         if ( extension !== null ) {
25477
25478                                 // TODO Complete?
25479
25480                                 return p;
25481
25482                         } else {
25483
25484                                 return null;
25485
25486                         }
25487
25488                 }
25489
25490                 if ( p === RGBA_BPTC_Format ) {
25491
25492                         extension = extensions.get( 'EXT_texture_compression_bptc' );
25493
25494                         if ( extension !== null ) {
25495
25496                                 // TODO Complete?
25497
25498                                 return p;
25499
25500                         } else {
25501
25502                                 return null;
25503
25504                         }
25505
25506                 }
25507
25508                 if ( p === UnsignedInt248Type ) {
25509
25510                         if ( isWebGL2 ) return 34042;
25511
25512                         extension = extensions.get( 'WEBGL_depth_texture' );
25513
25514                         if ( extension !== null ) {
25515
25516                                 return extension.UNSIGNED_INT_24_8_WEBGL;
25517
25518                         } else {
25519
25520                                 return null;
25521
25522                         }
25523
25524                 }
25525
25526         }
25527
25528         return { convert: convert };
25529
25530     }
25531
25532     function ArrayCamera( array = [] ) {
25533
25534         PerspectiveCamera.call( this );
25535
25536         this.cameras = array;
25537
25538     }
25539
25540     ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
25541
25542         constructor: ArrayCamera,
25543
25544         isArrayCamera: true
25545
25546     } );
25547
25548     function Group() {
25549
25550         Object3D.call( this );
25551
25552         this.type = 'Group';
25553
25554     }
25555
25556     Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
25557
25558         constructor: Group,
25559
25560         isGroup: true
25561
25562     } );
25563
25564     function WebXRController() {
25565
25566         this._targetRay = null;
25567         this._grip = null;
25568         this._hand = null;
25569
25570     }
25571
25572     Object.assign( WebXRController.prototype, {
25573
25574         constructor: WebXRController,
25575
25576         getHandSpace: function () {
25577
25578                 if ( this._hand === null ) {
25579
25580                         this._hand = new Group();
25581                         this._hand.matrixAutoUpdate = false;
25582                         this._hand.visible = false;
25583
25584                         this._hand.joints = {};
25585                         this._hand.inputState = { pinching: false };
25586
25587                 }
25588
25589                 return this._hand;
25590
25591         },
25592
25593         getTargetRaySpace: function () {
25594
25595                 if ( this._targetRay === null ) {
25596
25597                         this._targetRay = new Group();
25598                         this._targetRay.matrixAutoUpdate = false;
25599                         this._targetRay.visible = false;
25600
25601                 }
25602
25603                 return this._targetRay;
25604
25605         },
25606
25607         getGripSpace: function () {
25608
25609                 if ( this._grip === null ) {
25610
25611                         this._grip = new Group();
25612                         this._grip.matrixAutoUpdate = false;
25613                         this._grip.visible = false;
25614
25615                 }
25616
25617                 return this._grip;
25618
25619         },
25620
25621         dispatchEvent: function ( event ) {
25622
25623                 if ( this._targetRay !== null ) {
25624
25625                         this._targetRay.dispatchEvent( event );
25626
25627                 }
25628
25629                 if ( this._grip !== null ) {
25630
25631                         this._grip.dispatchEvent( event );
25632
25633                 }
25634
25635                 if ( this._hand !== null ) {
25636
25637                         this._hand.dispatchEvent( event );
25638
25639                 }
25640
25641                 return this;
25642
25643         },
25644
25645         disconnect: function ( inputSource ) {
25646
25647                 this.dispatchEvent( { type: 'disconnected', data: inputSource } );
25648
25649                 if ( this._targetRay !== null ) {
25650
25651                         this._targetRay.visible = false;
25652
25653                 }
25654
25655                 if ( this._grip !== null ) {
25656
25657                         this._grip.visible = false;
25658
25659                 }
25660
25661                 if ( this._hand !== null ) {
25662
25663                         this._hand.visible = false;
25664
25665                 }
25666
25667                 return this;
25668
25669         },
25670
25671         update: function ( inputSource, frame, referenceSpace ) {
25672
25673                 let inputPose = null;
25674                 let gripPose = null;
25675                 let handPose = null;
25676
25677                 const targetRay = this._targetRay;
25678                 const grip = this._grip;
25679                 const hand = this._hand;
25680
25681                 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
25682
25683                         if ( hand && inputSource.hand ) {
25684
25685                                 handPose = true;
25686
25687                                 for ( const inputjoint of inputSource.hand.values() ) {
25688
25689                                         // Update the joints groups with the XRJoint poses
25690                                         const jointPose = frame.getJointPose( inputjoint, referenceSpace );
25691
25692                                         if ( hand.joints[ inputjoint.jointName ] === undefined ) {
25693
25694                                                 // The transform of this joint will be updated with the joint pose on each frame
25695                                                 const joint = new Group();
25696                                                 joint.matrixAutoUpdate = false;
25697                                                 joint.visible = false;
25698                                                 hand.joints[ inputjoint.jointName ] = joint;
25699                                                 // ??
25700                                                 hand.add( joint );
25701
25702                                         }
25703
25704                                         const joint = hand.joints[ inputjoint.jointName ];
25705
25706                                         if ( jointPose !== null ) {
25707
25708                                                 joint.matrix.fromArray( jointPose.transform.matrix );
25709                                                 joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
25710                                                 joint.jointRadius = jointPose.radius;
25711
25712                                         }
25713
25714                                         joint.visible = jointPose !== null;
25715
25716                                 }
25717
25718                                 // Custom events
25719
25720                                 // Check pinchz
25721                                 const indexTip = hand.joints[ 'index-finger-tip' ];
25722                                 const thumbTip = hand.joints[ 'thumb-tip' ];
25723                                 const distance = indexTip.position.distanceTo( thumbTip.position );
25724
25725                                 const distanceToPinch = 0.02;
25726                                 const threshold = 0.005;
25727
25728                                 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
25729
25730                                         hand.inputState.pinching = false;
25731                                         this.dispatchEvent( {
25732                                                 type: 'pinchend',
25733                                                 handedness: inputSource.handedness,
25734                                                 target: this
25735                                         } );
25736
25737                                 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
25738
25739                                         hand.inputState.pinching = true;
25740                                         this.dispatchEvent( {
25741                                                 type: 'pinchstart',
25742                                                 handedness: inputSource.handedness,
25743                                                 target: this
25744                                         } );
25745
25746                                 }
25747
25748                         } else {
25749
25750                                 if ( targetRay !== null ) {
25751
25752                                         inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
25753
25754                                         if ( inputPose !== null ) {
25755
25756                                                 targetRay.matrix.fromArray( inputPose.transform.matrix );
25757                                                 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
25758
25759                                         }
25760
25761                                 }
25762
25763                                 if ( grip !== null && inputSource.gripSpace ) {
25764
25765                                         gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
25766
25767                                         if ( gripPose !== null ) {
25768
25769                                                 grip.matrix.fromArray( gripPose.transform.matrix );
25770                                                 grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
25771
25772                                         }
25773
25774                                 }
25775
25776                         }
25777
25778                 }
25779
25780                 if ( targetRay !== null ) {
25781
25782                         targetRay.visible = ( inputPose !== null );
25783
25784                 }
25785
25786                 if ( grip !== null ) {
25787
25788                         grip.visible = ( gripPose !== null );
25789
25790                 }
25791
25792                 if ( hand !== null ) {
25793
25794                         hand.visible = ( handPose !== null );
25795
25796                 }
25797
25798                 return this;
25799
25800         }
25801
25802     } );
25803
25804     function WebXRManager( renderer, gl ) {
25805
25806         const scope = this;
25807
25808         let session = null;
25809
25810         let framebufferScaleFactor = 1.0;
25811
25812         let referenceSpace = null;
25813         let referenceSpaceType = 'local-floor';
25814
25815         let pose = null;
25816
25817         const controllers = [];
25818         const inputSourcesMap = new Map();
25819
25820         //
25821
25822         const cameraL = new PerspectiveCamera();
25823         cameraL.layers.enable( 1 );
25824         cameraL.viewport = new Vector4();
25825
25826         const cameraR = new PerspectiveCamera();
25827         cameraR.layers.enable( 2 );
25828         cameraR.viewport = new Vector4();
25829
25830         const cameras = [ cameraL, cameraR ];
25831
25832         const cameraVR = new ArrayCamera();
25833         cameraVR.layers.enable( 1 );
25834         cameraVR.layers.enable( 2 );
25835
25836         let _currentDepthNear = null;
25837         let _currentDepthFar = null;
25838
25839         //
25840
25841         this.enabled = false;
25842
25843         this.isPresenting = false;
25844
25845         this.getController = function ( index ) {
25846
25847                 let controller = controllers[ index ];
25848
25849                 if ( controller === undefined ) {
25850
25851                         controller = new WebXRController();
25852                         controllers[ index ] = controller;
25853
25854                 }
25855
25856                 return controller.getTargetRaySpace();
25857
25858         };
25859
25860         this.getControllerGrip = function ( index ) {
25861
25862                 let controller = controllers[ index ];
25863
25864                 if ( controller === undefined ) {
25865
25866                         controller = new WebXRController();
25867                         controllers[ index ] = controller;
25868
25869                 }
25870
25871                 return controller.getGripSpace();
25872
25873         };
25874
25875         this.getHand = function ( index ) {
25876
25877                 let controller = controllers[ index ];
25878
25879                 if ( controller === undefined ) {
25880
25881                         controller = new WebXRController();
25882                         controllers[ index ] = controller;
25883
25884                 }
25885
25886                 return controller.getHandSpace();
25887
25888         };
25889
25890         //
25891
25892         function onSessionEvent( event ) {
25893
25894                 const controller = inputSourcesMap.get( event.inputSource );
25895
25896                 if ( controller ) {
25897
25898                         controller.dispatchEvent( { type: event.type, data: event.inputSource } );
25899
25900                 }
25901
25902         }
25903
25904         function onSessionEnd() {
25905
25906                 inputSourcesMap.forEach( function ( controller, inputSource ) {
25907
25908                         controller.disconnect( inputSource );
25909
25910                 } );
25911
25912                 inputSourcesMap.clear();
25913
25914                 _currentDepthNear = null;
25915                 _currentDepthFar = null;
25916
25917                 //
25918
25919                 renderer.setFramebuffer( null );
25920                 renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
25921                 animation.stop();
25922
25923                 scope.isPresenting = false;
25924
25925                 scope.dispatchEvent( { type: 'sessionend' } );
25926
25927         }
25928
25929         this.setFramebufferScaleFactor = function ( value ) {
25930
25931                 framebufferScaleFactor = value;
25932
25933                 if ( scope.isPresenting === true ) {
25934
25935                         console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
25936
25937                 }
25938
25939         };
25940
25941         this.setReferenceSpaceType = function ( value ) {
25942
25943                 referenceSpaceType = value;
25944
25945                 if ( scope.isPresenting === true ) {
25946
25947                         console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
25948
25949                 }
25950
25951         };
25952
25953         this.getReferenceSpace = function () {
25954
25955                 return referenceSpace;
25956
25957         };
25958
25959         this.getSession = function () {
25960
25961                 return session;
25962
25963         };
25964
25965         this.setSession = async function ( value ) {
25966
25967                 session = value;
25968
25969                 if ( session !== null ) {
25970
25971                         session.addEventListener( 'select', onSessionEvent );
25972                         session.addEventListener( 'selectstart', onSessionEvent );
25973                         session.addEventListener( 'selectend', onSessionEvent );
25974                         session.addEventListener( 'squeeze', onSessionEvent );
25975                         session.addEventListener( 'squeezestart', onSessionEvent );
25976                         session.addEventListener( 'squeezeend', onSessionEvent );
25977                         session.addEventListener( 'end', onSessionEnd );
25978                         session.addEventListener( 'inputsourceschange', onInputSourcesChange );
25979
25980                         const attributes = gl.getContextAttributes();
25981
25982                         if ( attributes.xrCompatible !== true ) {
25983
25984                                 await gl.makeXRCompatible();
25985
25986                         }
25987
25988                         const layerInit = {
25989                                 antialias: attributes.antialias,
25990                                 alpha: attributes.alpha,
25991                                 depth: attributes.depth,
25992                                 stencil: attributes.stencil,
25993                                 framebufferScaleFactor: framebufferScaleFactor
25994                         };
25995
25996                         // eslint-disable-next-line no-undef
25997                         const baseLayer = new XRWebGLLayer( session, gl, layerInit );
25998
25999                         session.updateRenderState( { baseLayer: baseLayer } );
26000
26001                         referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
26002
26003                         animation.setContext( session );
26004                         animation.start();
26005
26006                         scope.isPresenting = true;
26007
26008                         scope.dispatchEvent( { type: 'sessionstart' } );
26009
26010                 }
26011
26012         };
26013
26014         function onInputSourcesChange( event ) {
26015
26016                 const inputSources = session.inputSources;
26017
26018                 // Assign inputSources to available controllers
26019
26020                 for ( let i = 0; i < controllers.length; i ++ ) {
26021
26022                         inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
26023
26024                 }
26025
26026                 // Notify disconnected
26027
26028                 for ( let i = 0; i < event.removed.length; i ++ ) {
26029
26030                         const inputSource = event.removed[ i ];
26031                         const controller = inputSourcesMap.get( inputSource );
26032
26033                         if ( controller ) {
26034
26035                                 controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
26036                                 inputSourcesMap.delete( inputSource );
26037
26038                         }
26039
26040                 }
26041
26042                 // Notify connected
26043
26044                 for ( let i = 0; i < event.added.length; i ++ ) {
26045
26046                         const inputSource = event.added[ i ];
26047                         const controller = inputSourcesMap.get( inputSource );
26048
26049                         if ( controller ) {
26050
26051                                 controller.dispatchEvent( { type: 'connected', data: inputSource } );
26052
26053                         }
26054
26055                 }
26056
26057         }
26058
26059         //
26060
26061         const cameraLPos = new Vector3();
26062         const cameraRPos = new Vector3();
26063
26064         /**
26065          * Assumes 2 cameras that are parallel and share an X-axis, and that
26066          * the cameras' projection and world matrices have already been set.
26067          * And that near and far planes are identical for both cameras.
26068          * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
26069          */
26070         function setProjectionFromUnion( camera, cameraL, cameraR ) {
26071
26072                 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
26073                 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
26074
26075                 const ipd = cameraLPos.distanceTo( cameraRPos );
26076
26077                 const projL = cameraL.projectionMatrix.elements;
26078                 const projR = cameraR.projectionMatrix.elements;
26079
26080                 // VR systems will have identical far and near planes, and
26081                 // most likely identical top and bottom frustum extents.
26082                 // Use the left camera for these values.
26083                 const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
26084                 const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
26085                 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
26086                 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
26087
26088                 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
26089                 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
26090                 const left = near * leftFov;
26091                 const right = near * rightFov;
26092
26093                 // Calculate the new camera's position offset from the
26094                 // left camera. xOffset should be roughly half `ipd`.
26095                 const zOffset = ipd / ( - leftFov + rightFov );
26096                 const xOffset = zOffset * - leftFov;
26097
26098                 // TODO: Better way to apply this offset?
26099                 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
26100                 camera.translateX( xOffset );
26101                 camera.translateZ( zOffset );
26102                 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
26103                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26104
26105                 // Find the union of the frustum values of the cameras and scale
26106                 // the values so that the near plane's position does not change in world space,
26107                 // although must now be relative to the new union camera.
26108                 const near2 = near + zOffset;
26109                 const far2 = far + zOffset;
26110                 const left2 = left - xOffset;
26111                 const right2 = right + ( ipd - xOffset );
26112                 const top2 = topFov * far / far2 * near2;
26113                 const bottom2 = bottomFov * far / far2 * near2;
26114
26115                 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
26116
26117         }
26118
26119         function updateCamera( camera, parent ) {
26120
26121                 if ( parent === null ) {
26122
26123                         camera.matrixWorld.copy( camera.matrix );
26124
26125                 } else {
26126
26127                         camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
26128
26129                 }
26130
26131                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26132
26133         }
26134
26135         this.getCamera = function ( camera ) {
26136
26137                 cameraVR.near = cameraR.near = cameraL.near = camera.near;
26138                 cameraVR.far = cameraR.far = cameraL.far = camera.far;
26139
26140                 if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
26141
26142                         // Note that the new renderState won't apply until the next frame. See #18320
26143
26144                         session.updateRenderState( {
26145                                 depthNear: cameraVR.near,
26146                                 depthFar: cameraVR.far
26147                         } );
26148
26149                         _currentDepthNear = cameraVR.near;
26150                         _currentDepthFar = cameraVR.far;
26151
26152                 }
26153
26154                 const parent = camera.parent;
26155                 const cameras = cameraVR.cameras;
26156
26157                 updateCamera( cameraVR, parent );
26158
26159                 for ( let i = 0; i < cameras.length; i ++ ) {
26160
26161                         updateCamera( cameras[ i ], parent );
26162
26163                 }
26164
26165                 // update camera and its children
26166
26167                 camera.matrixWorld.copy( cameraVR.matrixWorld );
26168                 camera.matrix.copy( cameraVR.matrix );
26169                 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
26170
26171                 const children = camera.children;
26172
26173                 for ( let i = 0, l = children.length; i < l; i ++ ) {
26174
26175                         children[ i ].updateMatrixWorld( true );
26176
26177                 }
26178
26179                 // update projection matrix for proper view frustum culling
26180
26181                 if ( cameras.length === 2 ) {
26182
26183                         setProjectionFromUnion( cameraVR, cameraL, cameraR );
26184
26185                 } else {
26186
26187                         // assume single camera setup (AR)
26188
26189                         cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
26190
26191                 }
26192
26193                 return cameraVR;
26194
26195         };
26196
26197         // Animation Loop
26198
26199         let onAnimationFrameCallback = null;
26200
26201         function onAnimationFrame( time, frame ) {
26202
26203                 pose = frame.getViewerPose( referenceSpace );
26204
26205                 if ( pose !== null ) {
26206
26207                         const views = pose.views;
26208                         const baseLayer = session.renderState.baseLayer;
26209
26210                         renderer.setFramebuffer( baseLayer.framebuffer );
26211
26212                         let cameraVRNeedsUpdate = false;
26213
26214                         // check if it's necessary to rebuild cameraVR's camera list
26215
26216                         if ( views.length !== cameraVR.cameras.length ) {
26217
26218                                 cameraVR.cameras.length = 0;
26219                                 cameraVRNeedsUpdate = true;
26220
26221                         }
26222
26223                         for ( let i = 0; i < views.length; i ++ ) {
26224
26225                                 const view = views[ i ];
26226                                 const viewport = baseLayer.getViewport( view );
26227
26228                                 const camera = cameras[ i ];
26229                                 camera.matrix.fromArray( view.transform.matrix );
26230                                 camera.projectionMatrix.fromArray( view.projectionMatrix );
26231                                 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
26232
26233                                 if ( i === 0 ) {
26234
26235                                         cameraVR.matrix.copy( camera.matrix );
26236
26237                                 }
26238
26239                                 if ( cameraVRNeedsUpdate === true ) {
26240
26241                                         cameraVR.cameras.push( camera );
26242
26243                                 }
26244
26245                         }
26246
26247                 }
26248
26249                 //
26250
26251                 const inputSources = session.inputSources;
26252
26253                 for ( let i = 0; i < controllers.length; i ++ ) {
26254
26255                         const controller = controllers[ i ];
26256                         const inputSource = inputSources[ i ];
26257
26258                         controller.update( inputSource, frame, referenceSpace );
26259
26260                 }
26261
26262                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
26263
26264         }
26265
26266         const animation = new WebGLAnimation();
26267         animation.setAnimationLoop( onAnimationFrame );
26268
26269         this.setAnimationLoop = function ( callback ) {
26270
26271                 onAnimationFrameCallback = callback;
26272
26273         };
26274
26275         this.dispose = function () {};
26276
26277     }
26278
26279     Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
26280
26281     function WebGLMaterials( properties ) {
26282
26283         function refreshFogUniforms( uniforms, fog ) {
26284
26285                 uniforms.fogColor.value.copy( fog.color );
26286
26287                 if ( fog.isFog ) {
26288
26289                         uniforms.fogNear.value = fog.near;
26290                         uniforms.fogFar.value = fog.far;
26291
26292                 } else if ( fog.isFogExp2 ) {
26293
26294                         uniforms.fogDensity.value = fog.density;
26295
26296                 }
26297
26298         }
26299
26300         function refreshMaterialUniforms( uniforms, material, pixelRatio, height ) {
26301
26302                 if ( material.isMeshBasicMaterial ) {
26303
26304                         refreshUniformsCommon( uniforms, material );
26305
26306                 } else if ( material.isMeshLambertMaterial ) {
26307
26308                         refreshUniformsCommon( uniforms, material );
26309                         refreshUniformsLambert( uniforms, material );
26310
26311                 } else if ( material.isMeshToonMaterial ) {
26312
26313                         refreshUniformsCommon( uniforms, material );
26314                         refreshUniformsToon( uniforms, material );
26315
26316                 } else if ( material.isMeshPhongMaterial ) {
26317
26318                         refreshUniformsCommon( uniforms, material );
26319                         refreshUniformsPhong( uniforms, material );
26320
26321                 } else if ( material.isMeshStandardMaterial ) {
26322
26323                         refreshUniformsCommon( uniforms, material );
26324
26325                         if ( material.isMeshPhysicalMaterial ) {
26326
26327                                 refreshUniformsPhysical( uniforms, material );
26328
26329                         } else {
26330
26331                                 refreshUniformsStandard( uniforms, material );
26332
26333                         }
26334
26335                 } else if ( material.isMeshMatcapMaterial ) {
26336
26337                         refreshUniformsCommon( uniforms, material );
26338                         refreshUniformsMatcap( uniforms, material );
26339
26340                 } else if ( material.isMeshDepthMaterial ) {
26341
26342                         refreshUniformsCommon( uniforms, material );
26343                         refreshUniformsDepth( uniforms, material );
26344
26345                 } else if ( material.isMeshDistanceMaterial ) {
26346
26347                         refreshUniformsCommon( uniforms, material );
26348                         refreshUniformsDistance( uniforms, material );
26349
26350                 } else if ( material.isMeshNormalMaterial ) {
26351
26352                         refreshUniformsCommon( uniforms, material );
26353                         refreshUniformsNormal( uniforms, material );
26354
26355                 } else if ( material.isLineBasicMaterial ) {
26356
26357                         refreshUniformsLine( uniforms, material );
26358
26359                         if ( material.isLineDashedMaterial ) {
26360
26361                                 refreshUniformsDash( uniforms, material );
26362
26363                         }
26364
26365                 } else if ( material.isPointsMaterial ) {
26366
26367                         refreshUniformsPoints( uniforms, material, pixelRatio, height );
26368
26369                 } else if ( material.isSpriteMaterial ) {
26370
26371                         refreshUniformsSprites( uniforms, material );
26372
26373                 } else if ( material.isShadowMaterial ) {
26374
26375                         uniforms.color.value.copy( material.color );
26376                         uniforms.opacity.value = material.opacity;
26377
26378                 } else if ( material.isShaderMaterial ) {
26379
26380                         material.uniformsNeedUpdate = false; // #15581
26381
26382                 }
26383
26384         }
26385
26386         function refreshUniformsCommon( uniforms, material ) {
26387
26388                 uniforms.opacity.value = material.opacity;
26389
26390                 if ( material.color ) {
26391
26392                         uniforms.diffuse.value.copy( material.color );
26393
26394                 }
26395
26396                 if ( material.emissive ) {
26397
26398                         uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
26399
26400                 }
26401
26402                 if ( material.map ) {
26403
26404                         uniforms.map.value = material.map;
26405
26406                 }
26407
26408                 if ( material.alphaMap ) {
26409
26410                         uniforms.alphaMap.value = material.alphaMap;
26411
26412                 }
26413
26414                 if ( material.specularMap ) {
26415
26416                         uniforms.specularMap.value = material.specularMap;
26417
26418                 }
26419
26420                 const envMap = properties.get( material ).envMap;
26421
26422                 if ( envMap ) {
26423
26424                         uniforms.envMap.value = envMap;
26425
26426                         uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap._needsFlipEnvMap ) ? - 1 : 1;
26427
26428                         uniforms.reflectivity.value = material.reflectivity;
26429                         uniforms.refractionRatio.value = material.refractionRatio;
26430
26431                         const maxMipLevel = properties.get( envMap ).__maxMipLevel;
26432
26433                         if ( maxMipLevel !== undefined ) {
26434
26435                                 uniforms.maxMipLevel.value = maxMipLevel;
26436
26437                         }
26438
26439                 }
26440
26441                 if ( material.lightMap ) {
26442
26443                         uniforms.lightMap.value = material.lightMap;
26444                         uniforms.lightMapIntensity.value = material.lightMapIntensity;
26445
26446                 }
26447
26448                 if ( material.aoMap ) {
26449
26450                         uniforms.aoMap.value = material.aoMap;
26451                         uniforms.aoMapIntensity.value = material.aoMapIntensity;
26452
26453                 }
26454
26455                 // uv repeat and offset setting priorities
26456                 // 1. color map
26457                 // 2. specular map
26458                 // 3. displacementMap map
26459                 // 4. normal map
26460                 // 5. bump map
26461                 // 6. roughnessMap map
26462                 // 7. metalnessMap map
26463                 // 8. alphaMap map
26464                 // 9. emissiveMap map
26465                 // 10. clearcoat map
26466                 // 11. clearcoat normal map
26467                 // 12. clearcoat roughnessMap map
26468
26469                 let uvScaleMap;
26470
26471                 if ( material.map ) {
26472
26473                         uvScaleMap = material.map;
26474
26475                 } else if ( material.specularMap ) {
26476
26477                         uvScaleMap = material.specularMap;
26478
26479                 } else if ( material.displacementMap ) {
26480
26481                         uvScaleMap = material.displacementMap;
26482
26483                 } else if ( material.normalMap ) {
26484
26485                         uvScaleMap = material.normalMap;
26486
26487                 } else if ( material.bumpMap ) {
26488
26489                         uvScaleMap = material.bumpMap;
26490
26491                 } else if ( material.roughnessMap ) {
26492
26493                         uvScaleMap = material.roughnessMap;
26494
26495                 } else if ( material.metalnessMap ) {
26496
26497                         uvScaleMap = material.metalnessMap;
26498
26499                 } else if ( material.alphaMap ) {
26500
26501                         uvScaleMap = material.alphaMap;
26502
26503                 } else if ( material.emissiveMap ) {
26504
26505                         uvScaleMap = material.emissiveMap;
26506
26507                 } else if ( material.clearcoatMap ) {
26508
26509                         uvScaleMap = material.clearcoatMap;
26510
26511                 } else if ( material.clearcoatNormalMap ) {
26512
26513                         uvScaleMap = material.clearcoatNormalMap;
26514
26515                 } else if ( material.clearcoatRoughnessMap ) {
26516
26517                         uvScaleMap = material.clearcoatRoughnessMap;
26518
26519                 }
26520
26521                 if ( uvScaleMap !== undefined ) {
26522
26523                         // backwards compatibility
26524                         if ( uvScaleMap.isWebGLRenderTarget ) {
26525
26526                                 uvScaleMap = uvScaleMap.texture;
26527
26528                         }
26529
26530                         if ( uvScaleMap.matrixAutoUpdate === true ) {
26531
26532                                 uvScaleMap.updateMatrix();
26533
26534                         }
26535
26536                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26537
26538                 }
26539
26540                 // uv repeat and offset setting priorities for uv2
26541                 // 1. ao map
26542                 // 2. light map
26543
26544                 let uv2ScaleMap;
26545
26546                 if ( material.aoMap ) {
26547
26548                         uv2ScaleMap = material.aoMap;
26549
26550                 } else if ( material.lightMap ) {
26551
26552                         uv2ScaleMap = material.lightMap;
26553
26554                 }
26555
26556                 if ( uv2ScaleMap !== undefined ) {
26557
26558                         // backwards compatibility
26559                         if ( uv2ScaleMap.isWebGLRenderTarget ) {
26560
26561                                 uv2ScaleMap = uv2ScaleMap.texture;
26562
26563                         }
26564
26565                         if ( uv2ScaleMap.matrixAutoUpdate === true ) {
26566
26567                                 uv2ScaleMap.updateMatrix();
26568
26569                         }
26570
26571                         uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
26572
26573                 }
26574
26575         }
26576
26577         function refreshUniformsLine( uniforms, material ) {
26578
26579                 uniforms.diffuse.value.copy( material.color );
26580                 uniforms.opacity.value = material.opacity;
26581
26582         }
26583
26584         function refreshUniformsDash( uniforms, material ) {
26585
26586                 uniforms.dashSize.value = material.dashSize;
26587                 uniforms.totalSize.value = material.dashSize + material.gapSize;
26588                 uniforms.scale.value = material.scale;
26589
26590         }
26591
26592         function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
26593
26594                 uniforms.diffuse.value.copy( material.color );
26595                 uniforms.opacity.value = material.opacity;
26596                 uniforms.size.value = material.size * pixelRatio;
26597                 uniforms.scale.value = height * 0.5;
26598
26599                 if ( material.map ) {
26600
26601                         uniforms.map.value = material.map;
26602
26603                 }
26604
26605                 if ( material.alphaMap ) {
26606
26607                         uniforms.alphaMap.value = material.alphaMap;
26608
26609                 }
26610
26611                 // uv repeat and offset setting priorities
26612                 // 1. color map
26613                 // 2. alpha map
26614
26615                 let uvScaleMap;
26616
26617                 if ( material.map ) {
26618
26619                         uvScaleMap = material.map;
26620
26621                 } else if ( material.alphaMap ) {
26622
26623                         uvScaleMap = material.alphaMap;
26624
26625                 }
26626
26627                 if ( uvScaleMap !== undefined ) {
26628
26629                         if ( uvScaleMap.matrixAutoUpdate === true ) {
26630
26631                                 uvScaleMap.updateMatrix();
26632
26633                         }
26634
26635                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26636
26637                 }
26638
26639         }
26640
26641         function refreshUniformsSprites( uniforms, material ) {
26642
26643                 uniforms.diffuse.value.copy( material.color );
26644                 uniforms.opacity.value = material.opacity;
26645                 uniforms.rotation.value = material.rotation;
26646
26647                 if ( material.map ) {
26648
26649                         uniforms.map.value = material.map;
26650
26651                 }
26652
26653                 if ( material.alphaMap ) {
26654
26655                         uniforms.alphaMap.value = material.alphaMap;
26656
26657                 }
26658
26659                 // uv repeat and offset setting priorities
26660                 // 1. color map
26661                 // 2. alpha map
26662
26663                 let uvScaleMap;
26664
26665                 if ( material.map ) {
26666
26667                         uvScaleMap = material.map;
26668
26669                 } else if ( material.alphaMap ) {
26670
26671                         uvScaleMap = material.alphaMap;
26672
26673                 }
26674
26675                 if ( uvScaleMap !== undefined ) {
26676
26677                         if ( uvScaleMap.matrixAutoUpdate === true ) {
26678
26679                                 uvScaleMap.updateMatrix();
26680
26681                         }
26682
26683                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26684
26685                 }
26686
26687         }
26688
26689         function refreshUniformsLambert( uniforms, material ) {
26690
26691                 if ( material.emissiveMap ) {
26692
26693                         uniforms.emissiveMap.value = material.emissiveMap;
26694
26695                 }
26696
26697         }
26698
26699         function refreshUniformsPhong( uniforms, material ) {
26700
26701                 uniforms.specular.value.copy( material.specular );
26702                 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
26703
26704                 if ( material.emissiveMap ) {
26705
26706                         uniforms.emissiveMap.value = material.emissiveMap;
26707
26708                 }
26709
26710                 if ( material.bumpMap ) {
26711
26712                         uniforms.bumpMap.value = material.bumpMap;
26713                         uniforms.bumpScale.value = material.bumpScale;
26714                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26715
26716                 }
26717
26718                 if ( material.normalMap ) {
26719
26720                         uniforms.normalMap.value = material.normalMap;
26721                         uniforms.normalScale.value.copy( material.normalScale );
26722                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26723
26724                 }
26725
26726                 if ( material.displacementMap ) {
26727
26728                         uniforms.displacementMap.value = material.displacementMap;
26729                         uniforms.displacementScale.value = material.displacementScale;
26730                         uniforms.displacementBias.value = material.displacementBias;
26731
26732                 }
26733
26734         }
26735
26736         function refreshUniformsToon( uniforms, material ) {
26737
26738                 if ( material.gradientMap ) {
26739
26740                         uniforms.gradientMap.value = material.gradientMap;
26741
26742                 }
26743
26744                 if ( material.emissiveMap ) {
26745
26746                         uniforms.emissiveMap.value = material.emissiveMap;
26747
26748                 }
26749
26750                 if ( material.bumpMap ) {
26751
26752                         uniforms.bumpMap.value = material.bumpMap;
26753                         uniforms.bumpScale.value = material.bumpScale;
26754                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26755
26756                 }
26757
26758                 if ( material.normalMap ) {
26759
26760                         uniforms.normalMap.value = material.normalMap;
26761                         uniforms.normalScale.value.copy( material.normalScale );
26762                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26763
26764                 }
26765
26766                 if ( material.displacementMap ) {
26767
26768                         uniforms.displacementMap.value = material.displacementMap;
26769                         uniforms.displacementScale.value = material.displacementScale;
26770                         uniforms.displacementBias.value = material.displacementBias;
26771
26772                 }
26773
26774         }
26775
26776         function refreshUniformsStandard( uniforms, material ) {
26777
26778                 uniforms.roughness.value = material.roughness;
26779                 uniforms.metalness.value = material.metalness;
26780
26781                 if ( material.roughnessMap ) {
26782
26783                         uniforms.roughnessMap.value = material.roughnessMap;
26784
26785                 }
26786
26787                 if ( material.metalnessMap ) {
26788
26789                         uniforms.metalnessMap.value = material.metalnessMap;
26790
26791                 }
26792
26793                 if ( material.emissiveMap ) {
26794
26795                         uniforms.emissiveMap.value = material.emissiveMap;
26796
26797                 }
26798
26799                 if ( material.bumpMap ) {
26800
26801                         uniforms.bumpMap.value = material.bumpMap;
26802                         uniforms.bumpScale.value = material.bumpScale;
26803                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26804
26805                 }
26806
26807                 if ( material.normalMap ) {
26808
26809                         uniforms.normalMap.value = material.normalMap;
26810                         uniforms.normalScale.value.copy( material.normalScale );
26811                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26812
26813                 }
26814
26815                 if ( material.displacementMap ) {
26816
26817                         uniforms.displacementMap.value = material.displacementMap;
26818                         uniforms.displacementScale.value = material.displacementScale;
26819                         uniforms.displacementBias.value = material.displacementBias;
26820
26821                 }
26822
26823                 const envMap = properties.get( material ).envMap;
26824
26825                 if ( envMap ) {
26826
26827                         //uniforms.envMap.value = material.envMap; // part of uniforms common
26828                         uniforms.envMapIntensity.value = material.envMapIntensity;
26829
26830                 }
26831
26832         }
26833
26834         function refreshUniformsPhysical( uniforms, material ) {
26835
26836                 refreshUniformsStandard( uniforms, material );
26837
26838                 uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
26839
26840                 uniforms.clearcoat.value = material.clearcoat;
26841                 uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
26842                 if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
26843
26844                 if ( material.clearcoatMap ) {
26845
26846                         uniforms.clearcoatMap.value = material.clearcoatMap;
26847
26848                 }
26849
26850                 if ( material.clearcoatRoughnessMap ) {
26851
26852                         uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
26853
26854                 }
26855
26856                 if ( material.clearcoatNormalMap ) {
26857
26858                         uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
26859                         uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
26860
26861                         if ( material.side === BackSide ) {
26862
26863                                 uniforms.clearcoatNormalScale.value.negate();
26864
26865                         }
26866
26867                 }
26868
26869                 uniforms.transmission.value = material.transmission;
26870
26871                 if ( material.transmissionMap ) {
26872
26873                         uniforms.transmissionMap.value = material.transmissionMap;
26874
26875                 }
26876
26877         }
26878
26879         function refreshUniformsMatcap( uniforms, material ) {
26880
26881                 if ( material.matcap ) {
26882
26883                         uniforms.matcap.value = material.matcap;
26884
26885                 }
26886
26887                 if ( material.bumpMap ) {
26888
26889                         uniforms.bumpMap.value = material.bumpMap;
26890                         uniforms.bumpScale.value = material.bumpScale;
26891                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26892
26893                 }
26894
26895                 if ( material.normalMap ) {
26896
26897                         uniforms.normalMap.value = material.normalMap;
26898                         uniforms.normalScale.value.copy( material.normalScale );
26899                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26900
26901                 }
26902
26903                 if ( material.displacementMap ) {
26904
26905                         uniforms.displacementMap.value = material.displacementMap;
26906                         uniforms.displacementScale.value = material.displacementScale;
26907                         uniforms.displacementBias.value = material.displacementBias;
26908
26909                 }
26910
26911         }
26912
26913         function refreshUniformsDepth( uniforms, material ) {
26914
26915                 if ( material.displacementMap ) {
26916
26917                         uniforms.displacementMap.value = material.displacementMap;
26918                         uniforms.displacementScale.value = material.displacementScale;
26919                         uniforms.displacementBias.value = material.displacementBias;
26920
26921                 }
26922
26923         }
26924
26925         function refreshUniformsDistance( uniforms, material ) {
26926
26927                 if ( material.displacementMap ) {
26928
26929                         uniforms.displacementMap.value = material.displacementMap;
26930                         uniforms.displacementScale.value = material.displacementScale;
26931                         uniforms.displacementBias.value = material.displacementBias;
26932
26933                 }
26934
26935                 uniforms.referencePosition.value.copy( material.referencePosition );
26936                 uniforms.nearDistance.value = material.nearDistance;
26937                 uniforms.farDistance.value = material.farDistance;
26938
26939         }
26940
26941         function refreshUniformsNormal( uniforms, material ) {
26942
26943                 if ( material.bumpMap ) {
26944
26945                         uniforms.bumpMap.value = material.bumpMap;
26946                         uniforms.bumpScale.value = material.bumpScale;
26947                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26948
26949                 }
26950
26951                 if ( material.normalMap ) {
26952
26953                         uniforms.normalMap.value = material.normalMap;
26954                         uniforms.normalScale.value.copy( material.normalScale );
26955                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26956
26957                 }
26958
26959                 if ( material.displacementMap ) {
26960
26961                         uniforms.displacementMap.value = material.displacementMap;
26962                         uniforms.displacementScale.value = material.displacementScale;
26963                         uniforms.displacementBias.value = material.displacementBias;
26964
26965                 }
26966
26967         }
26968
26969         return {
26970                 refreshFogUniforms: refreshFogUniforms,
26971                 refreshMaterialUniforms: refreshMaterialUniforms
26972         };
26973
26974     }
26975
26976     function createCanvasElement() {
26977
26978         const canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
26979         canvas.style.display = 'block';
26980         return canvas;
26981
26982     }
26983
26984     function WebGLRenderer( parameters ) {
26985
26986         parameters = parameters || {};
26987
26988         const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
26989                 _context = parameters.context !== undefined ? parameters.context : null,
26990
26991                 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
26992                 _depth = parameters.depth !== undefined ? parameters.depth : true,
26993                 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
26994                 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
26995                 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
26996                 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
26997                 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
26998                 _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
26999
27000         let currentRenderList = null;
27001         let currentRenderState = null;
27002
27003         // render() can be called from within a callback triggered by another render.
27004         // We track this so that the nested render call gets its state isolated from the parent render call.
27005
27006         const renderStateStack = [];
27007
27008         // public properties
27009
27010         this.domElement = _canvas;
27011
27012         // Debug configuration container
27013         this.debug = {
27014
27015                 /**
27016                  * Enables error checking and reporting when shader programs are being compiled
27017                  * @type {boolean}
27018                  */
27019                 checkShaderErrors: true
27020         };
27021
27022         // clearing
27023
27024         this.autoClear = true;
27025         this.autoClearColor = true;
27026         this.autoClearDepth = true;
27027         this.autoClearStencil = true;
27028
27029         // scene graph
27030
27031         this.sortObjects = true;
27032
27033         // user-defined clipping
27034
27035         this.clippingPlanes = [];
27036         this.localClippingEnabled = false;
27037
27038         // physically based shading
27039
27040         this.gammaFactor = 2.0; // for backwards compatibility
27041         this.outputEncoding = LinearEncoding;
27042
27043         // physical lights
27044
27045         this.physicallyCorrectLights = false;
27046
27047         // tone mapping
27048
27049         this.toneMapping = NoToneMapping;
27050         this.toneMappingExposure = 1.0;
27051
27052         // morphs
27053
27054         this.maxMorphTargets = 8;
27055         this.maxMorphNormals = 4;
27056
27057         // internal properties
27058
27059         const _this = this;
27060
27061         let _isContextLost = false;
27062
27063         // internal state cache
27064
27065         let _framebuffer = null;
27066
27067         let _currentActiveCubeFace = 0;
27068         let _currentActiveMipmapLevel = 0;
27069         let _currentRenderTarget = null;
27070         let _currentFramebuffer = null;
27071         let _currentMaterialId = - 1;
27072
27073         let _currentCamera = null;
27074
27075         const _currentViewport = new Vector4();
27076         const _currentScissor = new Vector4();
27077         let _currentScissorTest = null;
27078
27079         //
27080
27081         let _width = _canvas.width;
27082         let _height = _canvas.height;
27083
27084         let _pixelRatio = 1;
27085         let _opaqueSort = null;
27086         let _transparentSort = null;
27087
27088         const _viewport = new Vector4( 0, 0, _width, _height );
27089         const _scissor = new Vector4( 0, 0, _width, _height );
27090         let _scissorTest = false;
27091
27092         // frustum
27093
27094         const _frustum = new Frustum();
27095
27096         // clipping
27097
27098         let _clippingEnabled = false;
27099         let _localClippingEnabled = false;
27100
27101         // camera matrices cache
27102
27103         const _projScreenMatrix = new Matrix4();
27104
27105         const _vector3 = new Vector3();
27106
27107         const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
27108
27109         function getTargetPixelRatio() {
27110
27111                 return _currentRenderTarget === null ? _pixelRatio : 1;
27112
27113         }
27114
27115         // initialize
27116
27117         let _gl = _context;
27118
27119         function getContext( contextNames, contextAttributes ) {
27120
27121                 for ( let i = 0; i < contextNames.length; i ++ ) {
27122
27123                         const contextName = contextNames[ i ];
27124                         const context = _canvas.getContext( contextName, contextAttributes );
27125                         if ( context !== null ) return context;
27126
27127                 }
27128
27129                 return null;
27130
27131         }
27132
27133         try {
27134
27135                 const contextAttributes = {
27136                         alpha: _alpha,
27137                         depth: _depth,
27138                         stencil: _stencil,
27139                         antialias: _antialias,
27140                         premultipliedAlpha: _premultipliedAlpha,
27141                         preserveDrawingBuffer: _preserveDrawingBuffer,
27142                         powerPreference: _powerPreference,
27143                         failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
27144                 };
27145
27146                 // event listeners must be registered before WebGL context is created, see #12753
27147
27148                 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
27149                 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
27150
27151                 if ( _gl === null ) {
27152
27153                         const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
27154
27155                         if ( _this.isWebGL1Renderer === true ) {
27156
27157                                 contextNames.shift();
27158
27159                         }
27160
27161                         _gl = getContext( contextNames, contextAttributes );
27162
27163                         if ( _gl === null ) {
27164
27165                                 if ( getContext( contextNames ) ) {
27166
27167                                         throw new Error( 'Error creating WebGL context with your selected attributes.' );
27168
27169                                 } else {
27170
27171                                         throw new Error( 'Error creating WebGL context.' );
27172
27173                                 }
27174
27175                         }
27176
27177                 }
27178
27179                 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
27180
27181                 if ( _gl.getShaderPrecisionFormat === undefined ) {
27182
27183                         _gl.getShaderPrecisionFormat = function () {
27184
27185                                 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
27186
27187                         };
27188
27189                 }
27190
27191         } catch ( error ) {
27192
27193                 console.error( 'THREE.WebGLRenderer: ' + error.message );
27194                 throw error;
27195
27196         }
27197
27198         let extensions, capabilities, state, info;
27199         let properties, textures, cubemaps, attributes, geometries, objects;
27200         let programCache, materials, renderLists, renderStates, clipping;
27201
27202         let background, morphtargets, bufferRenderer, indexedBufferRenderer;
27203
27204         let utils, bindingStates;
27205
27206         function initGLContext() {
27207
27208                 extensions = new WebGLExtensions( _gl );
27209
27210                 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
27211
27212                 extensions.init( capabilities );
27213
27214                 utils = new WebGLUtils( _gl, extensions, capabilities );
27215
27216                 state = new WebGLState( _gl, extensions, capabilities );
27217                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
27218                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
27219
27220                 info = new WebGLInfo( _gl );
27221                 properties = new WebGLProperties();
27222                 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
27223                 cubemaps = new WebGLCubeMaps( _this );
27224                 attributes = new WebGLAttributes( _gl, capabilities );
27225                 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
27226                 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
27227                 objects = new WebGLObjects( _gl, geometries, attributes, info );
27228                 morphtargets = new WebGLMorphtargets( _gl );
27229                 clipping = new WebGLClipping( properties );
27230                 programCache = new WebGLPrograms( _this, cubemaps, extensions, capabilities, bindingStates, clipping );
27231                 materials = new WebGLMaterials( properties );
27232                 renderLists = new WebGLRenderLists( properties );
27233                 renderStates = new WebGLRenderStates( extensions, capabilities );
27234                 background = new WebGLBackground( _this, cubemaps, state, objects, _premultipliedAlpha );
27235
27236                 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
27237                 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
27238
27239                 info.programs = programCache.programs;
27240
27241                 _this.capabilities = capabilities;
27242                 _this.extensions = extensions;
27243                 _this.properties = properties;
27244                 _this.renderLists = renderLists;
27245                 _this.state = state;
27246                 _this.info = info;
27247
27248         }
27249
27250         initGLContext();
27251
27252         // xr
27253
27254         const xr = new WebXRManager( _this, _gl );
27255
27256         this.xr = xr;
27257
27258         // shadow map
27259
27260         const shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
27261
27262         this.shadowMap = shadowMap;
27263
27264         // API
27265
27266         this.getContext = function () {
27267
27268                 return _gl;
27269
27270         };
27271
27272         this.getContextAttributes = function () {
27273
27274                 return _gl.getContextAttributes();
27275
27276         };
27277
27278         this.forceContextLoss = function () {
27279
27280                 const extension = extensions.get( 'WEBGL_lose_context' );
27281                 if ( extension ) extension.loseContext();
27282
27283         };
27284
27285         this.forceContextRestore = function () {
27286
27287                 const extension = extensions.get( 'WEBGL_lose_context' );
27288                 if ( extension ) extension.restoreContext();
27289
27290         };
27291
27292         this.getPixelRatio = function () {
27293
27294                 return _pixelRatio;
27295
27296         };
27297
27298         this.setPixelRatio = function ( value ) {
27299
27300                 if ( value === undefined ) return;
27301
27302                 _pixelRatio = value;
27303
27304                 this.setSize( _width, _height, false );
27305
27306         };
27307
27308         this.getSize = function ( target ) {
27309
27310                 if ( target === undefined ) {
27311
27312                         console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
27313
27314                         target = new Vector2();
27315
27316                 }
27317
27318                 return target.set( _width, _height );
27319
27320         };
27321
27322         this.setSize = function ( width, height, updateStyle ) {
27323
27324                 if ( xr.isPresenting ) {
27325
27326                         console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
27327                         return;
27328
27329                 }
27330
27331                 _width = width;
27332                 _height = height;
27333
27334                 _canvas.width = Math.floor( width * _pixelRatio );
27335                 _canvas.height = Math.floor( height * _pixelRatio );
27336
27337                 if ( updateStyle !== false ) {
27338
27339                         _canvas.style.width = width + 'px';
27340                         _canvas.style.height = height + 'px';
27341
27342                 }
27343
27344                 this.setViewport( 0, 0, width, height );
27345
27346         };
27347
27348         this.getDrawingBufferSize = function ( target ) {
27349
27350                 if ( target === undefined ) {
27351
27352                         console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
27353
27354                         target = new Vector2();
27355
27356                 }
27357
27358                 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
27359
27360         };
27361
27362         this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
27363
27364                 _width = width;
27365                 _height = height;
27366
27367                 _pixelRatio = pixelRatio;
27368
27369                 _canvas.width = Math.floor( width * pixelRatio );
27370                 _canvas.height = Math.floor( height * pixelRatio );
27371
27372                 this.setViewport( 0, 0, width, height );
27373
27374         };
27375
27376         this.getCurrentViewport = function ( target ) {
27377
27378                 if ( target === undefined ) {
27379
27380                         console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
27381
27382                         target = new Vector4();
27383
27384                 }
27385
27386                 return target.copy( _currentViewport );
27387
27388         };
27389
27390         this.getViewport = function ( target ) {
27391
27392                 return target.copy( _viewport );
27393
27394         };
27395
27396         this.setViewport = function ( x, y, width, height ) {
27397
27398                 if ( x.isVector4 ) {
27399
27400                         _viewport.set( x.x, x.y, x.z, x.w );
27401
27402                 } else {
27403
27404                         _viewport.set( x, y, width, height );
27405
27406                 }
27407
27408                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
27409
27410         };
27411
27412         this.getScissor = function ( target ) {
27413
27414                 return target.copy( _scissor );
27415
27416         };
27417
27418         this.setScissor = function ( x, y, width, height ) {
27419
27420                 if ( x.isVector4 ) {
27421
27422                         _scissor.set( x.x, x.y, x.z, x.w );
27423
27424                 } else {
27425
27426                         _scissor.set( x, y, width, height );
27427
27428                 }
27429
27430                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
27431
27432         };
27433
27434         this.getScissorTest = function () {
27435
27436                 return _scissorTest;
27437
27438         };
27439
27440         this.setScissorTest = function ( boolean ) {
27441
27442                 state.setScissorTest( _scissorTest = boolean );
27443
27444         };
27445
27446         this.setOpaqueSort = function ( method ) {
27447
27448                 _opaqueSort = method;
27449
27450         };
27451
27452         this.setTransparentSort = function ( method ) {
27453
27454                 _transparentSort = method;
27455
27456         };
27457
27458         // Clearing
27459
27460         this.getClearColor = function ( target ) {
27461
27462                 if ( target === undefined ) {
27463
27464                         console.warn( 'WebGLRenderer: .getClearColor() now requires a Color as an argument' );
27465
27466                         target = new Color();
27467
27468                 }
27469
27470                 return target.copy( background.getClearColor() );
27471
27472         };
27473
27474         this.setClearColor = function () {
27475
27476                 background.setClearColor.apply( background, arguments );
27477
27478         };
27479
27480         this.getClearAlpha = function () {
27481
27482                 return background.getClearAlpha();
27483
27484         };
27485
27486         this.setClearAlpha = function () {
27487
27488                 background.setClearAlpha.apply( background, arguments );
27489
27490         };
27491
27492         this.clear = function ( color, depth, stencil ) {
27493
27494                 let bits = 0;
27495
27496                 if ( color === undefined || color ) bits |= 16384;
27497                 if ( depth === undefined || depth ) bits |= 256;
27498                 if ( stencil === undefined || stencil ) bits |= 1024;
27499
27500                 _gl.clear( bits );
27501
27502         };
27503
27504         this.clearColor = function () {
27505
27506                 this.clear( true, false, false );
27507
27508         };
27509
27510         this.clearDepth = function () {
27511
27512                 this.clear( false, true, false );
27513
27514         };
27515
27516         this.clearStencil = function () {
27517
27518                 this.clear( false, false, true );
27519
27520         };
27521
27522         //
27523
27524         this.dispose = function () {
27525
27526                 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
27527                 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
27528
27529                 renderLists.dispose();
27530                 renderStates.dispose();
27531                 properties.dispose();
27532                 cubemaps.dispose();
27533                 objects.dispose();
27534                 bindingStates.dispose();
27535
27536                 xr.dispose();
27537
27538                 animation.stop();
27539
27540         };
27541
27542         // Events
27543
27544         function onContextLost( event ) {
27545
27546                 event.preventDefault();
27547
27548                 console.log( 'THREE.WebGLRenderer: Context Lost.' );
27549
27550                 _isContextLost = true;
27551
27552         }
27553
27554         function onContextRestore( /* event */ ) {
27555
27556                 console.log( 'THREE.WebGLRenderer: Context Restored.' );
27557
27558                 _isContextLost = false;
27559
27560                 initGLContext();
27561
27562         }
27563
27564         function onMaterialDispose( event ) {
27565
27566                 const material = event.target;
27567
27568                 material.removeEventListener( 'dispose', onMaterialDispose );
27569
27570                 deallocateMaterial( material );
27571
27572         }
27573
27574         // Buffer deallocation
27575
27576         function deallocateMaterial( material ) {
27577
27578                 releaseMaterialProgramReference( material );
27579
27580                 properties.remove( material );
27581
27582         }
27583
27584
27585         function releaseMaterialProgramReference( material ) {
27586
27587                 const programInfo = properties.get( material ).program;
27588
27589                 if ( programInfo !== undefined ) {
27590
27591                         programCache.releaseProgram( programInfo );
27592
27593                 }
27594
27595         }
27596
27597         // Buffer rendering
27598
27599         function renderObjectImmediate( object, program ) {
27600
27601                 object.render( function ( object ) {
27602
27603                         _this.renderBufferImmediate( object, program );
27604
27605                 } );
27606
27607         }
27608
27609         this.renderBufferImmediate = function ( object, program ) {
27610
27611                 bindingStates.initAttributes();
27612
27613                 const buffers = properties.get( object );
27614
27615                 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
27616                 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
27617                 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
27618                 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
27619
27620                 const programAttributes = program.getAttributes();
27621
27622                 if ( object.hasPositions ) {
27623
27624                         _gl.bindBuffer( 34962, buffers.position );
27625                         _gl.bufferData( 34962, object.positionArray, 35048 );
27626
27627                         bindingStates.enableAttribute( programAttributes.position );
27628                         _gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
27629
27630                 }
27631
27632                 if ( object.hasNormals ) {
27633
27634                         _gl.bindBuffer( 34962, buffers.normal );
27635                         _gl.bufferData( 34962, object.normalArray, 35048 );
27636
27637                         bindingStates.enableAttribute( programAttributes.normal );
27638                         _gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
27639
27640                 }
27641
27642                 if ( object.hasUvs ) {
27643
27644                         _gl.bindBuffer( 34962, buffers.uv );
27645                         _gl.bufferData( 34962, object.uvArray, 35048 );
27646
27647                         bindingStates.enableAttribute( programAttributes.uv );
27648                         _gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
27649
27650                 }
27651
27652                 if ( object.hasColors ) {
27653
27654                         _gl.bindBuffer( 34962, buffers.color );
27655                         _gl.bufferData( 34962, object.colorArray, 35048 );
27656
27657                         bindingStates.enableAttribute( programAttributes.color );
27658                         _gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
27659
27660                 }
27661
27662                 bindingStates.disableUnusedAttributes();
27663
27664                 _gl.drawArrays( 4, 0, object.count );
27665
27666                 object.count = 0;
27667
27668         };
27669
27670         this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
27671
27672                 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
27673
27674                 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
27675
27676                 const program = setProgram( camera, scene, material, object );
27677
27678                 state.setMaterial( material, frontFaceCW );
27679
27680                 //
27681
27682                 let index = geometry.index;
27683                 const position = geometry.attributes.position;
27684
27685                 //
27686
27687                 if ( index === null ) {
27688
27689                         if ( position === undefined || position.count === 0 ) return;
27690
27691                 } else if ( index.count === 0 ) {
27692
27693                         return;
27694
27695                 }
27696
27697                 //
27698
27699                 let rangeFactor = 1;
27700
27701                 if ( material.wireframe === true ) {
27702
27703                         index = geometries.getWireframeAttribute( geometry );
27704                         rangeFactor = 2;
27705
27706                 }
27707
27708                 if ( material.morphTargets || material.morphNormals ) {
27709
27710                         morphtargets.update( object, geometry, material, program );
27711
27712                 }
27713
27714                 bindingStates.setup( object, material, program, geometry, index );
27715
27716                 let attribute;
27717                 let renderer = bufferRenderer;
27718
27719                 if ( index !== null ) {
27720
27721                         attribute = attributes.get( index );
27722
27723                         renderer = indexedBufferRenderer;
27724                         renderer.setIndex( attribute );
27725
27726                 }
27727
27728                 //
27729
27730                 const dataCount = ( index !== null ) ? index.count : position.count;
27731
27732                 const rangeStart = geometry.drawRange.start * rangeFactor;
27733                 const rangeCount = geometry.drawRange.count * rangeFactor;
27734
27735                 const groupStart = group !== null ? group.start * rangeFactor : 0;
27736                 const groupCount = group !== null ? group.count * rangeFactor : Infinity;
27737
27738                 const drawStart = Math.max( rangeStart, groupStart );
27739                 const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
27740
27741                 const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
27742
27743                 if ( drawCount === 0 ) return;
27744
27745                 //
27746
27747                 if ( object.isMesh ) {
27748
27749                         if ( material.wireframe === true ) {
27750
27751                                 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
27752                                 renderer.setMode( 1 );
27753
27754                         } else {
27755
27756                                 renderer.setMode( 4 );
27757
27758                         }
27759
27760                 } else if ( object.isLine ) {
27761
27762                         let lineWidth = material.linewidth;
27763
27764                         if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
27765
27766                         state.setLineWidth( lineWidth * getTargetPixelRatio() );
27767
27768                         if ( object.isLineSegments ) {
27769
27770                                 renderer.setMode( 1 );
27771
27772                         } else if ( object.isLineLoop ) {
27773
27774                                 renderer.setMode( 2 );
27775
27776                         } else {
27777
27778                                 renderer.setMode( 3 );
27779
27780                         }
27781
27782                 } else if ( object.isPoints ) {
27783
27784                         renderer.setMode( 0 );
27785
27786                 } else if ( object.isSprite ) {
27787
27788                         renderer.setMode( 4 );
27789
27790                 }
27791
27792                 if ( object.isInstancedMesh ) {
27793
27794                         renderer.renderInstances( drawStart, drawCount, object.count );
27795
27796                 } else if ( geometry.isInstancedBufferGeometry ) {
27797
27798                         const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
27799
27800                         renderer.renderInstances( drawStart, drawCount, instanceCount );
27801
27802                 } else {
27803
27804                         renderer.render( drawStart, drawCount );
27805
27806                 }
27807
27808         };
27809
27810         // Compile
27811
27812         this.compile = function ( scene, camera ) {
27813
27814                 currentRenderState = renderStates.get( scene );
27815                 currentRenderState.init();
27816
27817                 scene.traverseVisible( function ( object ) {
27818
27819                         if ( object.isLight && object.layers.test( camera.layers ) ) {
27820
27821                                 currentRenderState.pushLight( object );
27822
27823                                 if ( object.castShadow ) {
27824
27825                                         currentRenderState.pushShadow( object );
27826
27827                                 }
27828
27829                         }
27830
27831                 } );
27832
27833                 currentRenderState.setupLights();
27834
27835                 const compiled = new WeakMap();
27836
27837                 scene.traverse( function ( object ) {
27838
27839                         const material = object.material;
27840
27841                         if ( material ) {
27842
27843                                 if ( Array.isArray( material ) ) {
27844
27845                                         for ( let i = 0; i < material.length; i ++ ) {
27846
27847                                                 const material2 = material[ i ];
27848
27849                                                 if ( compiled.has( material2 ) === false ) {
27850
27851                                                         initMaterial( material2, scene, object );
27852                                                         compiled.set( material2 );
27853
27854                                                 }
27855
27856                                         }
27857
27858                                 } else if ( compiled.has( material ) === false ) {
27859
27860                                         initMaterial( material, scene, object );
27861                                         compiled.set( material );
27862
27863                                 }
27864
27865                         }
27866
27867                 } );
27868
27869         };
27870
27871         // Animation Loop
27872
27873         let onAnimationFrameCallback = null;
27874
27875         function onAnimationFrame( time ) {
27876
27877                 if ( xr.isPresenting ) return;
27878                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
27879
27880         }
27881
27882         const animation = new WebGLAnimation();
27883         animation.setAnimationLoop( onAnimationFrame );
27884
27885         if ( typeof window !== 'undefined' ) animation.setContext( window );
27886
27887         this.setAnimationLoop = function ( callback ) {
27888
27889                 onAnimationFrameCallback = callback;
27890                 xr.setAnimationLoop( callback );
27891
27892                 ( callback === null ) ? animation.stop() : animation.start();
27893
27894         };
27895
27896         // Rendering
27897
27898         this.render = function ( scene, camera ) {
27899
27900                 let renderTarget, forceClear;
27901
27902                 if ( arguments[ 2 ] !== undefined ) {
27903
27904                         console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
27905                         renderTarget = arguments[ 2 ];
27906
27907                 }
27908
27909                 if ( arguments[ 3 ] !== undefined ) {
27910
27911                         console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
27912                         forceClear = arguments[ 3 ];
27913
27914                 }
27915
27916                 if ( camera !== undefined && camera.isCamera !== true ) {
27917
27918                         console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
27919                         return;
27920
27921                 }
27922
27923                 if ( _isContextLost === true ) return;
27924
27925                 // reset caching for this frame
27926
27927                 bindingStates.resetDefaultState();
27928                 _currentMaterialId = - 1;
27929                 _currentCamera = null;
27930
27931                 // update scene graph
27932
27933                 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
27934
27935                 // update camera matrices and frustum
27936
27937                 if ( camera.parent === null ) camera.updateMatrixWorld();
27938
27939                 if ( xr.enabled === true && xr.isPresenting === true ) {
27940
27941                         camera = xr.getCamera( camera );
27942
27943                 }
27944
27945                 //
27946                 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
27947
27948                 currentRenderState = renderStates.get( scene, renderStateStack.length );
27949                 currentRenderState.init();
27950
27951                 renderStateStack.push( currentRenderState );
27952
27953                 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
27954                 _frustum.setFromProjectionMatrix( _projScreenMatrix );
27955
27956                 _localClippingEnabled = this.localClippingEnabled;
27957                 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
27958
27959                 currentRenderList = renderLists.get( scene, camera );
27960                 currentRenderList.init();
27961
27962                 projectObject( scene, camera, 0, _this.sortObjects );
27963
27964                 currentRenderList.finish();
27965
27966                 if ( _this.sortObjects === true ) {
27967
27968                         currentRenderList.sort( _opaqueSort, _transparentSort );
27969
27970                 }
27971
27972                 //
27973
27974                 if ( _clippingEnabled === true ) clipping.beginShadows();
27975
27976                 const shadowsArray = currentRenderState.state.shadowsArray;
27977
27978                 shadowMap.render( shadowsArray, scene, camera );
27979
27980                 currentRenderState.setupLights();
27981                 currentRenderState.setupLightsView( camera );
27982
27983                 if ( _clippingEnabled === true ) clipping.endShadows();
27984
27985                 //
27986
27987                 if ( this.info.autoReset === true ) this.info.reset();
27988
27989                 if ( renderTarget !== undefined ) {
27990
27991                         this.setRenderTarget( renderTarget );
27992
27993                 }
27994
27995                 //
27996
27997                 background.render( currentRenderList, scene, camera, forceClear );
27998
27999                 // render scene
28000
28001                 const opaqueObjects = currentRenderList.opaque;
28002                 const transparentObjects = currentRenderList.transparent;
28003
28004                 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
28005                 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
28006
28007                 //
28008
28009                 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
28010
28011                 //
28012
28013                 if ( _currentRenderTarget !== null ) {
28014
28015                         // Generate mipmap if we're using any kind of mipmap filtering
28016
28017                         textures.updateRenderTargetMipmap( _currentRenderTarget );
28018
28019                         // resolve multisample renderbuffers to a single-sample texture if necessary
28020
28021                         textures.updateMultisampleRenderTarget( _currentRenderTarget );
28022
28023                 }
28024
28025                 // Ensure depth buffer writing is enabled so it can be cleared on next render
28026
28027                 state.buffers.depth.setTest( true );
28028                 state.buffers.depth.setMask( true );
28029                 state.buffers.color.setMask( true );
28030
28031                 state.setPolygonOffset( false );
28032
28033                 // _gl.finish();
28034
28035                 renderStateStack.pop();
28036                 if ( renderStateStack.length > 0 ) {
28037
28038                         currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
28039
28040                 } else {
28041
28042                         currentRenderState = null;
28043
28044                 }
28045
28046                 currentRenderList = null;
28047
28048         };
28049
28050         function projectObject( object, camera, groupOrder, sortObjects ) {
28051
28052                 if ( object.visible === false ) return;
28053
28054                 const visible = object.layers.test( camera.layers );
28055
28056                 if ( visible ) {
28057
28058                         if ( object.isGroup ) {
28059
28060                                 groupOrder = object.renderOrder;
28061
28062                         } else if ( object.isLOD ) {
28063
28064                                 if ( object.autoUpdate === true ) object.update( camera );
28065
28066                         } else if ( object.isLight ) {
28067
28068                                 currentRenderState.pushLight( object );
28069
28070                                 if ( object.castShadow ) {
28071
28072                                         currentRenderState.pushShadow( object );
28073
28074                                 }
28075
28076                         } else if ( object.isSprite ) {
28077
28078                                 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
28079
28080                                         if ( sortObjects ) {
28081
28082                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
28083                                                         .applyMatrix4( _projScreenMatrix );
28084
28085                                         }
28086
28087                                         const geometry = objects.update( object );
28088                                         const material = object.material;
28089
28090                                         if ( material.visible ) {
28091
28092                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28093
28094                                         }
28095
28096                                 }
28097
28098                         } else if ( object.isImmediateRenderObject ) {
28099
28100                                 if ( sortObjects ) {
28101
28102                                         _vector3.setFromMatrixPosition( object.matrixWorld )
28103                                                 .applyMatrix4( _projScreenMatrix );
28104
28105                                 }
28106
28107                                 currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
28108
28109                         } else if ( object.isMesh || object.isLine || object.isPoints ) {
28110
28111                                 if ( object.isSkinnedMesh ) {
28112
28113                                         // update skeleton only once in a frame
28114
28115                                         if ( object.skeleton.frame !== info.render.frame ) {
28116
28117                                                 object.skeleton.update();
28118                                                 object.skeleton.frame = info.render.frame;
28119
28120                                         }
28121
28122                                 }
28123
28124                                 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
28125
28126                                         if ( sortObjects ) {
28127
28128                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
28129                                                         .applyMatrix4( _projScreenMatrix );
28130
28131                                         }
28132
28133                                         const geometry = objects.update( object );
28134                                         const material = object.material;
28135
28136                                         if ( Array.isArray( material ) ) {
28137
28138                                                 const groups = geometry.groups;
28139
28140                                                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
28141
28142                                                         const group = groups[ i ];
28143                                                         const groupMaterial = material[ group.materialIndex ];
28144
28145                                                         if ( groupMaterial && groupMaterial.visible ) {
28146
28147                                                                 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
28148
28149                                                         }
28150
28151                                                 }
28152
28153                                         } else if ( material.visible ) {
28154
28155                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28156
28157                                         }
28158
28159                                 }
28160
28161                         }
28162
28163                 }
28164
28165                 const children = object.children;
28166
28167                 for ( let i = 0, l = children.length; i < l; i ++ ) {
28168
28169                         projectObject( children[ i ], camera, groupOrder, sortObjects );
28170
28171                 }
28172
28173         }
28174
28175         function renderObjects( renderList, scene, camera ) {
28176
28177                 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
28178
28179                 for ( let i = 0, l = renderList.length; i < l; i ++ ) {
28180
28181                         const renderItem = renderList[ i ];
28182
28183                         const object = renderItem.object;
28184                         const geometry = renderItem.geometry;
28185                         const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
28186                         const group = renderItem.group;
28187
28188                         if ( camera.isArrayCamera ) {
28189
28190                                 const cameras = camera.cameras;
28191
28192                                 for ( let j = 0, jl = cameras.length; j < jl; j ++ ) {
28193
28194                                         const camera2 = cameras[ j ];
28195
28196                                         if ( object.layers.test( camera2.layers ) ) {
28197
28198                                                 state.viewport( _currentViewport.copy( camera2.viewport ) );
28199
28200                                                 currentRenderState.setupLightsView( camera2 );
28201
28202                                                 renderObject( object, scene, camera2, geometry, material, group );
28203
28204                                         }
28205
28206                                 }
28207
28208                         } else {
28209
28210                                 renderObject( object, scene, camera, geometry, material, group );
28211
28212                         }
28213
28214                 }
28215
28216         }
28217
28218         function renderObject( object, scene, camera, geometry, material, group ) {
28219
28220                 object.onBeforeRender( _this, scene, camera, geometry, material, group );
28221
28222                 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
28223                 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
28224
28225                 if ( object.isImmediateRenderObject ) {
28226
28227                         const program = setProgram( camera, scene, material, object );
28228
28229                         state.setMaterial( material );
28230
28231                         bindingStates.reset();
28232
28233                         renderObjectImmediate( object, program );
28234
28235                 } else {
28236
28237                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
28238
28239                 }
28240
28241                 object.onAfterRender( _this, scene, camera, geometry, material, group );
28242
28243         }
28244
28245         function initMaterial( material, scene, object ) {
28246
28247                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
28248
28249                 const materialProperties = properties.get( material );
28250
28251                 const lights = currentRenderState.state.lights;
28252                 const shadowsArray = currentRenderState.state.shadowsArray;
28253
28254                 const lightsStateVersion = lights.state.version;
28255
28256                 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
28257                 const programCacheKey = programCache.getProgramCacheKey( parameters );
28258
28259                 let program = materialProperties.program;
28260                 let programChange = true;
28261
28262                 // always update environment and fog - changing these trigger an initMaterial call, but it's possible that the program doesn't change
28263
28264                 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
28265                 materialProperties.fog = scene.fog;
28266                 materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
28267
28268                 if ( program === undefined ) {
28269
28270                         // new material
28271                         material.addEventListener( 'dispose', onMaterialDispose );
28272
28273                 } else if ( program.cacheKey !== programCacheKey ) {
28274
28275                         // changed glsl or parameters
28276                         releaseMaterialProgramReference( material );
28277
28278                 } else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {
28279
28280                         programChange = false;
28281
28282                 } else if ( parameters.shaderID !== undefined ) {
28283
28284                         // same glsl and uniform list
28285                         return;
28286
28287                 } else {
28288
28289                         // only rebuild uniform list
28290                         programChange = false;
28291
28292                 }
28293
28294                 if ( programChange ) {
28295
28296                         parameters.uniforms = programCache.getUniforms( material );
28297
28298                         material.onBeforeCompile( parameters, _this );
28299
28300                         program = programCache.acquireProgram( parameters, programCacheKey );
28301
28302                         materialProperties.program = program;
28303                         materialProperties.uniforms = parameters.uniforms;
28304                         materialProperties.outputEncoding = parameters.outputEncoding;
28305
28306                 }
28307
28308                 const uniforms = materialProperties.uniforms;
28309
28310                 if ( ! material.isShaderMaterial &&
28311                         ! material.isRawShaderMaterial ||
28312                         material.clipping === true ) {
28313
28314                         materialProperties.numClippingPlanes = clipping.numPlanes;
28315                         materialProperties.numIntersection = clipping.numIntersection;
28316                         uniforms.clippingPlanes = clipping.uniform;
28317
28318                 }
28319
28320                 // store the light setup it was created for
28321
28322                 materialProperties.needsLights = materialNeedsLights( material );
28323                 materialProperties.lightsStateVersion = lightsStateVersion;
28324
28325                 if ( materialProperties.needsLights ) {
28326
28327                         // wire up the material to this renderer's lighting state
28328
28329                         uniforms.ambientLightColor.value = lights.state.ambient;
28330                         uniforms.lightProbe.value = lights.state.probe;
28331                         uniforms.directionalLights.value = lights.state.directional;
28332                         uniforms.directionalLightShadows.value = lights.state.directionalShadow;
28333                         uniforms.spotLights.value = lights.state.spot;
28334                         uniforms.spotLightShadows.value = lights.state.spotShadow;
28335                         uniforms.rectAreaLights.value = lights.state.rectArea;
28336                         uniforms.ltc_1.value = lights.state.rectAreaLTC1;
28337                         uniforms.ltc_2.value = lights.state.rectAreaLTC2;
28338                         uniforms.pointLights.value = lights.state.point;
28339                         uniforms.pointLightShadows.value = lights.state.pointShadow;
28340                         uniforms.hemisphereLights.value = lights.state.hemi;
28341
28342                         uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
28343                         uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
28344                         uniforms.spotShadowMap.value = lights.state.spotShadowMap;
28345                         uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
28346                         uniforms.pointShadowMap.value = lights.state.pointShadowMap;
28347                         uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
28348                         // TODO (abelnation): add area lights shadow info to uniforms
28349
28350                 }
28351
28352                 const progUniforms = materialProperties.program.getUniforms();
28353                 const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
28354
28355                 materialProperties.uniformsList = uniformsList;
28356
28357         }
28358
28359         function setProgram( camera, scene, material, object ) {
28360
28361                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
28362
28363                 textures.resetTextureUnits();
28364
28365                 const fog = scene.fog;
28366                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
28367                 const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
28368                 const envMap = cubemaps.get( material.envMap || environment );
28369
28370                 const materialProperties = properties.get( material );
28371                 const lights = currentRenderState.state.lights;
28372
28373                 if ( _clippingEnabled === true ) {
28374
28375                         if ( _localClippingEnabled === true || camera !== _currentCamera ) {
28376
28377                                 const useCache =
28378                                         camera === _currentCamera &&
28379                                         material.id === _currentMaterialId;
28380
28381                                 // we might want to call this function with some ClippingGroup
28382                                 // object instead of the material, once it becomes feasible
28383                                 // (#8465, #8379)
28384                                 clipping.setState( material, camera, useCache );
28385
28386                         }
28387
28388                 }
28389
28390                 if ( material.version === materialProperties.__version ) {
28391
28392                         if ( material.fog && materialProperties.fog !== fog ) {
28393
28394                                 initMaterial( material, scene, object );
28395
28396                         } else if ( materialProperties.environment !== environment ) {
28397
28398                                 initMaterial( material, scene, object );
28399
28400                         } else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
28401
28402                                 initMaterial( material, scene, object );
28403
28404                         } else if ( materialProperties.numClippingPlanes !== undefined &&
28405                                 ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
28406                                 materialProperties.numIntersection !== clipping.numIntersection ) ) {
28407
28408                                 initMaterial( material, scene, object );
28409
28410                         } else if ( materialProperties.outputEncoding !== encoding ) {
28411
28412                                 initMaterial( material, scene, object );
28413
28414                         } else if ( materialProperties.envMap !== envMap ) {
28415
28416                                 initMaterial( material, scene, object );
28417
28418                         }
28419
28420                 } else {
28421
28422                         initMaterial( material, scene, object );
28423                         materialProperties.__version = material.version;
28424
28425                 }
28426
28427                 let refreshProgram = false;
28428                 let refreshMaterial = false;
28429                 let refreshLights = false;
28430
28431                 const program = materialProperties.program,
28432                         p_uniforms = program.getUniforms(),
28433                         m_uniforms = materialProperties.uniforms;
28434
28435                 if ( state.useProgram( program.program ) ) {
28436
28437                         refreshProgram = true;
28438                         refreshMaterial = true;
28439                         refreshLights = true;
28440
28441                 }
28442
28443                 if ( material.id !== _currentMaterialId ) {
28444
28445                         _currentMaterialId = material.id;
28446
28447                         refreshMaterial = true;
28448
28449                 }
28450
28451                 if ( refreshProgram || _currentCamera !== camera ) {
28452
28453                         p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
28454
28455                         if ( capabilities.logarithmicDepthBuffer ) {
28456
28457                                 p_uniforms.setValue( _gl, 'logDepthBufFC',
28458                                         2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
28459
28460                         }
28461
28462                         if ( _currentCamera !== camera ) {
28463
28464                                 _currentCamera = camera;
28465
28466                                 // lighting uniforms depend on the camera so enforce an update
28467                                 // now, in case this material supports lights - or later, when
28468                                 // the next material that does gets activated:
28469
28470                                 refreshMaterial = true;         // set to true on material change
28471                                 refreshLights = true;           // remains set until update done
28472
28473                         }
28474
28475                         // load material specific uniforms
28476                         // (shader material also gets them for the sake of genericity)
28477
28478                         if ( material.isShaderMaterial ||
28479                                 material.isMeshPhongMaterial ||
28480                                 material.isMeshToonMaterial ||
28481                                 material.isMeshStandardMaterial ||
28482                                 material.envMap ) {
28483
28484                                 const uCamPos = p_uniforms.map.cameraPosition;
28485
28486                                 if ( uCamPos !== undefined ) {
28487
28488                                         uCamPos.setValue( _gl,
28489                                                 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
28490
28491                                 }
28492
28493                         }
28494
28495                         if ( material.isMeshPhongMaterial ||
28496                                 material.isMeshToonMaterial ||
28497                                 material.isMeshLambertMaterial ||
28498                                 material.isMeshBasicMaterial ||
28499                                 material.isMeshStandardMaterial ||
28500                                 material.isShaderMaterial ) {
28501
28502                                 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
28503
28504                         }
28505
28506                         if ( material.isMeshPhongMaterial ||
28507                                 material.isMeshToonMaterial ||
28508                                 material.isMeshLambertMaterial ||
28509                                 material.isMeshBasicMaterial ||
28510                                 material.isMeshStandardMaterial ||
28511                                 material.isShaderMaterial ||
28512                                 material.isShadowMaterial ||
28513                                 material.skinning ) {
28514
28515                                 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
28516
28517                         }
28518
28519                 }
28520
28521                 // skinning uniforms must be set even if material didn't change
28522                 // auto-setting of texture unit for bone texture must go before other textures
28523                 // otherwise textures used for skinning can take over texture units reserved for other material textures
28524
28525                 if ( material.skinning ) {
28526
28527                         p_uniforms.setOptional( _gl, object, 'bindMatrix' );
28528                         p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
28529
28530                         const skeleton = object.skeleton;
28531
28532                         if ( skeleton ) {
28533
28534                                 const bones = skeleton.bones;
28535
28536                                 if ( capabilities.floatVertexTextures ) {
28537
28538                                         if ( skeleton.boneTexture === null ) {
28539
28540                                                 // layout (1 matrix = 4 pixels)
28541                                                 //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
28542                                                 //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
28543                                                 //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
28544                                                 //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
28545                                                 //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
28546
28547
28548                                                 let size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
28549                                                 size = MathUtils.ceilPowerOfTwo( size );
28550                                                 size = Math.max( size, 4 );
28551
28552                                                 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
28553                                                 boneMatrices.set( skeleton.boneMatrices ); // copy current values
28554
28555                                                 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
28556
28557                                                 skeleton.boneMatrices = boneMatrices;
28558                                                 skeleton.boneTexture = boneTexture;
28559                                                 skeleton.boneTextureSize = size;
28560
28561                                         }
28562
28563                                         p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
28564                                         p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
28565
28566                                 } else {
28567
28568                                         p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
28569
28570                                 }
28571
28572                         }
28573
28574                 }
28575
28576                 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
28577
28578                         materialProperties.receiveShadow = object.receiveShadow;
28579                         p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
28580
28581                 }
28582
28583                 if ( refreshMaterial ) {
28584
28585                         p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
28586
28587                         if ( materialProperties.needsLights ) {
28588
28589                                 // the current material requires lighting info
28590
28591                                 // note: all lighting uniforms are always set correctly
28592                                 // they simply reference the renderer's state for their
28593                                 // values
28594                                 //
28595                                 // use the current material's .needsUpdate flags to set
28596                                 // the GL state when required
28597
28598                                 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
28599
28600                         }
28601
28602                         // refresh uniforms common to several materials
28603
28604                         if ( fog && material.fog ) {
28605
28606                                 materials.refreshFogUniforms( m_uniforms, fog );
28607
28608                         }
28609
28610                         materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height );
28611
28612                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
28613
28614                 }
28615
28616                 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
28617
28618                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
28619                         material.uniformsNeedUpdate = false;
28620
28621                 }
28622
28623                 if ( material.isSpriteMaterial ) {
28624
28625                         p_uniforms.setValue( _gl, 'center', object.center );
28626
28627                 }
28628
28629                 // common matrices
28630
28631                 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
28632                 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
28633                 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
28634
28635                 return program;
28636
28637         }
28638
28639         // If uniforms are marked as clean, they don't need to be loaded to the GPU.
28640
28641         function markUniformsLightsNeedsUpdate( uniforms, value ) {
28642
28643                 uniforms.ambientLightColor.needsUpdate = value;
28644                 uniforms.lightProbe.needsUpdate = value;
28645
28646                 uniforms.directionalLights.needsUpdate = value;
28647                 uniforms.directionalLightShadows.needsUpdate = value;
28648                 uniforms.pointLights.needsUpdate = value;
28649                 uniforms.pointLightShadows.needsUpdate = value;
28650                 uniforms.spotLights.needsUpdate = value;
28651                 uniforms.spotLightShadows.needsUpdate = value;
28652                 uniforms.rectAreaLights.needsUpdate = value;
28653                 uniforms.hemisphereLights.needsUpdate = value;
28654
28655         }
28656
28657         function materialNeedsLights( material ) {
28658
28659                 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
28660                         material.isMeshStandardMaterial || material.isShadowMaterial ||
28661                         ( material.isShaderMaterial && material.lights === true );
28662
28663         }
28664
28665         //
28666         this.setFramebuffer = function ( value ) {
28667
28668                 if ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( 36160, value );
28669
28670                 _framebuffer = value;
28671
28672         };
28673
28674         this.getActiveCubeFace = function () {
28675
28676                 return _currentActiveCubeFace;
28677
28678         };
28679
28680         this.getActiveMipmapLevel = function () {
28681
28682                 return _currentActiveMipmapLevel;
28683
28684         };
28685
28686         this.getRenderList = function () {
28687
28688                 return currentRenderList;
28689
28690         };
28691
28692         this.setRenderList = function ( renderList ) {
28693
28694                 currentRenderList = renderList;
28695
28696         };
28697
28698         this.getRenderTarget = function () {
28699
28700                 return _currentRenderTarget;
28701
28702         };
28703
28704         this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
28705
28706                 _currentRenderTarget = renderTarget;
28707                 _currentActiveCubeFace = activeCubeFace;
28708                 _currentActiveMipmapLevel = activeMipmapLevel;
28709
28710                 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
28711
28712                         textures.setupRenderTarget( renderTarget );
28713
28714                 }
28715
28716                 let framebuffer = _framebuffer;
28717                 let isCube = false;
28718
28719                 if ( renderTarget ) {
28720
28721                         const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
28722
28723                         if ( renderTarget.isWebGLCubeRenderTarget ) {
28724
28725                                 framebuffer = __webglFramebuffer[ activeCubeFace ];
28726                                 isCube = true;
28727
28728                         } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
28729
28730                                 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
28731
28732                         } else {
28733
28734                                 framebuffer = __webglFramebuffer;
28735
28736                         }
28737
28738                         _currentViewport.copy( renderTarget.viewport );
28739                         _currentScissor.copy( renderTarget.scissor );
28740                         _currentScissorTest = renderTarget.scissorTest;
28741
28742                 } else {
28743
28744                         _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
28745                         _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
28746                         _currentScissorTest = _scissorTest;
28747
28748                 }
28749
28750                 if ( _currentFramebuffer !== framebuffer ) {
28751
28752                         _gl.bindFramebuffer( 36160, framebuffer );
28753                         _currentFramebuffer = framebuffer;
28754
28755                 }
28756
28757                 state.viewport( _currentViewport );
28758                 state.scissor( _currentScissor );
28759                 state.setScissorTest( _currentScissorTest );
28760
28761                 if ( isCube ) {
28762
28763                         const textureProperties = properties.get( renderTarget.texture );
28764                         _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
28765
28766                 }
28767
28768         };
28769
28770         this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
28771
28772                 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
28773
28774                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
28775                         return;
28776
28777                 }
28778
28779                 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
28780
28781                 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
28782
28783                         framebuffer = framebuffer[ activeCubeFaceIndex ];
28784
28785                 }
28786
28787                 if ( framebuffer ) {
28788
28789                         let restore = false;
28790
28791                         if ( framebuffer !== _currentFramebuffer ) {
28792
28793                                 _gl.bindFramebuffer( 36160, framebuffer );
28794
28795                                 restore = true;
28796
28797                         }
28798
28799                         try {
28800
28801                                 const texture = renderTarget.texture;
28802                                 const textureFormat = texture.format;
28803                                 const textureType = texture.type;
28804
28805                                 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
28806
28807                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
28808                                         return;
28809
28810                                 }
28811
28812                                 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) );
28813
28814                                 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
28815                                         ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
28816                                         ! halfFloatSupportedByExt ) {
28817
28818                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
28819                                         return;
28820
28821                                 }
28822
28823                                 if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
28824
28825                                         // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
28826
28827                                         if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
28828
28829                                                 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
28830
28831                                         }
28832
28833                                 } else {
28834
28835                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
28836
28837                                 }
28838
28839                         } finally {
28840
28841                                 if ( restore ) {
28842
28843                                         _gl.bindFramebuffer( 36160, _currentFramebuffer );
28844
28845                                 }
28846
28847                         }
28848
28849                 }
28850
28851         };
28852
28853         this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
28854
28855                 const levelScale = Math.pow( 2, - level );
28856                 const width = Math.floor( texture.image.width * levelScale );
28857                 const height = Math.floor( texture.image.height * levelScale );
28858                 const glFormat = utils.convert( texture.format );
28859
28860                 textures.setTexture2D( texture, 0 );
28861
28862                 _gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
28863
28864                 state.unbindTexture();
28865
28866         };
28867
28868         this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
28869
28870                 const width = srcTexture.image.width;
28871                 const height = srcTexture.image.height;
28872                 const glFormat = utils.convert( dstTexture.format );
28873                 const glType = utils.convert( dstTexture.type );
28874
28875                 textures.setTexture2D( dstTexture, 0 );
28876
28877                 // As another texture upload may have changed pixelStorei
28878                 // parameters, make sure they are correct for the dstTexture
28879                 _gl.pixelStorei( 37440, dstTexture.flipY );
28880                 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
28881                 _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
28882
28883                 if ( srcTexture.isDataTexture ) {
28884
28885                         _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
28886
28887                 } else {
28888
28889                         if ( srcTexture.isCompressedTexture ) {
28890
28891                                 _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
28892
28893                         } else {
28894
28895                                 _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
28896
28897                         }
28898
28899                 }
28900
28901                 // Generate mipmaps only when copying level 0
28902                 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
28903
28904                 state.unbindTexture();
28905
28906         };
28907
28908         this.initTexture = function ( texture ) {
28909
28910                 textures.setTexture2D( texture, 0 );
28911
28912                 state.unbindTexture();
28913
28914         };
28915
28916         this.resetState = function () {
28917
28918                 state.reset();
28919                 bindingStates.reset();
28920
28921         };
28922
28923         if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
28924
28925                 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
28926
28927         }
28928
28929     }
28930
28931     function WebGL1Renderer( parameters ) {
28932
28933         WebGLRenderer.call( this, parameters );
28934
28935     }
28936
28937     WebGL1Renderer.prototype = Object.assign( Object.create( WebGLRenderer.prototype ), {
28938
28939         constructor: WebGL1Renderer,
28940
28941         isWebGL1Renderer: true
28942
28943     } );
28944
28945     class Scene extends Object3D {
28946
28947         constructor() {
28948
28949                 super();
28950
28951                 Object.defineProperty( this, 'isScene', { value: true } );
28952
28953                 this.type = 'Scene';
28954
28955                 this.background = null;
28956                 this.environment = null;
28957                 this.fog = null;
28958
28959                 this.overrideMaterial = null;
28960
28961                 this.autoUpdate = true; // checked by the renderer
28962
28963                 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
28964
28965                         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
28966
28967                 }
28968
28969         }
28970
28971         copy( source, recursive ) {
28972
28973                 super.copy( source, recursive );
28974
28975                 if ( source.background !== null ) this.background = source.background.clone();
28976                 if ( source.environment !== null ) this.environment = source.environment.clone();
28977                 if ( source.fog !== null ) this.fog = source.fog.clone();
28978
28979                 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
28980
28981                 this.autoUpdate = source.autoUpdate;
28982                 this.matrixAutoUpdate = source.matrixAutoUpdate;
28983
28984                 return this;
28985
28986         }
28987
28988         toJSON( meta ) {
28989
28990                 const data = super.toJSON( meta );
28991
28992                 if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
28993                 if ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );
28994                 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
28995
28996                 return data;
28997
28998         }
28999
29000     }
29001
29002     function InterleavedBuffer( array, stride ) {
29003
29004         this.array = array;
29005         this.stride = stride;
29006         this.count = array !== undefined ? array.length / stride : 0;
29007
29008         this.usage = StaticDrawUsage;
29009         this.updateRange = { offset: 0, count: - 1 };
29010
29011         this.version = 0;
29012
29013         this.uuid = MathUtils.generateUUID();
29014
29015     }
29016
29017     Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
29018
29019         set: function ( value ) {
29020
29021                 if ( value === true ) this.version ++;
29022
29023         }
29024
29025     } );
29026
29027     Object.assign( InterleavedBuffer.prototype, {
29028
29029         isInterleavedBuffer: true,
29030
29031         onUploadCallback: function () {},
29032
29033         setUsage: function ( value ) {
29034
29035                 this.usage = value;
29036
29037                 return this;
29038
29039         },
29040
29041         copy: function ( source ) {
29042
29043                 this.array = new source.array.constructor( source.array );
29044                 this.count = source.count;
29045                 this.stride = source.stride;
29046                 this.usage = source.usage;
29047
29048                 return this;
29049
29050         },
29051
29052         copyAt: function ( index1, attribute, index2 ) {
29053
29054                 index1 *= this.stride;
29055                 index2 *= attribute.stride;
29056
29057                 for ( let i = 0, l = this.stride; i < l; i ++ ) {
29058
29059                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
29060
29061                 }
29062
29063                 return this;
29064
29065         },
29066
29067         set: function ( value, offset = 0 ) {
29068
29069                 this.array.set( value, offset );
29070
29071                 return this;
29072
29073         },
29074
29075         clone: function ( data ) {
29076
29077                 if ( data.arrayBuffers === undefined ) {
29078
29079                         data.arrayBuffers = {};
29080
29081                 }
29082
29083                 if ( this.array.buffer._uuid === undefined ) {
29084
29085                         this.array.buffer._uuid = MathUtils.generateUUID();
29086
29087                 }
29088
29089                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
29090
29091                         data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
29092
29093                 }
29094
29095                 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
29096
29097                 const ib = new InterleavedBuffer( array, this.stride );
29098                 ib.setUsage( this.usage );
29099
29100                 return ib;
29101
29102         },
29103
29104         onUpload: function ( callback ) {
29105
29106                 this.onUploadCallback = callback;
29107
29108                 return this;
29109
29110         },
29111
29112         toJSON: function ( data ) {
29113
29114                 if ( data.arrayBuffers === undefined ) {
29115
29116                         data.arrayBuffers = {};
29117
29118                 }
29119
29120                 // generate UUID for array buffer if necessary
29121
29122                 if ( this.array.buffer._uuid === undefined ) {
29123
29124                         this.array.buffer._uuid = MathUtils.generateUUID();
29125
29126                 }
29127
29128                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
29129
29130                         data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
29131
29132                 }
29133
29134                 //
29135
29136                 return {
29137                         uuid: this.uuid,
29138                         buffer: this.array.buffer._uuid,
29139                         type: this.array.constructor.name,
29140                         stride: this.stride
29141                 };
29142
29143         }
29144
29145     } );
29146
29147     const _vector$6 = new Vector3();
29148
29149     function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
29150
29151         this.name = '';
29152
29153         this.data = interleavedBuffer;
29154         this.itemSize = itemSize;
29155         this.offset = offset;
29156
29157         this.normalized = normalized === true;
29158
29159     }
29160
29161     Object.defineProperties( InterleavedBufferAttribute.prototype, {
29162
29163         count: {
29164
29165                 get: function () {
29166
29167                         return this.data.count;
29168
29169                 }
29170
29171         },
29172
29173         array: {
29174
29175                 get: function () {
29176
29177                         return this.data.array;
29178
29179                 }
29180
29181         },
29182
29183         needsUpdate: {
29184
29185                 set: function ( value ) {
29186
29187                         this.data.needsUpdate = value;
29188
29189                 }
29190
29191         }
29192
29193     } );
29194
29195     Object.assign( InterleavedBufferAttribute.prototype, {
29196
29197         isInterleavedBufferAttribute: true,
29198
29199         applyMatrix4: function ( m ) {
29200
29201                 for ( let i = 0, l = this.data.count; i < l; i ++ ) {
29202
29203                         _vector$6.x = this.getX( i );
29204                         _vector$6.y = this.getY( i );
29205                         _vector$6.z = this.getZ( i );
29206
29207                         _vector$6.applyMatrix4( m );
29208
29209                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
29210
29211                 }
29212
29213                 return this;
29214
29215         },
29216
29217         setX: function ( index, x ) {
29218
29219                 this.data.array[ index * this.data.stride + this.offset ] = x;
29220
29221                 return this;
29222
29223         },
29224
29225         setY: function ( index, y ) {
29226
29227                 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
29228
29229                 return this;
29230
29231         },
29232
29233         setZ: function ( index, z ) {
29234
29235                 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
29236
29237                 return this;
29238
29239         },
29240
29241         setW: function ( index, w ) {
29242
29243                 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
29244
29245                 return this;
29246
29247         },
29248
29249         getX: function ( index ) {
29250
29251                 return this.data.array[ index * this.data.stride + this.offset ];
29252
29253         },
29254
29255         getY: function ( index ) {
29256
29257                 return this.data.array[ index * this.data.stride + this.offset + 1 ];
29258
29259         },
29260
29261         getZ: function ( index ) {
29262
29263                 return this.data.array[ index * this.data.stride + this.offset + 2 ];
29264
29265         },
29266
29267         getW: function ( index ) {
29268
29269                 return this.data.array[ index * this.data.stride + this.offset + 3 ];
29270
29271         },
29272
29273         setXY: function ( index, x, y ) {
29274
29275                 index = index * this.data.stride + this.offset;
29276
29277                 this.data.array[ index + 0 ] = x;
29278                 this.data.array[ index + 1 ] = y;
29279
29280                 return this;
29281
29282         },
29283
29284         setXYZ: function ( index, x, y, z ) {
29285
29286                 index = index * this.data.stride + this.offset;
29287
29288                 this.data.array[ index + 0 ] = x;
29289                 this.data.array[ index + 1 ] = y;
29290                 this.data.array[ index + 2 ] = z;
29291
29292                 return this;
29293
29294         },
29295
29296         setXYZW: function ( index, x, y, z, w ) {
29297
29298                 index = index * this.data.stride + this.offset;
29299
29300                 this.data.array[ index + 0 ] = x;
29301                 this.data.array[ index + 1 ] = y;
29302                 this.data.array[ index + 2 ] = z;
29303                 this.data.array[ index + 3 ] = w;
29304
29305                 return this;
29306
29307         },
29308
29309         clone: function ( data ) {
29310
29311                 if ( data === undefined ) {
29312
29313                         console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.' );
29314
29315                         const array = [];
29316
29317                         for ( let i = 0; i < this.count; i ++ ) {
29318
29319                                 const index = i * this.data.stride + this.offset;
29320
29321                                 for ( let j = 0; j < this.itemSize; j ++ ) {
29322
29323                                         array.push( this.data.array[ index + j ] );
29324
29325                                 }
29326
29327                         }
29328
29329                         return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
29330
29331                 } else {
29332
29333                         if ( data.interleavedBuffers === undefined ) {
29334
29335                                 data.interleavedBuffers = {};
29336
29337                         }
29338
29339                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
29340
29341                                 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
29342
29343                         }
29344
29345                         return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
29346
29347                 }
29348
29349         },
29350
29351         toJSON: function ( data ) {
29352
29353                 if ( data === undefined ) {
29354
29355                         console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
29356
29357                         const array = [];
29358
29359                         for ( let i = 0; i < this.count; i ++ ) {
29360
29361                                 const index = i * this.data.stride + this.offset;
29362
29363                                 for ( let j = 0; j < this.itemSize; j ++ ) {
29364
29365                                         array.push( this.data.array[ index + j ] );
29366
29367                                 }
29368
29369                         }
29370
29371                         // deinterleave data and save it as an ordinary buffer attribute for now
29372
29373                         return {
29374                                 itemSize: this.itemSize,
29375                                 type: this.array.constructor.name,
29376                                 array: array,
29377                                 normalized: this.normalized
29378                         };
29379
29380                 } else {
29381
29382                         // save as true interlaved attribtue
29383
29384                         if ( data.interleavedBuffers === undefined ) {
29385
29386                                 data.interleavedBuffers = {};
29387
29388                         }
29389
29390                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
29391
29392                                 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
29393
29394                         }
29395
29396                         return {
29397                                 isInterleavedBufferAttribute: true,
29398                                 itemSize: this.itemSize,
29399                                 data: this.data.uuid,
29400                                 offset: this.offset,
29401                                 normalized: this.normalized
29402                         };
29403
29404                 }
29405
29406         }
29407
29408     } );
29409
29410     /**
29411      * parameters = {
29412      *  color: <hex>,
29413      *  map: new THREE.Texture( <Image> ),
29414      *  alphaMap: new THREE.Texture( <Image> ),
29415      *  rotation: <float>,
29416      *  sizeAttenuation: <bool>
29417      * }
29418      */
29419
29420     function SpriteMaterial( parameters ) {
29421
29422         Material.call( this );
29423
29424         this.type = 'SpriteMaterial';
29425
29426         this.color = new Color( 0xffffff );
29427
29428         this.map = null;
29429
29430         this.alphaMap = null;
29431
29432         this.rotation = 0;
29433
29434         this.sizeAttenuation = true;
29435
29436         this.transparent = true;
29437
29438         this.setValues( parameters );
29439
29440     }
29441
29442     SpriteMaterial.prototype = Object.create( Material.prototype );
29443     SpriteMaterial.prototype.constructor = SpriteMaterial;
29444     SpriteMaterial.prototype.isSpriteMaterial = true;
29445
29446     SpriteMaterial.prototype.copy = function ( source ) {
29447
29448         Material.prototype.copy.call( this, source );
29449
29450         this.color.copy( source.color );
29451
29452         this.map = source.map;
29453
29454         this.alphaMap = source.alphaMap;
29455
29456         this.rotation = source.rotation;
29457
29458         this.sizeAttenuation = source.sizeAttenuation;
29459
29460         return this;
29461
29462     };
29463
29464     let _geometry;
29465
29466     const _intersectPoint = new Vector3();
29467     const _worldScale = new Vector3();
29468     const _mvPosition = new Vector3();
29469
29470     const _alignedPosition = new Vector2();
29471     const _rotatedPosition = new Vector2();
29472     const _viewWorldMatrix = new Matrix4();
29473
29474     const _vA$1 = new Vector3();
29475     const _vB$1 = new Vector3();
29476     const _vC$1 = new Vector3();
29477
29478     const _uvA$1 = new Vector2();
29479     const _uvB$1 = new Vector2();
29480     const _uvC$1 = new Vector2();
29481
29482     function Sprite( material ) {
29483
29484         Object3D.call( this );
29485
29486         this.type = 'Sprite';
29487
29488         if ( _geometry === undefined ) {
29489
29490                 _geometry = new BufferGeometry();
29491
29492                 const float32Array = new Float32Array( [
29493                         - 0.5, - 0.5, 0, 0, 0,
29494                         0.5, - 0.5, 0, 1, 0,
29495                         0.5, 0.5, 0, 1, 1,
29496                         - 0.5, 0.5, 0, 0, 1
29497                 ] );
29498
29499                 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
29500
29501                 _geometry.setIndex( [ 0, 1, 2,  0, 2, 3 ] );
29502                 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
29503                 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
29504
29505         }
29506
29507         this.geometry = _geometry;
29508         this.material = ( material !== undefined ) ? material : new SpriteMaterial();
29509
29510         this.center = new Vector2( 0.5, 0.5 );
29511
29512     }
29513
29514     Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
29515
29516         constructor: Sprite,
29517
29518         isSprite: true,
29519
29520         raycast: function ( raycaster, intersects ) {
29521
29522                 if ( raycaster.camera === null ) {
29523
29524                         console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
29525
29526                 }
29527
29528                 _worldScale.setFromMatrixScale( this.matrixWorld );
29529
29530                 _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
29531                 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
29532
29533                 _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
29534
29535                 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
29536
29537                         _worldScale.multiplyScalar( - _mvPosition.z );
29538
29539                 }
29540
29541                 const rotation = this.material.rotation;
29542                 let sin, cos;
29543
29544                 if ( rotation !== 0 ) {
29545
29546                         cos = Math.cos( rotation );
29547                         sin = Math.sin( rotation );
29548
29549                 }
29550
29551                 const center = this.center;
29552
29553                 transformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
29554                 transformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
29555                 transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
29556
29557                 _uvA$1.set( 0, 0 );
29558                 _uvB$1.set( 1, 0 );
29559                 _uvC$1.set( 1, 1 );
29560
29561                 // check first triangle
29562                 let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
29563
29564                 if ( intersect === null ) {
29565
29566                         // check second triangle
29567                         transformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
29568                         _uvB$1.set( 0, 1 );
29569
29570                         intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
29571                         if ( intersect === null ) {
29572
29573                                 return;
29574
29575                         }
29576
29577                 }
29578
29579                 const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
29580
29581                 if ( distance < raycaster.near || distance > raycaster.far ) return;
29582
29583                 intersects.push( {
29584
29585                         distance: distance,
29586                         point: _intersectPoint.clone(),
29587                         uv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),
29588                         face: null,
29589                         object: this
29590
29591                 } );
29592
29593         },
29594
29595         copy: function ( source ) {
29596
29597                 Object3D.prototype.copy.call( this, source );
29598
29599                 if ( source.center !== undefined ) this.center.copy( source.center );
29600
29601                 this.material = source.material;
29602
29603                 return this;
29604
29605         }
29606
29607     } );
29608
29609     function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
29610
29611         // compute position in camera space
29612         _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
29613
29614         // to check if rotation is not zero
29615         if ( sin !== undefined ) {
29616
29617                 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
29618                 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
29619
29620         } else {
29621
29622                 _rotatedPosition.copy( _alignedPosition );
29623
29624         }
29625
29626
29627         vertexPosition.copy( mvPosition );
29628         vertexPosition.x += _rotatedPosition.x;
29629         vertexPosition.y += _rotatedPosition.y;
29630
29631         // transform to world space
29632         vertexPosition.applyMatrix4( _viewWorldMatrix );
29633
29634     }
29635
29636     const _v1$4 = new Vector3();
29637     const _v2$2 = new Vector3();
29638
29639     function LOD() {
29640
29641         Object3D.call( this );
29642
29643         this._currentLevel = 0;
29644
29645         this.type = 'LOD';
29646
29647         Object.defineProperties( this, {
29648                 levels: {
29649                         enumerable: true,
29650                         value: []
29651                 }
29652         } );
29653
29654         this.autoUpdate = true;
29655
29656     }
29657
29658     LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
29659
29660         constructor: LOD,
29661
29662         isLOD: true,
29663
29664         copy: function ( source ) {
29665
29666                 Object3D.prototype.copy.call( this, source, false );
29667
29668                 const levels = source.levels;
29669
29670                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
29671
29672                         const level = levels[ i ];
29673
29674                         this.addLevel( level.object.clone(), level.distance );
29675
29676                 }
29677
29678                 this.autoUpdate = source.autoUpdate;
29679
29680                 return this;
29681
29682         },
29683
29684         addLevel: function ( object, distance = 0 ) {
29685
29686                 distance = Math.abs( distance );
29687
29688                 const levels = this.levels;
29689
29690                 let l;
29691
29692                 for ( l = 0; l < levels.length; l ++ ) {
29693
29694                         if ( distance < levels[ l ].distance ) {
29695
29696                                 break;
29697
29698                         }
29699
29700                 }
29701
29702                 levels.splice( l, 0, { distance: distance, object: object } );
29703
29704                 this.add( object );
29705
29706                 return this;
29707
29708         },
29709
29710         getCurrentLevel: function () {
29711
29712                 return this._currentLevel;
29713
29714         },
29715
29716         getObjectForDistance: function ( distance ) {
29717
29718                 const levels = this.levels;
29719
29720                 if ( levels.length > 0 ) {
29721
29722                         let i, l;
29723
29724                         for ( i = 1, l = levels.length; i < l; i ++ ) {
29725
29726                                 if ( distance < levels[ i ].distance ) {
29727
29728                                         break;
29729
29730                                 }
29731
29732                         }
29733
29734                         return levels[ i - 1 ].object;
29735
29736                 }
29737
29738                 return null;
29739
29740         },
29741
29742         raycast: function ( raycaster, intersects ) {
29743
29744                 const levels = this.levels;
29745
29746                 if ( levels.length > 0 ) {
29747
29748                         _v1$4.setFromMatrixPosition( this.matrixWorld );
29749
29750                         const distance = raycaster.ray.origin.distanceTo( _v1$4 );
29751
29752                         this.getObjectForDistance( distance ).raycast( raycaster, intersects );
29753
29754                 }
29755
29756         },
29757
29758         update: function ( camera ) {
29759
29760                 const levels = this.levels;
29761
29762                 if ( levels.length > 1 ) {
29763
29764                         _v1$4.setFromMatrixPosition( camera.matrixWorld );
29765                         _v2$2.setFromMatrixPosition( this.matrixWorld );
29766
29767                         const distance = _v1$4.distanceTo( _v2$2 ) / camera.zoom;
29768
29769                         levels[ 0 ].object.visible = true;
29770
29771                         let i, l;
29772
29773                         for ( i = 1, l = levels.length; i < l; i ++ ) {
29774
29775                                 if ( distance >= levels[ i ].distance ) {
29776
29777                                         levels[ i - 1 ].object.visible = false;
29778                                         levels[ i ].object.visible = true;
29779
29780                                 } else {
29781
29782                                         break;
29783
29784                                 }
29785
29786                         }
29787
29788                         this._currentLevel = i - 1;
29789
29790                         for ( ; i < l; i ++ ) {
29791
29792                                 levels[ i ].object.visible = false;
29793
29794                         }
29795
29796                 }
29797
29798         },
29799
29800         toJSON: function ( meta ) {
29801
29802                 const data = Object3D.prototype.toJSON.call( this, meta );
29803
29804                 if ( this.autoUpdate === false ) data.object.autoUpdate = false;
29805
29806                 data.object.levels = [];
29807
29808                 const levels = this.levels;
29809
29810                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
29811
29812                         const level = levels[ i ];
29813
29814                         data.object.levels.push( {
29815                                 object: level.object.uuid,
29816                                 distance: level.distance
29817                         } );
29818
29819                 }
29820
29821                 return data;
29822
29823         }
29824
29825     } );
29826
29827     const _basePosition = new Vector3();
29828
29829     const _skinIndex = new Vector4();
29830     const _skinWeight = new Vector4();
29831
29832     const _vector$7 = new Vector3();
29833     const _matrix$1 = new Matrix4();
29834
29835     function SkinnedMesh( geometry, material ) {
29836
29837         if ( geometry && geometry.isGeometry ) {
29838
29839                 console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
29840
29841         }
29842
29843         Mesh.call( this, geometry, material );
29844
29845         this.type = 'SkinnedMesh';
29846
29847         this.bindMode = 'attached';
29848         this.bindMatrix = new Matrix4();
29849         this.bindMatrixInverse = new Matrix4();
29850
29851     }
29852
29853     SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
29854
29855         constructor: SkinnedMesh,
29856
29857         isSkinnedMesh: true,
29858
29859         copy: function ( source ) {
29860
29861                 Mesh.prototype.copy.call( this, source );
29862
29863                 this.bindMode = source.bindMode;
29864                 this.bindMatrix.copy( source.bindMatrix );
29865                 this.bindMatrixInverse.copy( source.bindMatrixInverse );
29866
29867                 this.skeleton = source.skeleton;
29868
29869                 return this;
29870
29871         },
29872
29873         bind: function ( skeleton, bindMatrix ) {
29874
29875                 this.skeleton = skeleton;
29876
29877                 if ( bindMatrix === undefined ) {
29878
29879                         this.updateMatrixWorld( true );
29880
29881                         this.skeleton.calculateInverses();
29882
29883                         bindMatrix = this.matrixWorld;
29884
29885                 }
29886
29887                 this.bindMatrix.copy( bindMatrix );
29888                 this.bindMatrixInverse.copy( bindMatrix ).invert();
29889
29890         },
29891
29892         pose: function () {
29893
29894                 this.skeleton.pose();
29895
29896         },
29897
29898         normalizeSkinWeights: function () {
29899
29900                 const vector = new Vector4();
29901
29902                 const skinWeight = this.geometry.attributes.skinWeight;
29903
29904                 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
29905
29906                         vector.x = skinWeight.getX( i );
29907                         vector.y = skinWeight.getY( i );
29908                         vector.z = skinWeight.getZ( i );
29909                         vector.w = skinWeight.getW( i );
29910
29911                         const scale = 1.0 / vector.manhattanLength();
29912
29913                         if ( scale !== Infinity ) {
29914
29915                                 vector.multiplyScalar( scale );
29916
29917                         } else {
29918
29919                                 vector.set( 1, 0, 0, 0 ); // do something reasonable
29920
29921                         }
29922
29923                         skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
29924
29925                 }
29926
29927         },
29928
29929         updateMatrixWorld: function ( force ) {
29930
29931                 Mesh.prototype.updateMatrixWorld.call( this, force );
29932
29933                 if ( this.bindMode === 'attached' ) {
29934
29935                         this.bindMatrixInverse.copy( this.matrixWorld ).invert();
29936
29937                 } else if ( this.bindMode === 'detached' ) {
29938
29939                         this.bindMatrixInverse.copy( this.bindMatrix ).invert();
29940
29941                 } else {
29942
29943                         console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
29944
29945                 }
29946
29947         },
29948
29949         boneTransform: function ( index, target ) {
29950
29951                 const skeleton = this.skeleton;
29952                 const geometry = this.geometry;
29953
29954                 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
29955                 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
29956
29957                 _basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
29958
29959                 target.set( 0, 0, 0 );
29960
29961                 for ( let i = 0; i < 4; i ++ ) {
29962
29963                         const weight = _skinWeight.getComponent( i );
29964
29965                         if ( weight !== 0 ) {
29966
29967                                 const boneIndex = _skinIndex.getComponent( i );
29968
29969                                 _matrix$1.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
29970
29971                                 target.addScaledVector( _vector$7.copy( _basePosition ).applyMatrix4( _matrix$1 ), weight );
29972
29973                         }
29974
29975                 }
29976
29977                 return target.applyMatrix4( this.bindMatrixInverse );
29978
29979         }
29980
29981     } );
29982
29983     function Bone() {
29984
29985         Object3D.call( this );
29986
29987         this.type = 'Bone';
29988
29989     }
29990
29991     Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
29992
29993         constructor: Bone,
29994
29995         isBone: true
29996
29997     } );
29998
29999     const _offsetMatrix = new Matrix4();
30000     const _identityMatrix = new Matrix4();
30001
30002     function Skeleton( bones = [], boneInverses = [] ) {
30003
30004         this.uuid = MathUtils.generateUUID();
30005
30006         this.bones = bones.slice( 0 );
30007         this.boneInverses = boneInverses;
30008         this.boneMatrices = null;
30009
30010         this.boneTexture = null;
30011         this.boneTextureSize = 0;
30012
30013         this.frame = - 1;
30014
30015         this.init();
30016
30017     }
30018
30019     Object.assign( Skeleton.prototype, {
30020
30021         init: function () {
30022
30023                 const bones = this.bones;
30024                 const boneInverses = this.boneInverses;
30025
30026                 this.boneMatrices = new Float32Array( bones.length * 16 );
30027
30028                 // calculate inverse bone matrices if necessary
30029
30030                 if ( boneInverses.length === 0 ) {
30031
30032                         this.calculateInverses();
30033
30034                 } else {
30035
30036                         // handle special case
30037
30038                         if ( bones.length !== boneInverses.length ) {
30039
30040                                 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
30041
30042                                 this.boneInverses = [];
30043
30044                                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30045
30046                                         this.boneInverses.push( new Matrix4() );
30047
30048                                 }
30049
30050                         }
30051
30052                 }
30053
30054         },
30055
30056         calculateInverses: function () {
30057
30058                 this.boneInverses.length = 0;
30059
30060                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30061
30062                         const inverse = new Matrix4();
30063
30064                         if ( this.bones[ i ] ) {
30065
30066                                 inverse.copy( this.bones[ i ].matrixWorld ).invert();
30067
30068                         }
30069
30070                         this.boneInverses.push( inverse );
30071
30072                 }
30073
30074         },
30075
30076         pose: function () {
30077
30078                 // recover the bind-time world matrices
30079
30080                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30081
30082                         const bone = this.bones[ i ];
30083
30084                         if ( bone ) {
30085
30086                                 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
30087
30088                         }
30089
30090                 }
30091
30092                 // compute the local matrices, positions, rotations and scales
30093
30094                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30095
30096                         const bone = this.bones[ i ];
30097
30098                         if ( bone ) {
30099
30100                                 if ( bone.parent && bone.parent.isBone ) {
30101
30102                                         bone.matrix.copy( bone.parent.matrixWorld ).invert();
30103                                         bone.matrix.multiply( bone.matrixWorld );
30104
30105                                 } else {
30106
30107                                         bone.matrix.copy( bone.matrixWorld );
30108
30109                                 }
30110
30111                                 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
30112
30113                         }
30114
30115                 }
30116
30117         },
30118
30119         update: function () {
30120
30121                 const bones = this.bones;
30122                 const boneInverses = this.boneInverses;
30123                 const boneMatrices = this.boneMatrices;
30124                 const boneTexture = this.boneTexture;
30125
30126                 // flatten bone matrices to array
30127
30128                 for ( let i = 0, il = bones.length; i < il; i ++ ) {
30129
30130                         // compute the offset between the current and the original transform
30131
30132                         const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
30133
30134                         _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
30135                         _offsetMatrix.toArray( boneMatrices, i * 16 );
30136
30137                 }
30138
30139                 if ( boneTexture !== null ) {
30140
30141                         boneTexture.needsUpdate = true;
30142
30143                 }
30144
30145         },
30146
30147         clone: function () {
30148
30149                 return new Skeleton( this.bones, this.boneInverses );
30150
30151         },
30152
30153         getBoneByName: function ( name ) {
30154
30155                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30156
30157                         const bone = this.bones[ i ];
30158
30159                         if ( bone.name === name ) {
30160
30161                                 return bone;
30162
30163                         }
30164
30165                 }
30166
30167                 return undefined;
30168
30169         },
30170
30171         dispose: function ( ) {
30172
30173                 if ( this.boneTexture !== null ) {
30174
30175                         this.boneTexture.dispose();
30176
30177                         this.boneTexture = null;
30178
30179                 }
30180
30181         },
30182
30183         fromJSON: function ( json, bones ) {
30184
30185                 this.uuid = json.uuid;
30186
30187                 for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
30188
30189                         const uuid = json.bones[ i ];
30190                         let bone = bones[ uuid ];
30191
30192                         if ( bone === undefined ) {
30193
30194                                 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
30195                                 bone = new Bone();
30196
30197                         }
30198
30199                         this.bones.push( bone );
30200                         this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
30201
30202                 }
30203
30204                 this.init();
30205
30206                 return this;
30207
30208         },
30209
30210         toJSON: function () {
30211
30212                 const data = {
30213                         metadata: {
30214                                 version: 4.5,
30215                                 type: 'Skeleton',
30216                                 generator: 'Skeleton.toJSON'
30217                         },
30218                         bones: [],
30219                         boneInverses: []
30220                 };
30221
30222                 data.uuid = this.uuid;
30223
30224                 const bones = this.bones;
30225                 const boneInverses = this.boneInverses;
30226
30227                 for ( let i = 0, l = bones.length; i < l; i ++ ) {
30228
30229                         const bone = bones[ i ];
30230                         data.bones.push( bone.uuid );
30231
30232                         const boneInverse = boneInverses[ i ];
30233                         data.boneInverses.push( boneInverse.toArray() );
30234
30235                 }
30236
30237                 return data;
30238
30239         }
30240
30241     } );
30242
30243     const _instanceLocalMatrix = new Matrix4();
30244     const _instanceWorldMatrix = new Matrix4();
30245
30246     const _instanceIntersects = [];
30247
30248     const _mesh = new Mesh();
30249
30250     function InstancedMesh( geometry, material, count ) {
30251
30252         Mesh.call( this, geometry, material );
30253
30254         this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
30255         this.instanceColor = null;
30256
30257         this.count = count;
30258
30259         this.frustumCulled = false;
30260
30261     }
30262
30263     InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
30264
30265         constructor: InstancedMesh,
30266
30267         isInstancedMesh: true,
30268
30269         copy: function ( source ) {
30270
30271                 Mesh.prototype.copy.call( this, source );
30272
30273                 this.instanceMatrix.copy( source.instanceMatrix );
30274
30275                 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
30276
30277                 this.count = source.count;
30278
30279                 return this;
30280
30281         },
30282
30283         getColorAt: function ( index, color ) {
30284
30285                 color.fromArray( this.instanceColor.array, index * 3 );
30286
30287         },
30288
30289         getMatrixAt: function ( index, matrix ) {
30290
30291                 matrix.fromArray( this.instanceMatrix.array, index * 16 );
30292
30293         },
30294
30295         raycast: function ( raycaster, intersects ) {
30296
30297                 const matrixWorld = this.matrixWorld;
30298                 const raycastTimes = this.count;
30299
30300                 _mesh.geometry = this.geometry;
30301                 _mesh.material = this.material;
30302
30303                 if ( _mesh.material === undefined ) return;
30304
30305                 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
30306
30307                         // calculate the world matrix for each instance
30308
30309                         this.getMatrixAt( instanceId, _instanceLocalMatrix );
30310
30311                         _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
30312
30313                         // the mesh represents this single instance
30314
30315                         _mesh.matrixWorld = _instanceWorldMatrix;
30316
30317                         _mesh.raycast( raycaster, _instanceIntersects );
30318
30319                         // process the result of raycast
30320
30321                         for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
30322
30323                                 const intersect = _instanceIntersects[ i ];
30324                                 intersect.instanceId = instanceId;
30325                                 intersect.object = this;
30326                                 intersects.push( intersect );
30327
30328                         }
30329
30330                         _instanceIntersects.length = 0;
30331
30332                 }
30333
30334         },
30335
30336         setColorAt: function ( index, color ) {
30337
30338                 if ( this.instanceColor === null ) {
30339
30340                         this.instanceColor = new BufferAttribute( new Float32Array( this.count * 3 ), 3 );
30341
30342                 }
30343
30344                 color.toArray( this.instanceColor.array, index * 3 );
30345
30346         },
30347
30348         setMatrixAt: function ( index, matrix ) {
30349
30350                 matrix.toArray( this.instanceMatrix.array, index * 16 );
30351
30352         },
30353
30354         updateMorphTargets: function () {
30355
30356         },
30357
30358         dispose: function () {
30359
30360                 this.dispatchEvent( { type: 'dispose' } );
30361
30362         }
30363
30364     } );
30365
30366     /**
30367      * parameters = {
30368      *  color: <hex>,
30369      *  opacity: <float>,
30370      *
30371      *  linewidth: <float>,
30372      *  linecap: "round",
30373      *  linejoin: "round"
30374      * }
30375      */
30376
30377     function LineBasicMaterial( parameters ) {
30378
30379         Material.call( this );
30380
30381         this.type = 'LineBasicMaterial';
30382
30383         this.color = new Color( 0xffffff );
30384
30385         this.linewidth = 1;
30386         this.linecap = 'round';
30387         this.linejoin = 'round';
30388
30389         this.morphTargets = false;
30390
30391         this.setValues( parameters );
30392
30393     }
30394
30395     LineBasicMaterial.prototype = Object.create( Material.prototype );
30396     LineBasicMaterial.prototype.constructor = LineBasicMaterial;
30397
30398     LineBasicMaterial.prototype.isLineBasicMaterial = true;
30399
30400     LineBasicMaterial.prototype.copy = function ( source ) {
30401
30402         Material.prototype.copy.call( this, source );
30403
30404         this.color.copy( source.color );
30405
30406         this.linewidth = source.linewidth;
30407         this.linecap = source.linecap;
30408         this.linejoin = source.linejoin;
30409
30410         this.morphTargets = source.morphTargets;
30411
30412         return this;
30413
30414     };
30415
30416     const _start = new Vector3();
30417     const _end = new Vector3();
30418     const _inverseMatrix$1 = new Matrix4();
30419     const _ray$1 = new Ray();
30420     const _sphere$2 = new Sphere();
30421
30422     function Line( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
30423
30424         Object3D.call( this );
30425
30426         this.type = 'Line';
30427
30428         this.geometry = geometry;
30429         this.material = material;
30430
30431         this.updateMorphTargets();
30432
30433     }
30434
30435     Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
30436
30437         constructor: Line,
30438
30439         isLine: true,
30440
30441         copy: function ( source ) {
30442
30443                 Object3D.prototype.copy.call( this, source );
30444
30445                 this.material = source.material;
30446                 this.geometry = source.geometry;
30447
30448                 return this;
30449
30450         },
30451
30452         computeLineDistances: function () {
30453
30454                 const geometry = this.geometry;
30455
30456                 if ( geometry.isBufferGeometry ) {
30457
30458                         // we assume non-indexed geometry
30459
30460                         if ( geometry.index === null ) {
30461
30462                                 const positionAttribute = geometry.attributes.position;
30463                                 const lineDistances = [ 0 ];
30464
30465                                 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
30466
30467                                         _start.fromBufferAttribute( positionAttribute, i - 1 );
30468                                         _end.fromBufferAttribute( positionAttribute, i );
30469
30470                                         lineDistances[ i ] = lineDistances[ i - 1 ];
30471                                         lineDistances[ i ] += _start.distanceTo( _end );
30472
30473                                 }
30474
30475                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
30476
30477                         } else {
30478
30479                                 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
30480
30481                         }
30482
30483                 } else if ( geometry.isGeometry ) {
30484
30485                         console.error( 'THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
30486
30487                 }
30488
30489                 return this;
30490
30491         },
30492
30493         raycast: function ( raycaster, intersects ) {
30494
30495                 const geometry = this.geometry;
30496                 const matrixWorld = this.matrixWorld;
30497                 const threshold = raycaster.params.Line.threshold;
30498
30499                 // Checking boundingSphere distance to ray
30500
30501                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
30502
30503                 _sphere$2.copy( geometry.boundingSphere );
30504                 _sphere$2.applyMatrix4( matrixWorld );
30505                 _sphere$2.radius += threshold;
30506
30507                 if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return;
30508
30509                 //
30510
30511                 _inverseMatrix$1.copy( matrixWorld ).invert();
30512                 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
30513
30514                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
30515                 const localThresholdSq = localThreshold * localThreshold;
30516
30517                 const vStart = new Vector3();
30518                 const vEnd = new Vector3();
30519                 const interSegment = new Vector3();
30520                 const interRay = new Vector3();
30521                 const step = this.isLineSegments ? 2 : 1;
30522
30523                 if ( geometry.isBufferGeometry ) {
30524
30525                         const index = geometry.index;
30526                         const attributes = geometry.attributes;
30527                         const positionAttribute = attributes.position;
30528
30529                         if ( index !== null ) {
30530
30531                                 const indices = index.array;
30532
30533                                 for ( let i = 0, l = indices.length - 1; i < l; i += step ) {
30534
30535                                         const a = indices[ i ];
30536                                         const b = indices[ i + 1 ];
30537
30538                                         vStart.fromBufferAttribute( positionAttribute, a );
30539                                         vEnd.fromBufferAttribute( positionAttribute, b );
30540
30541                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
30542
30543                                         if ( distSq > localThresholdSq ) continue;
30544
30545                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
30546
30547                                         const distance = raycaster.ray.origin.distanceTo( interRay );
30548
30549                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
30550
30551                                         intersects.push( {
30552
30553                                                 distance: distance,
30554                                                 // What do we want? intersection point on the ray or on the segment??
30555                                                 // point: raycaster.ray.at( distance ),
30556                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
30557                                                 index: i,
30558                                                 face: null,
30559                                                 faceIndex: null,
30560                                                 object: this
30561
30562                                         } );
30563
30564                                 }
30565
30566                         } else {
30567
30568                                 for ( let i = 0, l = positionAttribute.count - 1; i < l; i += step ) {
30569
30570                                         vStart.fromBufferAttribute( positionAttribute, i );
30571                                         vEnd.fromBufferAttribute( positionAttribute, i + 1 );
30572
30573                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
30574
30575                                         if ( distSq > localThresholdSq ) continue;
30576
30577                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
30578
30579                                         const distance = raycaster.ray.origin.distanceTo( interRay );
30580
30581                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
30582
30583                                         intersects.push( {
30584
30585                                                 distance: distance,
30586                                                 // What do we want? intersection point on the ray or on the segment??
30587                                                 // point: raycaster.ray.at( distance ),
30588                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
30589                                                 index: i,
30590                                                 face: null,
30591                                                 faceIndex: null,
30592                                                 object: this
30593
30594                                         } );
30595
30596                                 }
30597
30598                         }
30599
30600                 } else if ( geometry.isGeometry ) {
30601
30602                         console.error( 'THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
30603
30604                 }
30605
30606         },
30607
30608         updateMorphTargets: function () {
30609
30610                 const geometry = this.geometry;
30611
30612                 if ( geometry.isBufferGeometry ) {
30613
30614                         const morphAttributes = geometry.morphAttributes;
30615                         const keys = Object.keys( morphAttributes );
30616
30617                         if ( keys.length > 0 ) {
30618
30619                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
30620
30621                                 if ( morphAttribute !== undefined ) {
30622
30623                                         this.morphTargetInfluences = [];
30624                                         this.morphTargetDictionary = {};
30625
30626                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
30627
30628                                                 const name = morphAttribute[ m ].name || String( m );
30629
30630                                                 this.morphTargetInfluences.push( 0 );
30631                                                 this.morphTargetDictionary[ name ] = m;
30632
30633                                         }
30634
30635                                 }
30636
30637                         }
30638
30639                 } else {
30640
30641                         const morphTargets = geometry.morphTargets;
30642
30643                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
30644
30645                                 console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
30646
30647                         }
30648
30649                 }
30650
30651         }
30652
30653     } );
30654
30655     const _start$1 = new Vector3();
30656     const _end$1 = new Vector3();
30657
30658     function LineSegments( geometry, material ) {
30659
30660         Line.call( this, geometry, material );
30661
30662         this.type = 'LineSegments';
30663
30664     }
30665
30666     LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
30667
30668         constructor: LineSegments,
30669
30670         isLineSegments: true,
30671
30672         computeLineDistances: function () {
30673
30674                 const geometry = this.geometry;
30675
30676                 if ( geometry.isBufferGeometry ) {
30677
30678                         // we assume non-indexed geometry
30679
30680                         if ( geometry.index === null ) {
30681
30682                                 const positionAttribute = geometry.attributes.position;
30683                                 const lineDistances = [];
30684
30685                                 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
30686
30687                                         _start$1.fromBufferAttribute( positionAttribute, i );
30688                                         _end$1.fromBufferAttribute( positionAttribute, i + 1 );
30689
30690                                         lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
30691                                         lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
30692
30693                                 }
30694
30695                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
30696
30697                         } else {
30698
30699                                 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
30700
30701                         }
30702
30703                 } else if ( geometry.isGeometry ) {
30704
30705                         console.error( 'THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
30706
30707                 }
30708
30709                 return this;
30710
30711         }
30712
30713     } );
30714
30715     function LineLoop( geometry, material ) {
30716
30717         Line.call( this, geometry, material );
30718
30719         this.type = 'LineLoop';
30720
30721     }
30722
30723     LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
30724
30725         constructor: LineLoop,
30726
30727         isLineLoop: true,
30728
30729     } );
30730
30731     /**
30732      * parameters = {
30733      *  color: <hex>,
30734      *  opacity: <float>,
30735      *  map: new THREE.Texture( <Image> ),
30736      *  alphaMap: new THREE.Texture( <Image> ),
30737      *
30738      *  size: <float>,
30739      *  sizeAttenuation: <bool>
30740      *
30741      *  morphTargets: <bool>
30742      * }
30743      */
30744
30745     function PointsMaterial( parameters ) {
30746
30747         Material.call( this );
30748
30749         this.type = 'PointsMaterial';
30750
30751         this.color = new Color( 0xffffff );
30752
30753         this.map = null;
30754
30755         this.alphaMap = null;
30756
30757         this.size = 1;
30758         this.sizeAttenuation = true;
30759
30760         this.morphTargets = false;
30761
30762         this.setValues( parameters );
30763
30764     }
30765
30766     PointsMaterial.prototype = Object.create( Material.prototype );
30767     PointsMaterial.prototype.constructor = PointsMaterial;
30768
30769     PointsMaterial.prototype.isPointsMaterial = true;
30770
30771     PointsMaterial.prototype.copy = function ( source ) {
30772
30773         Material.prototype.copy.call( this, source );
30774
30775         this.color.copy( source.color );
30776
30777         this.map = source.map;
30778
30779         this.alphaMap = source.alphaMap;
30780
30781         this.size = source.size;
30782         this.sizeAttenuation = source.sizeAttenuation;
30783
30784         this.morphTargets = source.morphTargets;
30785
30786         return this;
30787
30788     };
30789
30790     const _inverseMatrix$2 = new Matrix4();
30791     const _ray$2 = new Ray();
30792     const _sphere$3 = new Sphere();
30793     const _position$1 = new Vector3();
30794
30795     function Points( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
30796
30797         Object3D.call( this );
30798
30799         this.type = 'Points';
30800
30801         this.geometry = geometry;
30802         this.material = material;
30803
30804         this.updateMorphTargets();
30805
30806     }
30807
30808     Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
30809
30810         constructor: Points,
30811
30812         isPoints: true,
30813
30814         copy: function ( source ) {
30815
30816                 Object3D.prototype.copy.call( this, source );
30817
30818                 this.material = source.material;
30819                 this.geometry = source.geometry;
30820
30821                 return this;
30822
30823         },
30824
30825         raycast: function ( raycaster, intersects ) {
30826
30827                 const geometry = this.geometry;
30828                 const matrixWorld = this.matrixWorld;
30829                 const threshold = raycaster.params.Points.threshold;
30830
30831                 // Checking boundingSphere distance to ray
30832
30833                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
30834
30835                 _sphere$3.copy( geometry.boundingSphere );
30836                 _sphere$3.applyMatrix4( matrixWorld );
30837                 _sphere$3.radius += threshold;
30838
30839                 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
30840
30841                 //
30842
30843                 _inverseMatrix$2.copy( matrixWorld ).invert();
30844                 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
30845
30846                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
30847                 const localThresholdSq = localThreshold * localThreshold;
30848
30849                 if ( geometry.isBufferGeometry ) {
30850
30851                         const index = geometry.index;
30852                         const attributes = geometry.attributes;
30853                         const positionAttribute = attributes.position;
30854
30855                         if ( index !== null ) {
30856
30857                                 const indices = index.array;
30858
30859                                 for ( let i = 0, il = indices.length; i < il; i ++ ) {
30860
30861                                         const a = indices[ i ];
30862
30863                                         _position$1.fromBufferAttribute( positionAttribute, a );
30864
30865                                         testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
30866
30867                                 }
30868
30869                         } else {
30870
30871                                 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
30872
30873                                         _position$1.fromBufferAttribute( positionAttribute, i );
30874
30875                                         testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
30876
30877                                 }
30878
30879                         }
30880
30881                 } else {
30882
30883                         console.error( 'THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
30884
30885                 }
30886
30887         },
30888
30889         updateMorphTargets: function () {
30890
30891                 const geometry = this.geometry;
30892
30893                 if ( geometry.isBufferGeometry ) {
30894
30895                         const morphAttributes = geometry.morphAttributes;
30896                         const keys = Object.keys( morphAttributes );
30897
30898                         if ( keys.length > 0 ) {
30899
30900                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
30901
30902                                 if ( morphAttribute !== undefined ) {
30903
30904                                         this.morphTargetInfluences = [];
30905                                         this.morphTargetDictionary = {};
30906
30907                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
30908
30909                                                 const name = morphAttribute[ m ].name || String( m );
30910
30911                                                 this.morphTargetInfluences.push( 0 );
30912                                                 this.morphTargetDictionary[ name ] = m;
30913
30914                                         }
30915
30916                                 }
30917
30918                         }
30919
30920                 } else {
30921
30922                         const morphTargets = geometry.morphTargets;
30923
30924                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
30925
30926                                 console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
30927
30928                         }
30929
30930                 }
30931
30932         }
30933
30934     } );
30935
30936     function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
30937
30938         const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
30939
30940         if ( rayPointDistanceSq < localThresholdSq ) {
30941
30942                 const intersectPoint = new Vector3();
30943
30944                 _ray$2.closestPointToPoint( point, intersectPoint );
30945                 intersectPoint.applyMatrix4( matrixWorld );
30946
30947                 const distance = raycaster.ray.origin.distanceTo( intersectPoint );
30948
30949                 if ( distance < raycaster.near || distance > raycaster.far ) return;
30950
30951                 intersects.push( {
30952
30953                         distance: distance,
30954                         distanceToRay: Math.sqrt( rayPointDistanceSq ),
30955                         point: intersectPoint,
30956                         index: index,
30957                         face: null,
30958                         object: object
30959
30960                 } );
30961
30962         }
30963
30964     }
30965
30966     function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
30967
30968         Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
30969
30970         this.format = format !== undefined ? format : RGBFormat;
30971
30972         this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
30973         this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
30974
30975         this.generateMipmaps = false;
30976
30977         const scope = this;
30978
30979         function updateVideo() {
30980
30981                 scope.needsUpdate = true;
30982                 video.requestVideoFrameCallback( updateVideo );
30983
30984         }
30985
30986         if ( 'requestVideoFrameCallback' in video ) {
30987
30988                 video.requestVideoFrameCallback( updateVideo );
30989
30990         }
30991
30992     }
30993
30994     VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
30995
30996         constructor: VideoTexture,
30997
30998         clone: function () {
30999
31000                 return new this.constructor( this.image ).copy( this );
31001
31002         },
31003
31004         isVideoTexture: true,
31005
31006         update: function () {
31007
31008                 const video = this.image;
31009                 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
31010
31011                 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
31012
31013                         this.needsUpdate = true;
31014
31015                 }
31016
31017         }
31018
31019     } );
31020
31021     function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
31022
31023         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
31024
31025         this.image = { width: width, height: height };
31026         this.mipmaps = mipmaps;
31027
31028         // no flipping for cube textures
31029         // (also flipping doesn't work for compressed textures )
31030
31031         this.flipY = false;
31032
31033         // can't generate mipmaps for compressed textures
31034         // mips must be embedded in DDS files
31035
31036         this.generateMipmaps = false;
31037
31038     }
31039
31040     CompressedTexture.prototype = Object.create( Texture.prototype );
31041     CompressedTexture.prototype.constructor = CompressedTexture;
31042
31043     CompressedTexture.prototype.isCompressedTexture = true;
31044
31045     function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
31046
31047         Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31048
31049         this.needsUpdate = true;
31050
31051     }
31052
31053     CanvasTexture.prototype = Object.create( Texture.prototype );
31054     CanvasTexture.prototype.constructor = CanvasTexture;
31055     CanvasTexture.prototype.isCanvasTexture = true;
31056
31057     function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
31058
31059         format = format !== undefined ? format : DepthFormat;
31060
31061         if ( format !== DepthFormat && format !== DepthStencilFormat ) {
31062
31063                 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
31064
31065         }
31066
31067         if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
31068         if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
31069
31070         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31071
31072         this.image = { width: width, height: height };
31073
31074         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
31075         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
31076
31077         this.flipY = false;
31078         this.generateMipmaps = false;
31079
31080     }
31081
31082     DepthTexture.prototype = Object.create( Texture.prototype );
31083     DepthTexture.prototype.constructor = DepthTexture;
31084     DepthTexture.prototype.isDepthTexture = true;
31085
31086     class CircleGeometry extends BufferGeometry {
31087
31088         constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
31089
31090                 super();
31091
31092                 this.type = 'CircleGeometry';
31093
31094                 this.parameters = {
31095                         radius: radius,
31096                         segments: segments,
31097                         thetaStart: thetaStart,
31098                         thetaLength: thetaLength
31099                 };
31100
31101                 segments = Math.max( 3, segments );
31102
31103                 // buffers
31104
31105                 const indices = [];
31106                 const vertices = [];
31107                 const normals = [];
31108                 const uvs = [];
31109
31110                 // helper variables
31111
31112                 const vertex = new Vector3();
31113                 const uv = new Vector2();
31114
31115                 // center point
31116
31117                 vertices.push( 0, 0, 0 );
31118                 normals.push( 0, 0, 1 );
31119                 uvs.push( 0.5, 0.5 );
31120
31121                 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
31122
31123                         const segment = thetaStart + s / segments * thetaLength;
31124
31125                         // vertex
31126
31127                         vertex.x = radius * Math.cos( segment );
31128                         vertex.y = radius * Math.sin( segment );
31129
31130                         vertices.push( vertex.x, vertex.y, vertex.z );
31131
31132                         // normal
31133
31134                         normals.push( 0, 0, 1 );
31135
31136                         // uvs
31137
31138                         uv.x = ( vertices[ i ] / radius + 1 ) / 2;
31139                         uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
31140
31141                         uvs.push( uv.x, uv.y );
31142
31143                 }
31144
31145                 // indices
31146
31147                 for ( let i = 1; i <= segments; i ++ ) {
31148
31149                         indices.push( i, i + 1, 0 );
31150
31151                 }
31152
31153                 // build geometry
31154
31155                 this.setIndex( indices );
31156                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31157                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31158                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31159
31160         }
31161
31162     }
31163
31164     new Vector3();
31165     new Vector3();
31166     new Vector3();
31167     new Triangle();
31168
31169     /**
31170      * Port from https://github.com/mapbox/earcut (v2.2.2)
31171      */
31172
31173     const Earcut = {
31174
31175         triangulate: function ( data, holeIndices, dim ) {
31176
31177                 dim = dim || 2;
31178
31179                 const hasHoles = holeIndices && holeIndices.length;
31180                 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
31181                 let outerNode = linkedList$1( data, 0, outerLen, dim, true );
31182                 const triangles = [];
31183
31184                 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
31185
31186                 let minX, minY, maxX, maxY, x, y, invSize;
31187
31188                 if ( hasHoles ) outerNode = eliminateHoles$1( data, holeIndices, outerNode, dim );
31189
31190                 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
31191                 if ( data.length > 80 * dim ) {
31192
31193                         minX = maxX = data[ 0 ];
31194                         minY = maxY = data[ 1 ];
31195
31196                         for ( let i = dim; i < outerLen; i += dim ) {
31197
31198                                 x = data[ i ];
31199                                 y = data[ i + 1 ];
31200                                 if ( x < minX ) minX = x;
31201                                 if ( y < minY ) minY = y;
31202                                 if ( x > maxX ) maxX = x;
31203                                 if ( y > maxY ) maxY = y;
31204
31205                         }
31206
31207                         // minX, minY and invSize are later used to transform coords into integers for z-order calculation
31208                         invSize = Math.max( maxX - minX, maxY - minY );
31209                         invSize = invSize !== 0 ? 1 / invSize : 0;
31210
31211                 }
31212
31213                 earcutLinked$1( outerNode, triangles, dim, minX, minY, invSize );
31214
31215                 return triangles;
31216
31217         }
31218
31219     };
31220
31221     // create a circular doubly linked list from polygon points in the specified winding order
31222     function linkedList$1( data, start, end, dim, clockwise ) {
31223
31224         let i, last;
31225
31226         if ( clockwise === ( signedArea$2( data, start, end, dim ) > 0 ) ) {
31227
31228                 for ( i = start; i < end; i += dim ) last = insertNode$2( i, data[ i ], data[ i + 1 ], last );
31229
31230         } else {
31231
31232                 for ( i = end - dim; i >= start; i -= dim ) last = insertNode$2( i, data[ i ], data[ i + 1 ], last );
31233
31234         }
31235
31236         if ( last && equals$2( last, last.next ) ) {
31237
31238                 removeNode$2( last );
31239                 last = last.next;
31240
31241         }
31242
31243         return last;
31244
31245     }
31246
31247     // eliminate colinear or duplicate points
31248     function filterPoints$1( start, end ) {
31249
31250         if ( ! start ) return start;
31251         if ( ! end ) end = start;
31252
31253         let p = start,
31254                 again;
31255         do {
31256
31257                 again = false;
31258
31259                 if ( ! p.steiner && ( equals$2( p, p.next ) || area$1( p.prev, p, p.next ) === 0 ) ) {
31260
31261                         removeNode$2( p );
31262                         p = end = p.prev;
31263                         if ( p === p.next ) break;
31264                         again = true;
31265
31266                 } else {
31267
31268                         p = p.next;
31269
31270                 }
31271
31272         } while ( again || p !== end );
31273
31274         return end;
31275
31276     }
31277
31278     // main ear slicing loop which triangulates a polygon (given as a linked list)
31279     function earcutLinked$1( ear, triangles, dim, minX, minY, invSize, pass ) {
31280
31281         if ( ! ear ) return;
31282
31283         // interlink polygon nodes in z-order
31284         if ( ! pass && invSize ) indexCurve$1( ear, minX, minY, invSize );
31285
31286         let stop = ear,
31287                 prev, next;
31288
31289         // iterate through ears, slicing them one by one
31290         while ( ear.prev !== ear.next ) {
31291
31292                 prev = ear.prev;
31293                 next = ear.next;
31294
31295                 if ( invSize ? isEarHashed$1( ear, minX, minY, invSize ) : isEar$1( ear ) ) {
31296
31297                         // cut off the triangle
31298                         triangles.push( prev.i / dim );
31299                         triangles.push( ear.i / dim );
31300                         triangles.push( next.i / dim );
31301
31302                         removeNode$2( ear );
31303
31304                         // skipping the next vertex leads to less sliver triangles
31305                         ear = next.next;
31306                         stop = next.next;
31307
31308                         continue;
31309
31310                 }
31311
31312                 ear = next;
31313
31314                 // if we looped through the whole remaining polygon and can't find any more ears
31315                 if ( ear === stop ) {
31316
31317                         // try filtering points and slicing again
31318                         if ( ! pass ) {
31319
31320                                 earcutLinked$1( filterPoints$1( ear ), triangles, dim, minX, minY, invSize, 1 );
31321
31322                                 // if this didn't work, try curing all small self-intersections locally
31323
31324                         } else if ( pass === 1 ) {
31325
31326                                 ear = cureLocalIntersections$1( filterPoints$1( ear ), triangles, dim );
31327                                 earcutLinked$1( ear, triangles, dim, minX, minY, invSize, 2 );
31328
31329                                 // as a last resort, try splitting the remaining polygon into two
31330
31331                         } else if ( pass === 2 ) {
31332
31333                                 splitEarcut$1( ear, triangles, dim, minX, minY, invSize );
31334
31335                         }
31336
31337                         break;
31338
31339                 }
31340
31341         }
31342
31343     }
31344
31345     // check whether a polygon node forms a valid ear with adjacent nodes
31346     function isEar$1( ear ) {
31347
31348         const a = ear.prev,
31349                 b = ear,
31350                 c = ear.next;
31351
31352         if ( area$1( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
31353
31354         // now make sure we don't have other points inside the potential ear
31355         let p = ear.next.next;
31356
31357         while ( p !== ear.prev ) {
31358
31359                 if ( pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
31360                         area$1( p.prev, p, p.next ) >= 0 ) return false;
31361                 p = p.next;
31362
31363         }
31364
31365         return true;
31366
31367     }
31368
31369     function isEarHashed$1( ear, minX, minY, invSize ) {
31370
31371         const a = ear.prev,
31372                 b = ear,
31373                 c = ear.next;
31374
31375         if ( area$1( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
31376
31377         // triangle bbox; min & max are calculated like this for speed
31378         const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
31379                 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
31380                 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
31381                 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
31382
31383         // z-order range for the current triangle bbox;
31384         const minZ = zOrder$1( minTX, minTY, minX, minY, invSize ),
31385                 maxZ = zOrder$1( maxTX, maxTY, minX, minY, invSize );
31386
31387         let p = ear.prevZ,
31388                 n = ear.nextZ;
31389
31390         // look for points inside the triangle in both directions
31391         while ( p && p.z >= minZ && n && n.z <= maxZ ) {
31392
31393                 if ( p !== ear.prev && p !== ear.next &&
31394                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
31395                         area$1( p.prev, p, p.next ) >= 0 ) return false;
31396                 p = p.prevZ;
31397
31398                 if ( n !== ear.prev && n !== ear.next &&
31399                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
31400                         area$1( n.prev, n, n.next ) >= 0 ) return false;
31401                 n = n.nextZ;
31402
31403         }
31404
31405         // look for remaining points in decreasing z-order
31406         while ( p && p.z >= minZ ) {
31407
31408                 if ( p !== ear.prev && p !== ear.next &&
31409                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
31410                         area$1( p.prev, p, p.next ) >= 0 ) return false;
31411                 p = p.prevZ;
31412
31413         }
31414
31415         // look for remaining points in increasing z-order
31416         while ( n && n.z <= maxZ ) {
31417
31418                 if ( n !== ear.prev && n !== ear.next &&
31419                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
31420                         area$1( n.prev, n, n.next ) >= 0 ) return false;
31421                 n = n.nextZ;
31422
31423         }
31424
31425         return true;
31426
31427     }
31428
31429     // go through all polygon nodes and cure small local self-intersections
31430     function cureLocalIntersections$1( start, triangles, dim ) {
31431
31432         let p = start;
31433         do {
31434
31435                 const a = p.prev,
31436                         b = p.next.next;
31437
31438                 if ( ! equals$2( a, b ) && intersects$2( a, p, p.next, b ) && locallyInside$1( a, b ) && locallyInside$1( b, a ) ) {
31439
31440                         triangles.push( a.i / dim );
31441                         triangles.push( p.i / dim );
31442                         triangles.push( b.i / dim );
31443
31444                         // remove two nodes involved
31445                         removeNode$2( p );
31446                         removeNode$2( p.next );
31447
31448                         p = start = b;
31449
31450                 }
31451
31452                 p = p.next;
31453
31454         } while ( p !== start );
31455
31456         return filterPoints$1( p );
31457
31458     }
31459
31460     // try splitting polygon into two and triangulate them independently
31461     function splitEarcut$1( start, triangles, dim, minX, minY, invSize ) {
31462
31463         // look for a valid diagonal that divides the polygon into two
31464         let a = start;
31465         do {
31466
31467                 let b = a.next.next;
31468                 while ( b !== a.prev ) {
31469
31470                         if ( a.i !== b.i && isValidDiagonal$1( a, b ) ) {
31471
31472                                 // split the polygon in two by the diagonal
31473                                 let c = splitPolygon$1( a, b );
31474
31475                                 // filter colinear points around the cuts
31476                                 a = filterPoints$1( a, a.next );
31477                                 c = filterPoints$1( c, c.next );
31478
31479                                 // run earcut on each half
31480                                 earcutLinked$1( a, triangles, dim, minX, minY, invSize );
31481                                 earcutLinked$1( c, triangles, dim, minX, minY, invSize );
31482                                 return;
31483
31484                         }
31485
31486                         b = b.next;
31487
31488                 }
31489
31490                 a = a.next;
31491
31492         } while ( a !== start );
31493
31494     }
31495
31496     // link every hole into the outer loop, producing a single-ring polygon without holes
31497     function eliminateHoles$1( data, holeIndices, outerNode, dim ) {
31498
31499         const queue = [];
31500         let i, len, start, end, list;
31501
31502         for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
31503
31504                 start = holeIndices[ i ] * dim;
31505                 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
31506                 list = linkedList$1( data, start, end, dim, false );
31507                 if ( list === list.next ) list.steiner = true;
31508                 queue.push( getLeftmost$1( list ) );
31509
31510         }
31511
31512         queue.sort( compareX$1 );
31513
31514         // process holes from left to right
31515         for ( i = 0; i < queue.length; i ++ ) {
31516
31517                 eliminateHole$1( queue[ i ], outerNode );
31518                 outerNode = filterPoints$1( outerNode, outerNode.next );
31519
31520         }
31521
31522         return outerNode;
31523
31524     }
31525
31526     function compareX$1( a, b ) {
31527
31528         return a.x - b.x;
31529
31530     }
31531
31532     // find a bridge between vertices that connects hole with an outer ring and and link it
31533     function eliminateHole$1( hole, outerNode ) {
31534
31535         outerNode = findHoleBridge$1( hole, outerNode );
31536         if ( outerNode ) {
31537
31538                 const b = splitPolygon$1( outerNode, hole );
31539
31540                 // filter collinear points around the cuts
31541                 filterPoints$1( outerNode, outerNode.next );
31542                 filterPoints$1( b, b.next );
31543
31544         }
31545
31546     }
31547
31548     // David Eberly's algorithm for finding a bridge between hole and outer polygon
31549     function findHoleBridge$1( hole, outerNode ) {
31550
31551         let p = outerNode;
31552         const hx = hole.x;
31553         const hy = hole.y;
31554         let qx = - Infinity, m;
31555
31556         // find a segment intersected by a ray from the hole's leftmost point to the left;
31557         // segment's endpoint with lesser x will be potential connection point
31558         do {
31559
31560                 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
31561
31562                         const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
31563                         if ( x <= hx && x > qx ) {
31564
31565                                 qx = x;
31566                                 if ( x === hx ) {
31567
31568                                         if ( hy === p.y ) return p;
31569                                         if ( hy === p.next.y ) return p.next;
31570
31571                                 }
31572
31573                                 m = p.x < p.next.x ? p : p.next;
31574
31575                         }
31576
31577                 }
31578
31579                 p = p.next;
31580
31581         } while ( p !== outerNode );
31582
31583         if ( ! m ) return null;
31584
31585         if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
31586
31587         // look for points inside the triangle of hole point, segment intersection and endpoint;
31588         // if there are no points found, we have a valid connection;
31589         // otherwise choose the point of the minimum angle with the ray as connection point
31590
31591         const stop = m,
31592                 mx = m.x,
31593                 my = m.y;
31594         let tanMin = Infinity, tan;
31595
31596         p = m;
31597
31598         do {
31599
31600                 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
31601                                 pointInTriangle$1( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
31602
31603                         tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
31604
31605                         if ( locallyInside$1( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector$1( m, p ) ) ) ) ) ) {
31606
31607                                 m = p;
31608                                 tanMin = tan;
31609
31610                         }
31611
31612                 }
31613
31614                 p = p.next;
31615
31616         } while ( p !== stop );
31617
31618         return m;
31619
31620     }
31621
31622     // whether sector in vertex m contains sector in vertex p in the same coordinates
31623     function sectorContainsSector$1( m, p ) {
31624
31625         return area$1( m.prev, m, p.prev ) < 0 && area$1( p.next, m, m.next ) < 0;
31626
31627     }
31628
31629     // interlink polygon nodes in z-order
31630     function indexCurve$1( start, minX, minY, invSize ) {
31631
31632         let p = start;
31633         do {
31634
31635                 if ( p.z === null ) p.z = zOrder$1( p.x, p.y, minX, minY, invSize );
31636                 p.prevZ = p.prev;
31637                 p.nextZ = p.next;
31638                 p = p.next;
31639
31640         } while ( p !== start );
31641
31642         p.prevZ.nextZ = null;
31643         p.prevZ = null;
31644
31645         sortLinked$1( p );
31646
31647     }
31648
31649     // Simon Tatham's linked list merge sort algorithm
31650     // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
31651     function sortLinked$1( list ) {
31652
31653         let i, p, q, e, tail, numMerges, pSize, qSize,
31654                 inSize = 1;
31655
31656         do {
31657
31658                 p = list;
31659                 list = null;
31660                 tail = null;
31661                 numMerges = 0;
31662
31663                 while ( p ) {
31664
31665                         numMerges ++;
31666                         q = p;
31667                         pSize = 0;
31668                         for ( i = 0; i < inSize; i ++ ) {
31669
31670                                 pSize ++;
31671                                 q = q.nextZ;
31672                                 if ( ! q ) break;
31673
31674                         }
31675
31676                         qSize = inSize;
31677
31678                         while ( pSize > 0 || ( qSize > 0 && q ) ) {
31679
31680                                 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
31681
31682                                         e = p;
31683                                         p = p.nextZ;
31684                                         pSize --;
31685
31686                                 } else {
31687
31688                                         e = q;
31689                                         q = q.nextZ;
31690                                         qSize --;
31691
31692                                 }
31693
31694                                 if ( tail ) tail.nextZ = e;
31695                                 else list = e;
31696
31697                                 e.prevZ = tail;
31698                                 tail = e;
31699
31700                         }
31701
31702                         p = q;
31703
31704                 }
31705
31706                 tail.nextZ = null;
31707                 inSize *= 2;
31708
31709         } while ( numMerges > 1 );
31710
31711         return list;
31712
31713     }
31714
31715     // z-order of a point given coords and inverse of the longer side of data bbox
31716     function zOrder$1( x, y, minX, minY, invSize ) {
31717
31718         // coords are transformed into non-negative 15-bit integer range
31719         x = 32767 * ( x - minX ) * invSize;
31720         y = 32767 * ( y - minY ) * invSize;
31721
31722         x = ( x | ( x << 8 ) ) & 0x00FF00FF;
31723         x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
31724         x = ( x | ( x << 2 ) ) & 0x33333333;
31725         x = ( x | ( x << 1 ) ) & 0x55555555;
31726
31727         y = ( y | ( y << 8 ) ) & 0x00FF00FF;
31728         y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
31729         y = ( y | ( y << 2 ) ) & 0x33333333;
31730         y = ( y | ( y << 1 ) ) & 0x55555555;
31731
31732         return x | ( y << 1 );
31733
31734     }
31735
31736     // find the leftmost node of a polygon ring
31737     function getLeftmost$1( start ) {
31738
31739         let p = start,
31740                 leftmost = start;
31741         do {
31742
31743                 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
31744                 p = p.next;
31745
31746         } while ( p !== start );
31747
31748         return leftmost;
31749
31750     }
31751
31752     // check if a point lies within a convex triangle
31753     function pointInTriangle$1( ax, ay, bx, by, cx, cy, px, py ) {
31754
31755         return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
31756                         ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
31757                         ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
31758
31759     }
31760
31761     // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
31762     function isValidDiagonal$1( a, b ) {
31763
31764         return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon$1( a, b ) && // dones't intersect other edges
31765                 ( locallyInside$1( a, b ) && locallyInside$1( b, a ) && middleInside$1( a, b ) && // locally visible
31766                 ( area$1( a.prev, a, b.prev ) || area$1( a, b.prev, b ) ) || // does not create opposite-facing sectors
31767                 equals$2( a, b ) && area$1( a.prev, a, a.next ) > 0 && area$1( b.prev, b, b.next ) > 0 ); // special zero-length case
31768
31769     }
31770
31771     // signed area of a triangle
31772     function area$1( p, q, r ) {
31773
31774         return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
31775
31776     }
31777
31778     // check if two points are equal
31779     function equals$2( p1, p2 ) {
31780
31781         return p1.x === p2.x && p1.y === p2.y;
31782
31783     }
31784
31785     // check if two segments intersect
31786     function intersects$2( p1, q1, p2, q2 ) {
31787
31788         const o1 = sign$2( area$1( p1, q1, p2 ) );
31789         const o2 = sign$2( area$1( p1, q1, q2 ) );
31790         const o3 = sign$2( area$1( p2, q2, p1 ) );
31791         const o4 = sign$2( area$1( p2, q2, q1 ) );
31792
31793         if ( o1 !== o2 && o3 !== o4 ) return true; // general case
31794
31795         if ( o1 === 0 && onSegment$1( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
31796         if ( o2 === 0 && onSegment$1( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
31797         if ( o3 === 0 && onSegment$1( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
31798         if ( o4 === 0 && onSegment$1( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
31799
31800         return false;
31801
31802     }
31803
31804     // for collinear points p, q, r, check if point q lies on segment pr
31805     function onSegment$1( p, q, r ) {
31806
31807         return q.x <= Math.max( p.x, r.x ) && q.x >= Math.min( p.x, r.x ) && q.y <= Math.max( p.y, r.y ) && q.y >= Math.min( p.y, r.y );
31808
31809     }
31810
31811     function sign$2( num ) {
31812
31813         return num > 0 ? 1 : num < 0 ? - 1 : 0;
31814
31815     }
31816
31817     // check if a polygon diagonal intersects any polygon segments
31818     function intersectsPolygon$1( a, b ) {
31819
31820         let p = a;
31821         do {
31822
31823                 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
31824                                 intersects$2( p, p.next, a, b ) ) return true;
31825                 p = p.next;
31826
31827         } while ( p !== a );
31828
31829         return false;
31830
31831     }
31832
31833     // check if a polygon diagonal is locally inside the polygon
31834     function locallyInside$1( a, b ) {
31835
31836         return area$1( a.prev, a, a.next ) < 0 ?
31837                 area$1( a, b, a.next ) >= 0 && area$1( a, a.prev, b ) >= 0 :
31838                 area$1( a, b, a.prev ) < 0 || area$1( a, a.next, b ) < 0;
31839
31840     }
31841
31842     // check if the middle point of a polygon diagonal is inside the polygon
31843     function middleInside$1( a, b ) {
31844
31845         let p = a,
31846                 inside = false;
31847         const px = ( a.x + b.x ) / 2,
31848                 py = ( a.y + b.y ) / 2;
31849         do {
31850
31851                 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
31852                                 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
31853                         inside = ! inside;
31854                 p = p.next;
31855
31856         } while ( p !== a );
31857
31858         return inside;
31859
31860     }
31861
31862     // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
31863     // if one belongs to the outer ring and another to a hole, it merges it into a single ring
31864     function splitPolygon$1( a, b ) {
31865
31866         const a2 = new Node$1( a.i, a.x, a.y ),
31867                 b2 = new Node$1( b.i, b.x, b.y ),
31868                 an = a.next,
31869                 bp = b.prev;
31870
31871         a.next = b;
31872         b.prev = a;
31873
31874         a2.next = an;
31875         an.prev = a2;
31876
31877         b2.next = a2;
31878         a2.prev = b2;
31879
31880         bp.next = b2;
31881         b2.prev = bp;
31882
31883         return b2;
31884
31885     }
31886
31887     // create a node and optionally link it with previous one (in a circular doubly linked list)
31888     function insertNode$2( i, x, y, last ) {
31889
31890         const p = new Node$1( i, x, y );
31891
31892         if ( ! last ) {
31893
31894                 p.prev = p;
31895                 p.next = p;
31896
31897         } else {
31898
31899                 p.next = last.next;
31900                 p.prev = last;
31901                 last.next.prev = p;
31902                 last.next = p;
31903
31904         }
31905
31906         return p;
31907
31908     }
31909
31910     function removeNode$2( p ) {
31911
31912         p.next.prev = p.prev;
31913         p.prev.next = p.next;
31914
31915         if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
31916         if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
31917
31918     }
31919
31920     function Node$1( i, x, y ) {
31921
31922         // vertex index in coordinates array
31923         this.i = i;
31924
31925         // vertex coordinates
31926         this.x = x;
31927         this.y = y;
31928
31929         // previous and next vertex nodes in a polygon ring
31930         this.prev = null;
31931         this.next = null;
31932
31933         // z-order curve value
31934         this.z = null;
31935
31936         // previous and next nodes in z-order
31937         this.prevZ = null;
31938         this.nextZ = null;
31939
31940         // indicates whether this is a steiner point
31941         this.steiner = false;
31942
31943     }
31944
31945     function signedArea$2( data, start, end, dim ) {
31946
31947         let sum = 0;
31948         for ( let i = start, j = end - dim; i < end; i += dim ) {
31949
31950                 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
31951                 j = i;
31952
31953         }
31954
31955         return sum;
31956
31957     }
31958
31959     const ShapeUtils = {
31960
31961         // calculate area of the contour polygon
31962
31963         area: function ( contour ) {
31964
31965                 const n = contour.length;
31966                 let a = 0.0;
31967
31968                 for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
31969
31970                         a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
31971
31972                 }
31973
31974                 return a * 0.5;
31975
31976         },
31977
31978         isClockWise: function ( pts ) {
31979
31980                 return ShapeUtils.area( pts ) < 0;
31981
31982         },
31983
31984         triangulateShape: function ( contour, holes ) {
31985
31986                 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
31987                 const holeIndices = []; // array of hole indices
31988                 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
31989
31990                 removeDupEndPts( contour );
31991                 addContour( vertices, contour );
31992
31993                 //
31994
31995                 let holeIndex = contour.length;
31996
31997                 holes.forEach( removeDupEndPts );
31998
31999                 for ( let i = 0; i < holes.length; i ++ ) {
32000
32001                         holeIndices.push( holeIndex );
32002                         holeIndex += holes[ i ].length;
32003                         addContour( vertices, holes[ i ] );
32004
32005                 }
32006
32007                 //
32008
32009                 const triangles = Earcut.triangulate( vertices, holeIndices );
32010
32011                 //
32012
32013                 for ( let i = 0; i < triangles.length; i += 3 ) {
32014
32015                         faces.push( triangles.slice( i, i + 3 ) );
32016
32017                 }
32018
32019                 return faces;
32020
32021         }
32022
32023     };
32024
32025     function removeDupEndPts( points ) {
32026
32027         const l = points.length;
32028
32029         if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
32030
32031                 points.pop();
32032
32033         }
32034
32035     }
32036
32037     function addContour( vertices, contour ) {
32038
32039         for ( let i = 0; i < contour.length; i ++ ) {
32040
32041                 vertices.push( contour[ i ].x );
32042                 vertices.push( contour[ i ].y );
32043
32044         }
32045
32046     }
32047
32048     /**
32049      * Creates extruded geometry from a path shape.
32050      *
32051      * parameters = {
32052      *
32053      *  curveSegments: <int>, // number of points on the curves
32054      *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
32055      *  depth: <float>, // Depth to extrude the shape
32056      *
32057      *  bevelEnabled: <bool>, // turn on bevel
32058      *  bevelThickness: <float>, // how deep into the original shape bevel goes
32059      *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
32060      *  bevelOffset: <float>, // how far from shape outline does bevel start
32061      *  bevelSegments: <int>, // number of bevel layers
32062      *
32063      *  extrudePath: <THREE.Curve> // curve to extrude shape along
32064      *
32065      *  UVGenerator: <Object> // object that provides UV generator functions
32066      *
32067      * }
32068      */
32069
32070     class ExtrudeGeometry extends BufferGeometry {
32071
32072         constructor( shapes, options ) {
32073
32074                 super();
32075
32076                 this.type = 'ExtrudeGeometry';
32077
32078                 this.parameters = {
32079                         shapes: shapes,
32080                         options: options
32081                 };
32082
32083                 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
32084
32085                 const scope = this;
32086
32087                 const verticesArray = [];
32088                 const uvArray = [];
32089
32090                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
32091
32092                         const shape = shapes[ i ];
32093                         addShape( shape );
32094
32095                 }
32096
32097                 // build geometry
32098
32099                 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
32100                 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
32101
32102                 this.computeVertexNormals();
32103
32104                 // functions
32105
32106                 function addShape( shape ) {
32107
32108                         const placeholder = [];
32109
32110                         // options
32111
32112                         const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
32113                         const steps = options.steps !== undefined ? options.steps : 1;
32114                         let depth = options.depth !== undefined ? options.depth : 100;
32115
32116                         let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
32117                         let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
32118                         let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
32119                         let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
32120                         let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
32121
32122                         const extrudePath = options.extrudePath;
32123
32124                         const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
32125
32126                         // deprecated options
32127
32128                         if ( options.amount !== undefined ) {
32129
32130                                 console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
32131                                 depth = options.amount;
32132
32133                         }
32134
32135                         //
32136
32137                         let extrudePts, extrudeByPath = false;
32138                         let splineTube, binormal, normal, position2;
32139
32140                         if ( extrudePath ) {
32141
32142                                 extrudePts = extrudePath.getSpacedPoints( steps );
32143
32144                                 extrudeByPath = true;
32145                                 bevelEnabled = false; // bevels not supported for path extrusion
32146
32147                                 // SETUP TNB variables
32148
32149                                 // TODO1 - have a .isClosed in spline?
32150
32151                                 splineTube = extrudePath.computeFrenetFrames( steps, false );
32152
32153                                 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
32154
32155                                 binormal = new Vector3();
32156                                 normal = new Vector3();
32157                                 position2 = new Vector3();
32158
32159                         }
32160
32161                         // Safeguards if bevels are not enabled
32162
32163                         if ( ! bevelEnabled ) {
32164
32165                                 bevelSegments = 0;
32166                                 bevelThickness = 0;
32167                                 bevelSize = 0;
32168                                 bevelOffset = 0;
32169
32170                         }
32171
32172                         // Variables initialization
32173
32174                         const shapePoints = shape.extractPoints( curveSegments );
32175
32176                         let vertices = shapePoints.shape;
32177                         const holes = shapePoints.holes;
32178
32179                         const reverse = ! ShapeUtils.isClockWise( vertices );
32180
32181                         if ( reverse ) {
32182
32183                                 vertices = vertices.reverse();
32184
32185                                 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
32186
32187                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32188
32189                                         const ahole = holes[ h ];
32190
32191                                         if ( ShapeUtils.isClockWise( ahole ) ) {
32192
32193                                                 holes[ h ] = ahole.reverse();
32194
32195                                         }
32196
32197                                 }
32198
32199                         }
32200
32201
32202                         const faces = ShapeUtils.triangulateShape( vertices, holes );
32203
32204                         /* Vertices */
32205
32206                         const contour = vertices; // vertices has all points but contour has only points of circumference
32207
32208                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32209
32210                                 const ahole = holes[ h ];
32211
32212                                 vertices = vertices.concat( ahole );
32213
32214                         }
32215
32216
32217                         function scalePt2( pt, vec, size ) {
32218
32219                                 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
32220
32221                                 return vec.clone().multiplyScalar( size ).add( pt );
32222
32223                         }
32224
32225                         const vlen = vertices.length, flen = faces.length;
32226
32227
32228                         // Find directions for point movement
32229
32230
32231                         function getBevelVec( inPt, inPrev, inNext ) {
32232
32233                                 // computes for inPt the corresponding point inPt' on a new contour
32234                                 //   shifted by 1 unit (length of normalized vector) to the left
32235                                 // if we walk along contour clockwise, this new contour is outside the old one
32236                                 //
32237                                 // inPt' is the intersection of the two lines parallel to the two
32238                                 //  adjacent edges of inPt at a distance of 1 unit on the left side.
32239
32240                                 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
32241
32242                                 // good reading for geometry algorithms (here: line-line intersection)
32243                                 // http://geomalgorithms.com/a05-_intersect-1.html
32244
32245                                 const v_prev_x = inPt.x - inPrev.x,
32246                                         v_prev_y = inPt.y - inPrev.y;
32247                                 const v_next_x = inNext.x - inPt.x,
32248                                         v_next_y = inNext.y - inPt.y;
32249
32250                                 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
32251
32252                                 // check for collinear edges
32253                                 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
32254
32255                                 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
32256
32257                                         // not collinear
32258
32259                                         // length of vectors for normalizing
32260
32261                                         const v_prev_len = Math.sqrt( v_prev_lensq );
32262                                         const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
32263
32264                                         // shift adjacent points by unit vectors to the left
32265
32266                                         const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
32267                                         const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
32268
32269                                         const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
32270                                         const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
32271
32272                                         // scaling factor for v_prev to intersection point
32273
32274                                         const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
32275                                                         ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
32276                                                 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
32277
32278                                         // vector from inPt to intersection point
32279
32280                                         v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
32281                                         v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
32282
32283                                         // Don't normalize!, otherwise sharp corners become ugly
32284                                         //  but prevent crazy spikes
32285                                         const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
32286                                         if ( v_trans_lensq <= 2 ) {
32287
32288                                                 return new Vector2( v_trans_x, v_trans_y );
32289
32290                                         } else {
32291
32292                                                 shrink_by = Math.sqrt( v_trans_lensq / 2 );
32293
32294                                         }
32295
32296                                 } else {
32297
32298                                         // handle special case of collinear edges
32299
32300                                         let direction_eq = false; // assumes: opposite
32301
32302                                         if ( v_prev_x > Number.EPSILON ) {
32303
32304                                                 if ( v_next_x > Number.EPSILON ) {
32305
32306                                                         direction_eq = true;
32307
32308                                                 }
32309
32310                                         } else {
32311
32312                                                 if ( v_prev_x < - Number.EPSILON ) {
32313
32314                                                         if ( v_next_x < - Number.EPSILON ) {
32315
32316                                                                 direction_eq = true;
32317
32318                                                         }
32319
32320                                                 } else {
32321
32322                                                         if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
32323
32324                                                                 direction_eq = true;
32325
32326                                                         }
32327
32328                                                 }
32329
32330                                         }
32331
32332                                         if ( direction_eq ) {
32333
32334                                                 // console.log("Warning: lines are a straight sequence");
32335                                                 v_trans_x = - v_prev_y;
32336                                                 v_trans_y = v_prev_x;
32337                                                 shrink_by = Math.sqrt( v_prev_lensq );
32338
32339                                         } else {
32340
32341                                                 // console.log("Warning: lines are a straight spike");
32342                                                 v_trans_x = v_prev_x;
32343                                                 v_trans_y = v_prev_y;
32344                                                 shrink_by = Math.sqrt( v_prev_lensq / 2 );
32345
32346                                         }
32347
32348                                 }
32349
32350                                 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
32351
32352                         }
32353
32354
32355                         const contourMovements = [];
32356
32357                         for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
32358
32359                                 if ( j === il ) j = 0;
32360                                 if ( k === il ) k = 0;
32361
32362                                 //  (j)---(i)---(k)
32363                                 // console.log('i,j,k', i, j , k)
32364
32365                                 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
32366
32367                         }
32368
32369                         const holesMovements = [];
32370                         let oneHoleMovements, verticesMovements = contourMovements.concat();
32371
32372                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32373
32374                                 const ahole = holes[ h ];
32375
32376                                 oneHoleMovements = [];
32377
32378                                 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
32379
32380                                         if ( j === il ) j = 0;
32381                                         if ( k === il ) k = 0;
32382
32383                                         //  (j)---(i)---(k)
32384                                         oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
32385
32386                                 }
32387
32388                                 holesMovements.push( oneHoleMovements );
32389                                 verticesMovements = verticesMovements.concat( oneHoleMovements );
32390
32391                         }
32392
32393
32394                         // Loop bevelSegments, 1 for the front, 1 for the back
32395
32396                         for ( let b = 0; b < bevelSegments; b ++ ) {
32397
32398                                 //for ( b = bevelSegments; b > 0; b -- ) {
32399
32400                                 const t = b / bevelSegments;
32401                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
32402                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
32403
32404                                 // contract shape
32405
32406                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
32407
32408                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
32409
32410                                         v( vert.x, vert.y, - z );
32411
32412                                 }
32413
32414                                 // expand holes
32415
32416                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32417
32418                                         const ahole = holes[ h ];
32419                                         oneHoleMovements = holesMovements[ h ];
32420
32421                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
32422
32423                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
32424
32425                                                 v( vert.x, vert.y, - z );
32426
32427                                         }
32428
32429                                 }
32430
32431                         }
32432
32433                         const bs = bevelSize + bevelOffset;
32434
32435                         // Back facing vertices
32436
32437                         for ( let i = 0; i < vlen; i ++ ) {
32438
32439                                 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
32440
32441                                 if ( ! extrudeByPath ) {
32442
32443                                         v( vert.x, vert.y, 0 );
32444
32445                                 } else {
32446
32447                                         // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
32448
32449                                         normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
32450                                         binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
32451
32452                                         position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
32453
32454                                         v( position2.x, position2.y, position2.z );
32455
32456                                 }
32457
32458                         }
32459
32460                         // Add stepped vertices...
32461                         // Including front facing vertices
32462
32463                         for ( let s = 1; s <= steps; s ++ ) {
32464
32465                                 for ( let i = 0; i < vlen; i ++ ) {
32466
32467                                         const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
32468
32469                                         if ( ! extrudeByPath ) {
32470
32471                                                 v( vert.x, vert.y, depth / steps * s );
32472
32473                                         } else {
32474
32475                                                 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
32476
32477                                                 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
32478                                                 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
32479
32480                                                 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
32481
32482                                                 v( position2.x, position2.y, position2.z );
32483
32484                                         }
32485
32486                                 }
32487
32488                         }
32489
32490
32491                         // Add bevel segments planes
32492
32493                         //for ( b = 1; b <= bevelSegments; b ++ ) {
32494                         for ( let b = bevelSegments - 1; b >= 0; b -- ) {
32495
32496                                 const t = b / bevelSegments;
32497                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
32498                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
32499
32500                                 // contract shape
32501
32502                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
32503
32504                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
32505                                         v( vert.x, vert.y, depth + z );
32506
32507                                 }
32508
32509                                 // expand holes
32510
32511                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32512
32513                                         const ahole = holes[ h ];
32514                                         oneHoleMovements = holesMovements[ h ];
32515
32516                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
32517
32518                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
32519
32520                                                 if ( ! extrudeByPath ) {
32521
32522                                                         v( vert.x, vert.y, depth + z );
32523
32524                                                 } else {
32525
32526                                                         v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
32527
32528                                                 }
32529
32530                                         }
32531
32532                                 }
32533
32534                         }
32535
32536                         /* Faces */
32537
32538                         // Top and bottom faces
32539
32540                         buildLidFaces();
32541
32542                         // Sides faces
32543
32544                         buildSideFaces();
32545
32546
32547                         /////  Internal functions
32548
32549                         function buildLidFaces() {
32550
32551                                 const start = verticesArray.length / 3;
32552
32553                                 if ( bevelEnabled ) {
32554
32555                                         let layer = 0; // steps + 1
32556                                         let offset = vlen * layer;
32557
32558                                         // Bottom faces
32559
32560                                         for ( let i = 0; i < flen; i ++ ) {
32561
32562                                                 const face = faces[ i ];
32563                                                 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
32564
32565                                         }
32566
32567                                         layer = steps + bevelSegments * 2;
32568                                         offset = vlen * layer;
32569
32570                                         // Top faces
32571
32572                                         for ( let i = 0; i < flen; i ++ ) {
32573
32574                                                 const face = faces[ i ];
32575                                                 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
32576
32577                                         }
32578
32579                                 } else {
32580
32581                                         // Bottom faces
32582
32583                                         for ( let i = 0; i < flen; i ++ ) {
32584
32585                                                 const face = faces[ i ];
32586                                                 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
32587
32588                                         }
32589
32590                                         // Top faces
32591
32592                                         for ( let i = 0; i < flen; i ++ ) {
32593
32594                                                 const face = faces[ i ];
32595                                                 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
32596
32597                                         }
32598
32599                                 }
32600
32601                                 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
32602
32603                         }
32604
32605                         // Create faces for the z-sides of the shape
32606
32607                         function buildSideFaces() {
32608
32609                                 const start = verticesArray.length / 3;
32610                                 let layeroffset = 0;
32611                                 sidewalls( contour, layeroffset );
32612                                 layeroffset += contour.length;
32613
32614                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
32615
32616                                         const ahole = holes[ h ];
32617                                         sidewalls( ahole, layeroffset );
32618
32619                                         //, true
32620                                         layeroffset += ahole.length;
32621
32622                                 }
32623
32624
32625                                 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
32626
32627
32628                         }
32629
32630                         function sidewalls( contour, layeroffset ) {
32631
32632                                 let i = contour.length;
32633
32634                                 while ( -- i >= 0 ) {
32635
32636                                         const j = i;
32637                                         let k = i - 1;
32638                                         if ( k < 0 ) k = contour.length - 1;
32639
32640                                         //console.log('b', i,j, i-1, k,vertices.length);
32641
32642                                         for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
32643
32644                                                 const slen1 = vlen * s;
32645                                                 const slen2 = vlen * ( s + 1 );
32646
32647                                                 const a = layeroffset + j + slen1,
32648                                                         b = layeroffset + k + slen1,
32649                                                         c = layeroffset + k + slen2,
32650                                                         d = layeroffset + j + slen2;
32651
32652                                                 f4( a, b, c, d );
32653
32654                                         }
32655
32656                                 }
32657
32658                         }
32659
32660                         function v( x, y, z ) {
32661
32662                                 placeholder.push( x );
32663                                 placeholder.push( y );
32664                                 placeholder.push( z );
32665
32666                         }
32667
32668
32669                         function f3( a, b, c ) {
32670
32671                                 addVertex( a );
32672                                 addVertex( b );
32673                                 addVertex( c );
32674
32675                                 const nextIndex = verticesArray.length / 3;
32676                                 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
32677
32678                                 addUV( uvs[ 0 ] );
32679                                 addUV( uvs[ 1 ] );
32680                                 addUV( uvs[ 2 ] );
32681
32682                         }
32683
32684                         function f4( a, b, c, d ) {
32685
32686                                 addVertex( a );
32687                                 addVertex( b );
32688                                 addVertex( d );
32689
32690                                 addVertex( b );
32691                                 addVertex( c );
32692                                 addVertex( d );
32693
32694
32695                                 const nextIndex = verticesArray.length / 3;
32696                                 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
32697
32698                                 addUV( uvs[ 0 ] );
32699                                 addUV( uvs[ 1 ] );
32700                                 addUV( uvs[ 3 ] );
32701
32702                                 addUV( uvs[ 1 ] );
32703                                 addUV( uvs[ 2 ] );
32704                                 addUV( uvs[ 3 ] );
32705
32706                         }
32707
32708                         function addVertex( index ) {
32709
32710                                 verticesArray.push( placeholder[ index * 3 + 0 ] );
32711                                 verticesArray.push( placeholder[ index * 3 + 1 ] );
32712                                 verticesArray.push( placeholder[ index * 3 + 2 ] );
32713
32714                         }
32715
32716
32717                         function addUV( vector2 ) {
32718
32719                                 uvArray.push( vector2.x );
32720                                 uvArray.push( vector2.y );
32721
32722                         }
32723
32724                 }
32725
32726         }
32727
32728         toJSON() {
32729
32730                 const data = BufferGeometry.prototype.toJSON.call( this );
32731
32732                 const shapes = this.parameters.shapes;
32733                 const options = this.parameters.options;
32734
32735                 return toJSON( shapes, options, data );
32736
32737         }
32738
32739     }
32740
32741     const WorldUVGenerator = {
32742
32743         generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
32744
32745                 const a_x = vertices[ indexA * 3 ];
32746                 const a_y = vertices[ indexA * 3 + 1 ];
32747                 const b_x = vertices[ indexB * 3 ];
32748                 const b_y = vertices[ indexB * 3 + 1 ];
32749                 const c_x = vertices[ indexC * 3 ];
32750                 const c_y = vertices[ indexC * 3 + 1 ];
32751
32752                 return [
32753                         new Vector2( a_x, a_y ),
32754                         new Vector2( b_x, b_y ),
32755                         new Vector2( c_x, c_y )
32756                 ];
32757
32758         },
32759
32760         generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
32761
32762                 const a_x = vertices[ indexA * 3 ];
32763                 const a_y = vertices[ indexA * 3 + 1 ];
32764                 const a_z = vertices[ indexA * 3 + 2 ];
32765                 const b_x = vertices[ indexB * 3 ];
32766                 const b_y = vertices[ indexB * 3 + 1 ];
32767                 const b_z = vertices[ indexB * 3 + 2 ];
32768                 const c_x = vertices[ indexC * 3 ];
32769                 const c_y = vertices[ indexC * 3 + 1 ];
32770                 const c_z = vertices[ indexC * 3 + 2 ];
32771                 const d_x = vertices[ indexD * 3 ];
32772                 const d_y = vertices[ indexD * 3 + 1 ];
32773                 const d_z = vertices[ indexD * 3 + 2 ];
32774
32775                 if ( Math.abs( a_y - b_y ) < 0.01 ) {
32776
32777                         return [
32778                                 new Vector2( a_x, 1 - a_z ),
32779                                 new Vector2( b_x, 1 - b_z ),
32780                                 new Vector2( c_x, 1 - c_z ),
32781                                 new Vector2( d_x, 1 - d_z )
32782                         ];
32783
32784                 } else {
32785
32786                         return [
32787                                 new Vector2( a_y, 1 - a_z ),
32788                                 new Vector2( b_y, 1 - b_z ),
32789                                 new Vector2( c_y, 1 - c_z ),
32790                                 new Vector2( d_y, 1 - d_z )
32791                         ];
32792
32793                 }
32794
32795         }
32796
32797     };
32798
32799     function toJSON( shapes, options, data ) {
32800
32801         data.shapes = [];
32802
32803         if ( Array.isArray( shapes ) ) {
32804
32805                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
32806
32807                         const shape = shapes[ i ];
32808
32809                         data.shapes.push( shape.uuid );
32810
32811                 }
32812
32813         } else {
32814
32815                 data.shapes.push( shapes.uuid );
32816
32817         }
32818
32819         if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
32820
32821         return data;
32822
32823     }
32824
32825     /**
32826      * Parametric Surfaces Geometry
32827      * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
32828      */
32829
32830     function ParametricGeometry( func, slices, stacks ) {
32831
32832         BufferGeometry.call( this );
32833
32834         this.type = 'ParametricGeometry';
32835
32836         this.parameters = {
32837                 func: func,
32838                 slices: slices,
32839                 stacks: stacks
32840         };
32841
32842         // buffers
32843
32844         const indices = [];
32845         const vertices = [];
32846         const normals = [];
32847         const uvs = [];
32848
32849         const EPS = 0.00001;
32850
32851         const normal = new Vector3();
32852
32853         const p0 = new Vector3(), p1 = new Vector3();
32854         const pu = new Vector3(), pv = new Vector3();
32855
32856         if ( func.length < 3 ) {
32857
32858                 console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
32859
32860         }
32861
32862         // generate vertices, normals and uvs
32863
32864         const sliceCount = slices + 1;
32865
32866         for ( let i = 0; i <= stacks; i ++ ) {
32867
32868                 const v = i / stacks;
32869
32870                 for ( let j = 0; j <= slices; j ++ ) {
32871
32872                         const u = j / slices;
32873
32874                         // vertex
32875
32876                         func( u, v, p0 );
32877                         vertices.push( p0.x, p0.y, p0.z );
32878
32879                         // normal
32880
32881                         // approximate tangent vectors via finite differences
32882
32883                         if ( u - EPS >= 0 ) {
32884
32885                                 func( u - EPS, v, p1 );
32886                                 pu.subVectors( p0, p1 );
32887
32888                         } else {
32889
32890                                 func( u + EPS, v, p1 );
32891                                 pu.subVectors( p1, p0 );
32892
32893                         }
32894
32895                         if ( v - EPS >= 0 ) {
32896
32897                                 func( u, v - EPS, p1 );
32898                                 pv.subVectors( p0, p1 );
32899
32900                         } else {
32901
32902                                 func( u, v + EPS, p1 );
32903                                 pv.subVectors( p1, p0 );
32904
32905                         }
32906
32907                         // cross product of tangent vectors returns surface normal
32908
32909                         normal.crossVectors( pu, pv ).normalize();
32910                         normals.push( normal.x, normal.y, normal.z );
32911
32912                         // uv
32913
32914                         uvs.push( u, v );
32915
32916                 }
32917
32918         }
32919
32920         // generate indices
32921
32922         for ( let i = 0; i < stacks; i ++ ) {
32923
32924                 for ( let j = 0; j < slices; j ++ ) {
32925
32926                         const a = i * sliceCount + j;
32927                         const b = i * sliceCount + j + 1;
32928                         const c = ( i + 1 ) * sliceCount + j + 1;
32929                         const d = ( i + 1 ) * sliceCount + j;
32930
32931                         // faces one and two
32932
32933                         indices.push( a, b, d );
32934                         indices.push( b, c, d );
32935
32936                 }
32937
32938         }
32939
32940         // build geometry
32941
32942         this.setIndex( indices );
32943         this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32944         this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32945         this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32946
32947     }
32948
32949     ParametricGeometry.prototype = Object.create( BufferGeometry.prototype );
32950     ParametricGeometry.prototype.constructor = ParametricGeometry;
32951
32952     class ShapeGeometry extends BufferGeometry {
32953
32954         constructor( shapes, curveSegments = 12 ) {
32955
32956                 super();
32957                 this.type = 'ShapeGeometry';
32958
32959                 this.parameters = {
32960                         shapes: shapes,
32961                         curveSegments: curveSegments
32962                 };
32963
32964                 // buffers
32965
32966                 const indices = [];
32967                 const vertices = [];
32968                 const normals = [];
32969                 const uvs = [];
32970
32971                 // helper variables
32972
32973                 let groupStart = 0;
32974                 let groupCount = 0;
32975
32976                 // allow single and array values for "shapes" parameter
32977
32978                 if ( Array.isArray( shapes ) === false ) {
32979
32980                         addShape( shapes );
32981
32982                 } else {
32983
32984                         for ( let i = 0; i < shapes.length; i ++ ) {
32985
32986                                 addShape( shapes[ i ] );
32987
32988                                 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
32989
32990                                 groupStart += groupCount;
32991                                 groupCount = 0;
32992
32993                         }
32994
32995                 }
32996
32997                 // build geometry
32998
32999                 this.setIndex( indices );
33000                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
33001                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
33002                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
33003
33004
33005                 // helper functions
33006
33007                 function addShape( shape ) {
33008
33009                         const indexOffset = vertices.length / 3;
33010                         const points = shape.extractPoints( curveSegments );
33011
33012                         let shapeVertices = points.shape;
33013                         const shapeHoles = points.holes;
33014
33015                         // check direction of vertices
33016
33017                         if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
33018
33019                                 shapeVertices = shapeVertices.reverse();
33020
33021                         }
33022
33023                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
33024
33025                                 const shapeHole = shapeHoles[ i ];
33026
33027                                 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
33028
33029                                         shapeHoles[ i ] = shapeHole.reverse();
33030
33031                                 }
33032
33033                         }
33034
33035                         const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
33036
33037                         // join vertices of inner and outer paths to a single array
33038
33039                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
33040
33041                                 const shapeHole = shapeHoles[ i ];
33042                                 shapeVertices = shapeVertices.concat( shapeHole );
33043
33044                         }
33045
33046                         // vertices, normals, uvs
33047
33048                         for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
33049
33050                                 const vertex = shapeVertices[ i ];
33051
33052                                 vertices.push( vertex.x, vertex.y, 0 );
33053                                 normals.push( 0, 0, 1 );
33054                                 uvs.push( vertex.x, vertex.y ); // world uvs
33055
33056                         }
33057
33058                         // incides
33059
33060                         for ( let i = 0, l = faces.length; i < l; i ++ ) {
33061
33062                                 const face = faces[ i ];
33063
33064                                 const a = face[ 0 ] + indexOffset;
33065                                 const b = face[ 1 ] + indexOffset;
33066                                 const c = face[ 2 ] + indexOffset;
33067
33068                                 indices.push( a, b, c );
33069                                 groupCount += 3;
33070
33071                         }
33072
33073                 }
33074
33075         }
33076
33077         toJSON() {
33078
33079                 const data = BufferGeometry.prototype.toJSON.call( this );
33080
33081                 const shapes = this.parameters.shapes;
33082
33083                 return toJSON$1( shapes, data );
33084
33085         }
33086
33087     }
33088
33089     function toJSON$1( shapes, data ) {
33090
33091         data.shapes = [];
33092
33093         if ( Array.isArray( shapes ) ) {
33094
33095                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
33096
33097                         const shape = shapes[ i ];
33098
33099                         data.shapes.push( shape.uuid );
33100
33101                 }
33102
33103         } else {
33104
33105                 data.shapes.push( shapes.uuid );
33106
33107         }
33108
33109         return data;
33110
33111     }
33112
33113     class SphereGeometry extends BufferGeometry {
33114
33115         constructor( radius = 1, widthSegments = 8, heightSegments = 6, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
33116
33117                 super();
33118                 this.type = 'SphereGeometry';
33119
33120                 this.parameters = {
33121                         radius: radius,
33122                         widthSegments: widthSegments,
33123                         heightSegments: heightSegments,
33124                         phiStart: phiStart,
33125                         phiLength: phiLength,
33126                         thetaStart: thetaStart,
33127                         thetaLength: thetaLength
33128                 };
33129
33130                 widthSegments = Math.max( 3, Math.floor( widthSegments ) );
33131                 heightSegments = Math.max( 2, Math.floor( heightSegments ) );
33132
33133                 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
33134
33135                 let index = 0;
33136                 const grid = [];
33137
33138                 const vertex = new Vector3();
33139                 const normal = new Vector3();
33140
33141                 // buffers
33142
33143                 const indices = [];
33144                 const vertices = [];
33145                 const normals = [];
33146                 const uvs = [];
33147
33148                 // generate vertices, normals and uvs
33149
33150                 for ( let iy = 0; iy <= heightSegments; iy ++ ) {
33151
33152                         const verticesRow = [];
33153
33154                         const v = iy / heightSegments;
33155
33156                         // special case for the poles
33157
33158                         let uOffset = 0;
33159
33160                         if ( iy == 0 && thetaStart == 0 ) {
33161
33162                                 uOffset = 0.5 / widthSegments;
33163
33164                         } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
33165
33166                                 uOffset = - 0.5 / widthSegments;
33167
33168                         }
33169
33170                         for ( let ix = 0; ix <= widthSegments; ix ++ ) {
33171
33172                                 const u = ix / widthSegments;
33173
33174                                 // vertex
33175
33176                                 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
33177                                 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
33178                                 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
33179
33180                                 vertices.push( vertex.x, vertex.y, vertex.z );
33181
33182                                 // normal
33183
33184                                 normal.copy( vertex ).normalize();
33185                                 normals.push( normal.x, normal.y, normal.z );
33186
33187                                 // uv
33188
33189                                 uvs.push( u + uOffset, 1 - v );
33190
33191                                 verticesRow.push( index ++ );
33192
33193                         }
33194
33195                         grid.push( verticesRow );
33196
33197                 }
33198
33199                 // indices
33200
33201                 for ( let iy = 0; iy < heightSegments; iy ++ ) {
33202
33203                         for ( let ix = 0; ix < widthSegments; ix ++ ) {
33204
33205                                 const a = grid[ iy ][ ix + 1 ];
33206                                 const b = grid[ iy ][ ix ];
33207                                 const c = grid[ iy + 1 ][ ix ];
33208                                 const d = grid[ iy + 1 ][ ix + 1 ];
33209
33210                                 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
33211                                 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
33212
33213                         }
33214
33215                 }
33216
33217                 // build geometry
33218
33219                 this.setIndex( indices );
33220                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
33221                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
33222                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
33223
33224         }
33225
33226     }
33227
33228     /**
33229      * parameters = {
33230      *  color: <THREE.Color>
33231      * }
33232      */
33233
33234     function ShadowMaterial( parameters ) {
33235
33236         Material.call( this );
33237
33238         this.type = 'ShadowMaterial';
33239
33240         this.color = new Color( 0x000000 );
33241         this.transparent = true;
33242
33243         this.setValues( parameters );
33244
33245     }
33246
33247     ShadowMaterial.prototype = Object.create( Material.prototype );
33248     ShadowMaterial.prototype.constructor = ShadowMaterial;
33249
33250     ShadowMaterial.prototype.isShadowMaterial = true;
33251
33252     ShadowMaterial.prototype.copy = function ( source ) {
33253
33254         Material.prototype.copy.call( this, source );
33255
33256         this.color.copy( source.color );
33257
33258         return this;
33259
33260     };
33261
33262     function RawShaderMaterial( parameters ) {
33263
33264         ShaderMaterial.call( this, parameters );
33265
33266         this.type = 'RawShaderMaterial';
33267
33268     }
33269
33270     RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
33271     RawShaderMaterial.prototype.constructor = RawShaderMaterial;
33272
33273     RawShaderMaterial.prototype.isRawShaderMaterial = true;
33274
33275     /**
33276      * parameters = {
33277      *  color: <hex>,
33278      *  roughness: <float>,
33279      *  metalness: <float>,
33280      *  opacity: <float>,
33281      *
33282      *  map: new THREE.Texture( <Image> ),
33283      *
33284      *  lightMap: new THREE.Texture( <Image> ),
33285      *  lightMapIntensity: <float>
33286      *
33287      *  aoMap: new THREE.Texture( <Image> ),
33288      *  aoMapIntensity: <float>
33289      *
33290      *  emissive: <hex>,
33291      *  emissiveIntensity: <float>
33292      *  emissiveMap: new THREE.Texture( <Image> ),
33293      *
33294      *  bumpMap: new THREE.Texture( <Image> ),
33295      *  bumpScale: <float>,
33296      *
33297      *  normalMap: new THREE.Texture( <Image> ),
33298      *  normalMapType: THREE.TangentSpaceNormalMap,
33299      *  normalScale: <Vector2>,
33300      *
33301      *  displacementMap: new THREE.Texture( <Image> ),
33302      *  displacementScale: <float>,
33303      *  displacementBias: <float>,
33304      *
33305      *  roughnessMap: new THREE.Texture( <Image> ),
33306      *
33307      *  metalnessMap: new THREE.Texture( <Image> ),
33308      *
33309      *  alphaMap: new THREE.Texture( <Image> ),
33310      *
33311      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33312      *  envMapIntensity: <float>
33313      *
33314      *  refractionRatio: <float>,
33315      *
33316      *  wireframe: <boolean>,
33317      *  wireframeLinewidth: <float>,
33318      *
33319      *  skinning: <bool>,
33320      *  morphTargets: <bool>,
33321      *  morphNormals: <bool>
33322      * }
33323      */
33324
33325     function MeshStandardMaterial( parameters ) {
33326
33327         Material.call( this );
33328
33329         this.defines = { 'STANDARD': '' };
33330
33331         this.type = 'MeshStandardMaterial';
33332
33333         this.color = new Color( 0xffffff ); // diffuse
33334         this.roughness = 1.0;
33335         this.metalness = 0.0;
33336
33337         this.map = null;
33338
33339         this.lightMap = null;
33340         this.lightMapIntensity = 1.0;
33341
33342         this.aoMap = null;
33343         this.aoMapIntensity = 1.0;
33344
33345         this.emissive = new Color( 0x000000 );
33346         this.emissiveIntensity = 1.0;
33347         this.emissiveMap = null;
33348
33349         this.bumpMap = null;
33350         this.bumpScale = 1;
33351
33352         this.normalMap = null;
33353         this.normalMapType = TangentSpaceNormalMap;
33354         this.normalScale = new Vector2( 1, 1 );
33355
33356         this.displacementMap = null;
33357         this.displacementScale = 1;
33358         this.displacementBias = 0;
33359
33360         this.roughnessMap = null;
33361
33362         this.metalnessMap = null;
33363
33364         this.alphaMap = null;
33365
33366         this.envMap = null;
33367         this.envMapIntensity = 1.0;
33368
33369         this.refractionRatio = 0.98;
33370
33371         this.wireframe = false;
33372         this.wireframeLinewidth = 1;
33373         this.wireframeLinecap = 'round';
33374         this.wireframeLinejoin = 'round';
33375
33376         this.skinning = false;
33377         this.morphTargets = false;
33378         this.morphNormals = false;
33379
33380         this.vertexTangents = false;
33381
33382         this.setValues( parameters );
33383
33384     }
33385
33386     MeshStandardMaterial.prototype = Object.create( Material.prototype );
33387     MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
33388
33389     MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
33390
33391     MeshStandardMaterial.prototype.copy = function ( source ) {
33392
33393         Material.prototype.copy.call( this, source );
33394
33395         this.defines = { 'STANDARD': '' };
33396
33397         this.color.copy( source.color );
33398         this.roughness = source.roughness;
33399         this.metalness = source.metalness;
33400
33401         this.map = source.map;
33402
33403         this.lightMap = source.lightMap;
33404         this.lightMapIntensity = source.lightMapIntensity;
33405
33406         this.aoMap = source.aoMap;
33407         this.aoMapIntensity = source.aoMapIntensity;
33408
33409         this.emissive.copy( source.emissive );
33410         this.emissiveMap = source.emissiveMap;
33411         this.emissiveIntensity = source.emissiveIntensity;
33412
33413         this.bumpMap = source.bumpMap;
33414         this.bumpScale = source.bumpScale;
33415
33416         this.normalMap = source.normalMap;
33417         this.normalMapType = source.normalMapType;
33418         this.normalScale.copy( source.normalScale );
33419
33420         this.displacementMap = source.displacementMap;
33421         this.displacementScale = source.displacementScale;
33422         this.displacementBias = source.displacementBias;
33423
33424         this.roughnessMap = source.roughnessMap;
33425
33426         this.metalnessMap = source.metalnessMap;
33427
33428         this.alphaMap = source.alphaMap;
33429
33430         this.envMap = source.envMap;
33431         this.envMapIntensity = source.envMapIntensity;
33432
33433         this.refractionRatio = source.refractionRatio;
33434
33435         this.wireframe = source.wireframe;
33436         this.wireframeLinewidth = source.wireframeLinewidth;
33437         this.wireframeLinecap = source.wireframeLinecap;
33438         this.wireframeLinejoin = source.wireframeLinejoin;
33439
33440         this.skinning = source.skinning;
33441         this.morphTargets = source.morphTargets;
33442         this.morphNormals = source.morphNormals;
33443
33444         this.vertexTangents = source.vertexTangents;
33445
33446         return this;
33447
33448     };
33449
33450     /**
33451      * parameters = {
33452      *  clearcoat: <float>,
33453      *  clearcoatMap: new THREE.Texture( <Image> ),
33454      *  clearcoatRoughness: <float>,
33455      *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
33456      *  clearcoatNormalScale: <Vector2>,
33457      *  clearcoatNormalMap: new THREE.Texture( <Image> ),
33458      *
33459      *  reflectivity: <float>,
33460      *  ior: <float>,
33461      *
33462      *  sheen: <Color>,
33463      *
33464      *  transmission: <float>,
33465      *  transmissionMap: new THREE.Texture( <Image> )
33466      * }
33467      */
33468
33469     function MeshPhysicalMaterial( parameters ) {
33470
33471         MeshStandardMaterial.call( this );
33472
33473         this.defines = {
33474
33475                 'STANDARD': '',
33476                 'PHYSICAL': ''
33477
33478         };
33479
33480         this.type = 'MeshPhysicalMaterial';
33481
33482         this.clearcoat = 0.0;
33483         this.clearcoatMap = null;
33484         this.clearcoatRoughness = 0.0;
33485         this.clearcoatRoughnessMap = null;
33486         this.clearcoatNormalScale = new Vector2( 1, 1 );
33487         this.clearcoatNormalMap = null;
33488
33489         this.reflectivity = 0.5; // maps to F0 = 0.04
33490
33491         Object.defineProperty( this, 'ior', {
33492                 get: function () {
33493
33494                         return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity );
33495
33496                 },
33497                 set: function ( ior ) {
33498
33499                         this.reflectivity = MathUtils.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 );
33500
33501                 }
33502         } );
33503
33504         this.sheen = null; // null will disable sheen bsdf
33505
33506         this.transmission = 0.0;
33507         this.transmissionMap = null;
33508
33509         this.setValues( parameters );
33510
33511     }
33512
33513     MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
33514     MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
33515
33516     MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
33517
33518     MeshPhysicalMaterial.prototype.copy = function ( source ) {
33519
33520         MeshStandardMaterial.prototype.copy.call( this, source );
33521
33522         this.defines = {
33523
33524                 'STANDARD': '',
33525                 'PHYSICAL': ''
33526
33527         };
33528
33529         this.clearcoat = source.clearcoat;
33530         this.clearcoatMap = source.clearcoatMap;
33531         this.clearcoatRoughness = source.clearcoatRoughness;
33532         this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
33533         this.clearcoatNormalMap = source.clearcoatNormalMap;
33534         this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
33535
33536         this.reflectivity = source.reflectivity;
33537
33538         if ( source.sheen ) {
33539
33540                 this.sheen = ( this.sheen || new Color() ).copy( source.sheen );
33541
33542         } else {
33543
33544                 this.sheen = null;
33545
33546         }
33547
33548         this.transmission = source.transmission;
33549         this.transmissionMap = source.transmissionMap;
33550
33551         return this;
33552
33553     };
33554
33555     /**
33556      * parameters = {
33557      *  color: <hex>,
33558      *  specular: <hex>,
33559      *  shininess: <float>,
33560      *  opacity: <float>,
33561      *
33562      *  map: new THREE.Texture( <Image> ),
33563      *
33564      *  lightMap: new THREE.Texture( <Image> ),
33565      *  lightMapIntensity: <float>
33566      *
33567      *  aoMap: new THREE.Texture( <Image> ),
33568      *  aoMapIntensity: <float>
33569      *
33570      *  emissive: <hex>,
33571      *  emissiveIntensity: <float>
33572      *  emissiveMap: new THREE.Texture( <Image> ),
33573      *
33574      *  bumpMap: new THREE.Texture( <Image> ),
33575      *  bumpScale: <float>,
33576      *
33577      *  normalMap: new THREE.Texture( <Image> ),
33578      *  normalMapType: THREE.TangentSpaceNormalMap,
33579      *  normalScale: <Vector2>,
33580      *
33581      *  displacementMap: new THREE.Texture( <Image> ),
33582      *  displacementScale: <float>,
33583      *  displacementBias: <float>,
33584      *
33585      *  specularMap: new THREE.Texture( <Image> ),
33586      *
33587      *  alphaMap: new THREE.Texture( <Image> ),
33588      *
33589      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33590      *  combine: THREE.MultiplyOperation,
33591      *  reflectivity: <float>,
33592      *  refractionRatio: <float>,
33593      *
33594      *  wireframe: <boolean>,
33595      *  wireframeLinewidth: <float>,
33596      *
33597      *  skinning: <bool>,
33598      *  morphTargets: <bool>,
33599      *  morphNormals: <bool>
33600      * }
33601      */
33602
33603     function MeshPhongMaterial( parameters ) {
33604
33605         Material.call( this );
33606
33607         this.type = 'MeshPhongMaterial';
33608
33609         this.color = new Color( 0xffffff ); // diffuse
33610         this.specular = new Color( 0x111111 );
33611         this.shininess = 30;
33612
33613         this.map = null;
33614
33615         this.lightMap = null;
33616         this.lightMapIntensity = 1.0;
33617
33618         this.aoMap = null;
33619         this.aoMapIntensity = 1.0;
33620
33621         this.emissive = new Color( 0x000000 );
33622         this.emissiveIntensity = 1.0;
33623         this.emissiveMap = null;
33624
33625         this.bumpMap = null;
33626         this.bumpScale = 1;
33627
33628         this.normalMap = null;
33629         this.normalMapType = TangentSpaceNormalMap;
33630         this.normalScale = new Vector2( 1, 1 );
33631
33632         this.displacementMap = null;
33633         this.displacementScale = 1;
33634         this.displacementBias = 0;
33635
33636         this.specularMap = null;
33637
33638         this.alphaMap = null;
33639
33640         this.envMap = null;
33641         this.combine = MultiplyOperation;
33642         this.reflectivity = 1;
33643         this.refractionRatio = 0.98;
33644
33645         this.wireframe = false;
33646         this.wireframeLinewidth = 1;
33647         this.wireframeLinecap = 'round';
33648         this.wireframeLinejoin = 'round';
33649
33650         this.skinning = false;
33651         this.morphTargets = false;
33652         this.morphNormals = false;
33653
33654         this.setValues( parameters );
33655
33656     }
33657
33658     MeshPhongMaterial.prototype = Object.create( Material.prototype );
33659     MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
33660
33661     MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
33662
33663     MeshPhongMaterial.prototype.copy = function ( source ) {
33664
33665         Material.prototype.copy.call( this, source );
33666
33667         this.color.copy( source.color );
33668         this.specular.copy( source.specular );
33669         this.shininess = source.shininess;
33670
33671         this.map = source.map;
33672
33673         this.lightMap = source.lightMap;
33674         this.lightMapIntensity = source.lightMapIntensity;
33675
33676         this.aoMap = source.aoMap;
33677         this.aoMapIntensity = source.aoMapIntensity;
33678
33679         this.emissive.copy( source.emissive );
33680         this.emissiveMap = source.emissiveMap;
33681         this.emissiveIntensity = source.emissiveIntensity;
33682
33683         this.bumpMap = source.bumpMap;
33684         this.bumpScale = source.bumpScale;
33685
33686         this.normalMap = source.normalMap;
33687         this.normalMapType = source.normalMapType;
33688         this.normalScale.copy( source.normalScale );
33689
33690         this.displacementMap = source.displacementMap;
33691         this.displacementScale = source.displacementScale;
33692         this.displacementBias = source.displacementBias;
33693
33694         this.specularMap = source.specularMap;
33695
33696         this.alphaMap = source.alphaMap;
33697
33698         this.envMap = source.envMap;
33699         this.combine = source.combine;
33700         this.reflectivity = source.reflectivity;
33701         this.refractionRatio = source.refractionRatio;
33702
33703         this.wireframe = source.wireframe;
33704         this.wireframeLinewidth = source.wireframeLinewidth;
33705         this.wireframeLinecap = source.wireframeLinecap;
33706         this.wireframeLinejoin = source.wireframeLinejoin;
33707
33708         this.skinning = source.skinning;
33709         this.morphTargets = source.morphTargets;
33710         this.morphNormals = source.morphNormals;
33711
33712         return this;
33713
33714     };
33715
33716     /**
33717      * parameters = {
33718      *  color: <hex>,
33719      *
33720      *  map: new THREE.Texture( <Image> ),
33721      *  gradientMap: new THREE.Texture( <Image> ),
33722      *
33723      *  lightMap: new THREE.Texture( <Image> ),
33724      *  lightMapIntensity: <float>
33725      *
33726      *  aoMap: new THREE.Texture( <Image> ),
33727      *  aoMapIntensity: <float>
33728      *
33729      *  emissive: <hex>,
33730      *  emissiveIntensity: <float>
33731      *  emissiveMap: new THREE.Texture( <Image> ),
33732      *
33733      *  bumpMap: new THREE.Texture( <Image> ),
33734      *  bumpScale: <float>,
33735      *
33736      *  normalMap: new THREE.Texture( <Image> ),
33737      *  normalMapType: THREE.TangentSpaceNormalMap,
33738      *  normalScale: <Vector2>,
33739      *
33740      *  displacementMap: new THREE.Texture( <Image> ),
33741      *  displacementScale: <float>,
33742      *  displacementBias: <float>,
33743      *
33744      *  alphaMap: new THREE.Texture( <Image> ),
33745      *
33746      *  wireframe: <boolean>,
33747      *  wireframeLinewidth: <float>,
33748      *
33749      *  skinning: <bool>,
33750      *  morphTargets: <bool>,
33751      *  morphNormals: <bool>
33752      * }
33753      */
33754
33755     function MeshToonMaterial( parameters ) {
33756
33757         Material.call( this );
33758
33759         this.defines = { 'TOON': '' };
33760
33761         this.type = 'MeshToonMaterial';
33762
33763         this.color = new Color( 0xffffff );
33764
33765         this.map = null;
33766         this.gradientMap = null;
33767
33768         this.lightMap = null;
33769         this.lightMapIntensity = 1.0;
33770
33771         this.aoMap = null;
33772         this.aoMapIntensity = 1.0;
33773
33774         this.emissive = new Color( 0x000000 );
33775         this.emissiveIntensity = 1.0;
33776         this.emissiveMap = null;
33777
33778         this.bumpMap = null;
33779         this.bumpScale = 1;
33780
33781         this.normalMap = null;
33782         this.normalMapType = TangentSpaceNormalMap;
33783         this.normalScale = new Vector2( 1, 1 );
33784
33785         this.displacementMap = null;
33786         this.displacementScale = 1;
33787         this.displacementBias = 0;
33788
33789         this.alphaMap = null;
33790
33791         this.wireframe = false;
33792         this.wireframeLinewidth = 1;
33793         this.wireframeLinecap = 'round';
33794         this.wireframeLinejoin = 'round';
33795
33796         this.skinning = false;
33797         this.morphTargets = false;
33798         this.morphNormals = false;
33799
33800         this.setValues( parameters );
33801
33802     }
33803
33804     MeshToonMaterial.prototype = Object.create( Material.prototype );
33805     MeshToonMaterial.prototype.constructor = MeshToonMaterial;
33806
33807     MeshToonMaterial.prototype.isMeshToonMaterial = true;
33808
33809     MeshToonMaterial.prototype.copy = function ( source ) {
33810
33811         Material.prototype.copy.call( this, source );
33812
33813         this.color.copy( source.color );
33814
33815         this.map = source.map;
33816         this.gradientMap = source.gradientMap;
33817
33818         this.lightMap = source.lightMap;
33819         this.lightMapIntensity = source.lightMapIntensity;
33820
33821         this.aoMap = source.aoMap;
33822         this.aoMapIntensity = source.aoMapIntensity;
33823
33824         this.emissive.copy( source.emissive );
33825         this.emissiveMap = source.emissiveMap;
33826         this.emissiveIntensity = source.emissiveIntensity;
33827
33828         this.bumpMap = source.bumpMap;
33829         this.bumpScale = source.bumpScale;
33830
33831         this.normalMap = source.normalMap;
33832         this.normalMapType = source.normalMapType;
33833         this.normalScale.copy( source.normalScale );
33834
33835         this.displacementMap = source.displacementMap;
33836         this.displacementScale = source.displacementScale;
33837         this.displacementBias = source.displacementBias;
33838
33839         this.alphaMap = source.alphaMap;
33840
33841         this.wireframe = source.wireframe;
33842         this.wireframeLinewidth = source.wireframeLinewidth;
33843         this.wireframeLinecap = source.wireframeLinecap;
33844         this.wireframeLinejoin = source.wireframeLinejoin;
33845
33846         this.skinning = source.skinning;
33847         this.morphTargets = source.morphTargets;
33848         this.morphNormals = source.morphNormals;
33849
33850         return this;
33851
33852     };
33853
33854     /**
33855      * parameters = {
33856      *  opacity: <float>,
33857      *
33858      *  bumpMap: new THREE.Texture( <Image> ),
33859      *  bumpScale: <float>,
33860      *
33861      *  normalMap: new THREE.Texture( <Image> ),
33862      *  normalMapType: THREE.TangentSpaceNormalMap,
33863      *  normalScale: <Vector2>,
33864      *
33865      *  displacementMap: new THREE.Texture( <Image> ),
33866      *  displacementScale: <float>,
33867      *  displacementBias: <float>,
33868      *
33869      *  wireframe: <boolean>,
33870      *  wireframeLinewidth: <float>
33871      *
33872      *  skinning: <bool>,
33873      *  morphTargets: <bool>,
33874      *  morphNormals: <bool>
33875      * }
33876      */
33877
33878     function MeshNormalMaterial( parameters ) {
33879
33880         Material.call( this );
33881
33882         this.type = 'MeshNormalMaterial';
33883
33884         this.bumpMap = null;
33885         this.bumpScale = 1;
33886
33887         this.normalMap = null;
33888         this.normalMapType = TangentSpaceNormalMap;
33889         this.normalScale = new Vector2( 1, 1 );
33890
33891         this.displacementMap = null;
33892         this.displacementScale = 1;
33893         this.displacementBias = 0;
33894
33895         this.wireframe = false;
33896         this.wireframeLinewidth = 1;
33897
33898         this.fog = false;
33899
33900         this.skinning = false;
33901         this.morphTargets = false;
33902         this.morphNormals = false;
33903
33904         this.setValues( parameters );
33905
33906     }
33907
33908     MeshNormalMaterial.prototype = Object.create( Material.prototype );
33909     MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
33910
33911     MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
33912
33913     MeshNormalMaterial.prototype.copy = function ( source ) {
33914
33915         Material.prototype.copy.call( this, source );
33916
33917         this.bumpMap = source.bumpMap;
33918         this.bumpScale = source.bumpScale;
33919
33920         this.normalMap = source.normalMap;
33921         this.normalMapType = source.normalMapType;
33922         this.normalScale.copy( source.normalScale );
33923
33924         this.displacementMap = source.displacementMap;
33925         this.displacementScale = source.displacementScale;
33926         this.displacementBias = source.displacementBias;
33927
33928         this.wireframe = source.wireframe;
33929         this.wireframeLinewidth = source.wireframeLinewidth;
33930
33931         this.skinning = source.skinning;
33932         this.morphTargets = source.morphTargets;
33933         this.morphNormals = source.morphNormals;
33934
33935         return this;
33936
33937     };
33938
33939     /**
33940      * parameters = {
33941      *  color: <hex>,
33942      *  opacity: <float>,
33943      *
33944      *  map: new THREE.Texture( <Image> ),
33945      *
33946      *  lightMap: new THREE.Texture( <Image> ),
33947      *  lightMapIntensity: <float>
33948      *
33949      *  aoMap: new THREE.Texture( <Image> ),
33950      *  aoMapIntensity: <float>
33951      *
33952      *  emissive: <hex>,
33953      *  emissiveIntensity: <float>
33954      *  emissiveMap: new THREE.Texture( <Image> ),
33955      *
33956      *  specularMap: new THREE.Texture( <Image> ),
33957      *
33958      *  alphaMap: new THREE.Texture( <Image> ),
33959      *
33960      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33961      *  combine: THREE.Multiply,
33962      *  reflectivity: <float>,
33963      *  refractionRatio: <float>,
33964      *
33965      *  wireframe: <boolean>,
33966      *  wireframeLinewidth: <float>,
33967      *
33968      *  skinning: <bool>,
33969      *  morphTargets: <bool>,
33970      *  morphNormals: <bool>
33971      * }
33972      */
33973
33974     function MeshLambertMaterial( parameters ) {
33975
33976         Material.call( this );
33977
33978         this.type = 'MeshLambertMaterial';
33979
33980         this.color = new Color( 0xffffff ); // diffuse
33981
33982         this.map = null;
33983
33984         this.lightMap = null;
33985         this.lightMapIntensity = 1.0;
33986
33987         this.aoMap = null;
33988         this.aoMapIntensity = 1.0;
33989
33990         this.emissive = new Color( 0x000000 );
33991         this.emissiveIntensity = 1.0;
33992         this.emissiveMap = null;
33993
33994         this.specularMap = null;
33995
33996         this.alphaMap = null;
33997
33998         this.envMap = null;
33999         this.combine = MultiplyOperation;
34000         this.reflectivity = 1;
34001         this.refractionRatio = 0.98;
34002
34003         this.wireframe = false;
34004         this.wireframeLinewidth = 1;
34005         this.wireframeLinecap = 'round';
34006         this.wireframeLinejoin = 'round';
34007
34008         this.skinning = false;
34009         this.morphTargets = false;
34010         this.morphNormals = false;
34011
34012         this.setValues( parameters );
34013
34014     }
34015
34016     MeshLambertMaterial.prototype = Object.create( Material.prototype );
34017     MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
34018
34019     MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
34020
34021     MeshLambertMaterial.prototype.copy = function ( source ) {
34022
34023         Material.prototype.copy.call( this, source );
34024
34025         this.color.copy( source.color );
34026
34027         this.map = source.map;
34028
34029         this.lightMap = source.lightMap;
34030         this.lightMapIntensity = source.lightMapIntensity;
34031
34032         this.aoMap = source.aoMap;
34033         this.aoMapIntensity = source.aoMapIntensity;
34034
34035         this.emissive.copy( source.emissive );
34036         this.emissiveMap = source.emissiveMap;
34037         this.emissiveIntensity = source.emissiveIntensity;
34038
34039         this.specularMap = source.specularMap;
34040
34041         this.alphaMap = source.alphaMap;
34042
34043         this.envMap = source.envMap;
34044         this.combine = source.combine;
34045         this.reflectivity = source.reflectivity;
34046         this.refractionRatio = source.refractionRatio;
34047
34048         this.wireframe = source.wireframe;
34049         this.wireframeLinewidth = source.wireframeLinewidth;
34050         this.wireframeLinecap = source.wireframeLinecap;
34051         this.wireframeLinejoin = source.wireframeLinejoin;
34052
34053         this.skinning = source.skinning;
34054         this.morphTargets = source.morphTargets;
34055         this.morphNormals = source.morphNormals;
34056
34057         return this;
34058
34059     };
34060
34061     /**
34062      * parameters = {
34063      *  color: <hex>,
34064      *  opacity: <float>,
34065      *
34066      *  matcap: new THREE.Texture( <Image> ),
34067      *
34068      *  map: new THREE.Texture( <Image> ),
34069      *
34070      *  bumpMap: new THREE.Texture( <Image> ),
34071      *  bumpScale: <float>,
34072      *
34073      *  normalMap: new THREE.Texture( <Image> ),
34074      *  normalMapType: THREE.TangentSpaceNormalMap,
34075      *  normalScale: <Vector2>,
34076      *
34077      *  displacementMap: new THREE.Texture( <Image> ),
34078      *  displacementScale: <float>,
34079      *  displacementBias: <float>,
34080      *
34081      *  alphaMap: new THREE.Texture( <Image> ),
34082      *
34083      *  skinning: <bool>,
34084      *  morphTargets: <bool>,
34085      *  morphNormals: <bool>
34086      * }
34087      */
34088
34089     function MeshMatcapMaterial( parameters ) {
34090
34091         Material.call( this );
34092
34093         this.defines = { 'MATCAP': '' };
34094
34095         this.type = 'MeshMatcapMaterial';
34096
34097         this.color = new Color( 0xffffff ); // diffuse
34098
34099         this.matcap = null;
34100
34101         this.map = null;
34102
34103         this.bumpMap = null;
34104         this.bumpScale = 1;
34105
34106         this.normalMap = null;
34107         this.normalMapType = TangentSpaceNormalMap;
34108         this.normalScale = new Vector2( 1, 1 );
34109
34110         this.displacementMap = null;
34111         this.displacementScale = 1;
34112         this.displacementBias = 0;
34113
34114         this.alphaMap = null;
34115
34116         this.skinning = false;
34117         this.morphTargets = false;
34118         this.morphNormals = false;
34119
34120         this.setValues( parameters );
34121
34122     }
34123
34124     MeshMatcapMaterial.prototype = Object.create( Material.prototype );
34125     MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
34126
34127     MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
34128
34129     MeshMatcapMaterial.prototype.copy = function ( source ) {
34130
34131         Material.prototype.copy.call( this, source );
34132
34133         this.defines = { 'MATCAP': '' };
34134
34135         this.color.copy( source.color );
34136
34137         this.matcap = source.matcap;
34138
34139         this.map = source.map;
34140
34141         this.bumpMap = source.bumpMap;
34142         this.bumpScale = source.bumpScale;
34143
34144         this.normalMap = source.normalMap;
34145         this.normalMapType = source.normalMapType;
34146         this.normalScale.copy( source.normalScale );
34147
34148         this.displacementMap = source.displacementMap;
34149         this.displacementScale = source.displacementScale;
34150         this.displacementBias = source.displacementBias;
34151
34152         this.alphaMap = source.alphaMap;
34153
34154         this.skinning = source.skinning;
34155         this.morphTargets = source.morphTargets;
34156         this.morphNormals = source.morphNormals;
34157
34158         return this;
34159
34160     };
34161
34162     /**
34163      * parameters = {
34164      *  color: <hex>,
34165      *  opacity: <float>,
34166      *
34167      *  linewidth: <float>,
34168      *
34169      *  scale: <float>,
34170      *  dashSize: <float>,
34171      *  gapSize: <float>
34172      * }
34173      */
34174
34175     function LineDashedMaterial( parameters ) {
34176
34177         LineBasicMaterial.call( this );
34178
34179         this.type = 'LineDashedMaterial';
34180
34181         this.scale = 1;
34182         this.dashSize = 3;
34183         this.gapSize = 1;
34184
34185         this.setValues( parameters );
34186
34187     }
34188
34189     LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
34190     LineDashedMaterial.prototype.constructor = LineDashedMaterial;
34191
34192     LineDashedMaterial.prototype.isLineDashedMaterial = true;
34193
34194     LineDashedMaterial.prototype.copy = function ( source ) {
34195
34196         LineBasicMaterial.prototype.copy.call( this, source );
34197
34198         this.scale = source.scale;
34199         this.dashSize = source.dashSize;
34200         this.gapSize = source.gapSize;
34201
34202         return this;
34203
34204     };
34205
34206     var Materials = /*#__PURE__*/Object.freeze({
34207         __proto__: null,
34208         ShadowMaterial: ShadowMaterial,
34209         SpriteMaterial: SpriteMaterial,
34210         RawShaderMaterial: RawShaderMaterial,
34211         ShaderMaterial: ShaderMaterial,
34212         PointsMaterial: PointsMaterial,
34213         MeshPhysicalMaterial: MeshPhysicalMaterial,
34214         MeshStandardMaterial: MeshStandardMaterial,
34215         MeshPhongMaterial: MeshPhongMaterial,
34216         MeshToonMaterial: MeshToonMaterial,
34217         MeshNormalMaterial: MeshNormalMaterial,
34218         MeshLambertMaterial: MeshLambertMaterial,
34219         MeshDepthMaterial: MeshDepthMaterial,
34220         MeshDistanceMaterial: MeshDistanceMaterial,
34221         MeshBasicMaterial: MeshBasicMaterial,
34222         MeshMatcapMaterial: MeshMatcapMaterial,
34223         LineDashedMaterial: LineDashedMaterial,
34224         LineBasicMaterial: LineBasicMaterial,
34225         Material: Material
34226     });
34227
34228     const AnimationUtils = {
34229
34230         // same as Array.prototype.slice, but also works on typed arrays
34231         arraySlice: function ( array, from, to ) {
34232
34233                 if ( AnimationUtils.isTypedArray( array ) ) {
34234
34235                         // in ios9 array.subarray(from, undefined) will return empty array
34236                         // but array.subarray(from) or array.subarray(from, len) is correct
34237                         return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
34238
34239                 }
34240
34241                 return array.slice( from, to );
34242
34243         },
34244
34245         // converts an array to a specific type
34246         convertArray: function ( array, type, forceClone ) {
34247
34248                 if ( ! array || // let 'undefined' and 'null' pass
34249                         ! forceClone && array.constructor === type ) return array;
34250
34251                 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
34252
34253                         return new type( array ); // create typed array
34254
34255                 }
34256
34257                 return Array.prototype.slice.call( array ); // create Array
34258
34259         },
34260
34261         isTypedArray: function ( object ) {
34262
34263                 return ArrayBuffer.isView( object ) &&
34264                         ! ( object instanceof DataView );
34265
34266         },
34267
34268         // returns an array by which times and values can be sorted
34269         getKeyframeOrder: function ( times ) {
34270
34271                 function compareTime( i, j ) {
34272
34273                         return times[ i ] - times[ j ];
34274
34275                 }
34276
34277                 const n = times.length;
34278                 const result = new Array( n );
34279                 for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
34280
34281                 result.sort( compareTime );
34282
34283                 return result;
34284
34285         },
34286
34287         // uses the array previously returned by 'getKeyframeOrder' to sort data
34288         sortedArray: function ( values, stride, order ) {
34289
34290                 const nValues = values.length;
34291                 const result = new values.constructor( nValues );
34292
34293                 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
34294
34295                         const srcOffset = order[ i ] * stride;
34296
34297                         for ( let j = 0; j !== stride; ++ j ) {
34298
34299                                 result[ dstOffset ++ ] = values[ srcOffset + j ];
34300
34301                         }
34302
34303                 }
34304
34305                 return result;
34306
34307         },
34308
34309         // function for parsing AOS keyframe formats
34310         flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
34311
34312                 let i = 1, key = jsonKeys[ 0 ];
34313
34314                 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
34315
34316                         key = jsonKeys[ i ++ ];
34317
34318                 }
34319
34320                 if ( key === undefined ) return; // no data
34321
34322                 let value = key[ valuePropertyName ];
34323                 if ( value === undefined ) return; // no data
34324
34325                 if ( Array.isArray( value ) ) {
34326
34327                         do {
34328
34329                                 value = key[ valuePropertyName ];
34330
34331                                 if ( value !== undefined ) {
34332
34333                                         times.push( key.time );
34334                                         values.push.apply( values, value ); // push all elements
34335
34336                                 }
34337
34338                                 key = jsonKeys[ i ++ ];
34339
34340                         } while ( key !== undefined );
34341
34342                 } else if ( value.toArray !== undefined ) {
34343
34344                         // ...assume THREE.Math-ish
34345
34346                         do {
34347
34348                                 value = key[ valuePropertyName ];
34349
34350                                 if ( value !== undefined ) {
34351
34352                                         times.push( key.time );
34353                                         value.toArray( values, values.length );
34354
34355                                 }
34356
34357                                 key = jsonKeys[ i ++ ];
34358
34359                         } while ( key !== undefined );
34360
34361                 } else {
34362
34363                         // otherwise push as-is
34364
34365                         do {
34366
34367                                 value = key[ valuePropertyName ];
34368
34369                                 if ( value !== undefined ) {
34370
34371                                         times.push( key.time );
34372                                         values.push( value );
34373
34374                                 }
34375
34376                                 key = jsonKeys[ i ++ ];
34377
34378                         } while ( key !== undefined );
34379
34380                 }
34381
34382         },
34383
34384         subclip: function ( sourceClip, name, startFrame, endFrame, fps = 30 ) {
34385
34386                 const clip = sourceClip.clone();
34387
34388                 clip.name = name;
34389
34390                 const tracks = [];
34391
34392                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34393
34394                         const track = clip.tracks[ i ];
34395                         const valueSize = track.getValueSize();
34396
34397                         const times = [];
34398                         const values = [];
34399
34400                         for ( let j = 0; j < track.times.length; ++ j ) {
34401
34402                                 const frame = track.times[ j ] * fps;
34403
34404                                 if ( frame < startFrame || frame >= endFrame ) continue;
34405
34406                                 times.push( track.times[ j ] );
34407
34408                                 for ( let k = 0; k < valueSize; ++ k ) {
34409
34410                                         values.push( track.values[ j * valueSize + k ] );
34411
34412                                 }
34413
34414                         }
34415
34416                         if ( times.length === 0 ) continue;
34417
34418                         track.times = AnimationUtils.convertArray( times, track.times.constructor );
34419                         track.values = AnimationUtils.convertArray( values, track.values.constructor );
34420
34421                         tracks.push( track );
34422
34423                 }
34424
34425                 clip.tracks = tracks;
34426
34427                 // find minimum .times value across all tracks in the trimmed clip
34428
34429                 let minStartTime = Infinity;
34430
34431                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34432
34433                         if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
34434
34435                                 minStartTime = clip.tracks[ i ].times[ 0 ];
34436
34437                         }
34438
34439                 }
34440
34441                 // shift all tracks such that clip begins at t=0
34442
34443                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34444
34445                         clip.tracks[ i ].shift( - 1 * minStartTime );
34446
34447                 }
34448
34449                 clip.resetDuration();
34450
34451                 return clip;
34452
34453         },
34454
34455         makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
34456
34457                 if ( fps <= 0 ) fps = 30;
34458
34459                 const numTracks = referenceClip.tracks.length;
34460                 const referenceTime = referenceFrame / fps;
34461
34462                 // Make each track's values relative to the values at the reference frame
34463                 for ( let i = 0; i < numTracks; ++ i ) {
34464
34465                         const referenceTrack = referenceClip.tracks[ i ];
34466                         const referenceTrackType = referenceTrack.ValueTypeName;
34467
34468                         // Skip this track if it's non-numeric
34469                         if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
34470
34471                         // Find the track in the target clip whose name and type matches the reference track
34472                         const targetTrack = targetClip.tracks.find( function ( track ) {
34473
34474                                 return track.name === referenceTrack.name
34475                                         && track.ValueTypeName === referenceTrackType;
34476
34477                         } );
34478
34479                         if ( targetTrack === undefined ) continue;
34480
34481                         let referenceOffset = 0;
34482                         const referenceValueSize = referenceTrack.getValueSize();
34483
34484                         if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
34485
34486                                 referenceOffset = referenceValueSize / 3;
34487
34488                         }
34489
34490                         let targetOffset = 0;
34491                         const targetValueSize = targetTrack.getValueSize();
34492
34493                         if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
34494
34495                                 targetOffset = targetValueSize / 3;
34496
34497                         }
34498
34499                         const lastIndex = referenceTrack.times.length - 1;
34500                         let referenceValue;
34501
34502                         // Find the value to subtract out of the track
34503                         if ( referenceTime <= referenceTrack.times[ 0 ] ) {
34504
34505                                 // Reference frame is earlier than the first keyframe, so just use the first keyframe
34506                                 const startIndex = referenceOffset;
34507                                 const endIndex = referenceValueSize - referenceOffset;
34508                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
34509
34510                         } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
34511
34512                                 // Reference frame is after the last keyframe, so just use the last keyframe
34513                                 const startIndex = lastIndex * referenceValueSize + referenceOffset;
34514                                 const endIndex = startIndex + referenceValueSize - referenceOffset;
34515                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
34516
34517                         } else {
34518
34519                                 // Interpolate to the reference value
34520                                 const interpolant = referenceTrack.createInterpolant();
34521                                 const startIndex = referenceOffset;
34522                                 const endIndex = referenceValueSize - referenceOffset;
34523                                 interpolant.evaluate( referenceTime );
34524                                 referenceValue = AnimationUtils.arraySlice( interpolant.resultBuffer, startIndex, endIndex );
34525
34526                         }
34527
34528                         // Conjugate the quaternion
34529                         if ( referenceTrackType === 'quaternion' ) {
34530
34531                                 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
34532                                 referenceQuat.toArray( referenceValue );
34533
34534                         }
34535
34536                         // Subtract the reference value from all of the track values
34537
34538                         const numTimes = targetTrack.times.length;
34539                         for ( let j = 0; j < numTimes; ++ j ) {
34540
34541                                 const valueStart = j * targetValueSize + targetOffset;
34542
34543                                 if ( referenceTrackType === 'quaternion' ) {
34544
34545                                         // Multiply the conjugate for quaternion track types
34546                                         Quaternion.multiplyQuaternionsFlat(
34547                                                 targetTrack.values,
34548                                                 valueStart,
34549                                                 referenceValue,
34550                                                 0,
34551                                                 targetTrack.values,
34552                                                 valueStart
34553                                         );
34554
34555                                 } else {
34556
34557                                         const valueEnd = targetValueSize - targetOffset * 2;
34558
34559                                         // Subtract each value for all other numeric track types
34560                                         for ( let k = 0; k < valueEnd; ++ k ) {
34561
34562                                                 targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
34563
34564                                         }
34565
34566                                 }
34567
34568                         }
34569
34570                 }
34571
34572                 targetClip.blendMode = AdditiveAnimationBlendMode;
34573
34574                 return targetClip;
34575
34576         }
34577
34578     };
34579
34580     /**
34581      * Abstract base class of interpolants over parametric samples.
34582      *
34583      * The parameter domain is one dimensional, typically the time or a path
34584      * along a curve defined by the data.
34585      *
34586      * The sample values can have any dimensionality and derived classes may
34587      * apply special interpretations to the data.
34588      *
34589      * This class provides the interval seek in a Template Method, deferring
34590      * the actual interpolation to derived classes.
34591      *
34592      * Time complexity is O(1) for linear access crossing at most two points
34593      * and O(log N) for random access, where N is the number of positions.
34594      *
34595      * References:
34596      *
34597      *          http://www.oodesign.com/template-method-pattern.html
34598      *
34599      */
34600
34601     function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34602
34603         this.parameterPositions = parameterPositions;
34604         this._cachedIndex = 0;
34605
34606         this.resultBuffer = resultBuffer !== undefined ?
34607                 resultBuffer : new sampleValues.constructor( sampleSize );
34608         this.sampleValues = sampleValues;
34609         this.valueSize = sampleSize;
34610
34611     }
34612
34613     Object.assign( Interpolant.prototype, {
34614
34615         evaluate: function ( t ) {
34616
34617                 const pp = this.parameterPositions;
34618                 let i1 = this._cachedIndex,
34619                         t1 = pp[ i1 ],
34620                         t0 = pp[ i1 - 1 ];
34621
34622                 validate_interval: {
34623
34624                         seek: {
34625
34626                                 let right;
34627
34628                                 linear_scan: {
34629
34630                                         //- See http://jsperf.com/comparison-to-undefined/3
34631                                         //- slower code:
34632                                         //-
34633                                         //-                             if ( t >= t1 || t1 === undefined ) {
34634                                         forward_scan: if ( ! ( t < t1 ) ) {
34635
34636                                                 for ( let giveUpAt = i1 + 2; ; ) {
34637
34638                                                         if ( t1 === undefined ) {
34639
34640                                                                 if ( t < t0 ) break forward_scan;
34641
34642                                                                 // after end
34643
34644                                                                 i1 = pp.length;
34645                                                                 this._cachedIndex = i1;
34646                                                                 return this.afterEnd_( i1 - 1, t, t0 );
34647
34648                                                         }
34649
34650                                                         if ( i1 === giveUpAt ) break; // this loop
34651
34652                                                         t0 = t1;
34653                                                         t1 = pp[ ++ i1 ];
34654
34655                                                         if ( t < t1 ) {
34656
34657                                                                 // we have arrived at the sought interval
34658                                                                 break seek;
34659
34660                                                         }
34661
34662                                                 }
34663
34664                                                 // prepare binary search on the right side of the index
34665                                                 right = pp.length;
34666                                                 break linear_scan;
34667
34668                                         }
34669
34670                                         //- slower code:
34671                                         //-                                     if ( t < t0 || t0 === undefined ) {
34672                                         if ( ! ( t >= t0 ) ) {
34673
34674                                                 // looping?
34675
34676                                                 const t1global = pp[ 1 ];
34677
34678                                                 if ( t < t1global ) {
34679
34680                                                         i1 = 2; // + 1, using the scan for the details
34681                                                         t0 = t1global;
34682
34683                                                 }
34684
34685                                                 // linear reverse scan
34686
34687                                                 for ( let giveUpAt = i1 - 2; ; ) {
34688
34689                                                         if ( t0 === undefined ) {
34690
34691                                                                 // before start
34692
34693                                                                 this._cachedIndex = 0;
34694                                                                 return this.beforeStart_( 0, t, t1 );
34695
34696                                                         }
34697
34698                                                         if ( i1 === giveUpAt ) break; // this loop
34699
34700                                                         t1 = t0;
34701                                                         t0 = pp[ -- i1 - 1 ];
34702
34703                                                         if ( t >= t0 ) {
34704
34705                                                                 // we have arrived at the sought interval
34706                                                                 break seek;
34707
34708                                                         }
34709
34710                                                 }
34711
34712                                                 // prepare binary search on the left side of the index
34713                                                 right = i1;
34714                                                 i1 = 0;
34715                                                 break linear_scan;
34716
34717                                         }
34718
34719                                         // the interval is valid
34720
34721                                         break validate_interval;
34722
34723                                 } // linear scan
34724
34725                                 // binary search
34726
34727                                 while ( i1 < right ) {
34728
34729                                         const mid = ( i1 + right ) >>> 1;
34730
34731                                         if ( t < pp[ mid ] ) {
34732
34733                                                 right = mid;
34734
34735                                         } else {
34736
34737                                                 i1 = mid + 1;
34738
34739                                         }
34740
34741                                 }
34742
34743                                 t1 = pp[ i1 ];
34744                                 t0 = pp[ i1 - 1 ];
34745
34746                                 // check boundary cases, again
34747
34748                                 if ( t0 === undefined ) {
34749
34750                                         this._cachedIndex = 0;
34751                                         return this.beforeStart_( 0, t, t1 );
34752
34753                                 }
34754
34755                                 if ( t1 === undefined ) {
34756
34757                                         i1 = pp.length;
34758                                         this._cachedIndex = i1;
34759                                         return this.afterEnd_( i1 - 1, t0, t );
34760
34761                                 }
34762
34763                         } // seek
34764
34765                         this._cachedIndex = i1;
34766
34767                         this.intervalChanged_( i1, t0, t1 );
34768
34769                 } // validate_interval
34770
34771                 return this.interpolate_( i1, t0, t, t1 );
34772
34773         },
34774
34775         settings: null, // optional, subclass-specific settings structure
34776         // Note: The indirection allows central control of many interpolants.
34777
34778         // --- Protected interface
34779
34780         DefaultSettings_: {},
34781
34782         getSettings_: function () {
34783
34784                 return this.settings || this.DefaultSettings_;
34785
34786         },
34787
34788         copySampleValue_: function ( index ) {
34789
34790                 // copies a sample value to the result buffer
34791
34792                 const result = this.resultBuffer,
34793                         values = this.sampleValues,
34794                         stride = this.valueSize,
34795                         offset = index * stride;
34796
34797                 for ( let i = 0; i !== stride; ++ i ) {
34798
34799                         result[ i ] = values[ offset + i ];
34800
34801                 }
34802
34803                 return result;
34804
34805         },
34806
34807         // Template methods for derived classes:
34808
34809         interpolate_: function ( /* i1, t0, t, t1 */ ) {
34810
34811                 throw new Error( 'call to abstract method' );
34812                 // implementations shall return this.resultBuffer
34813
34814         },
34815
34816         intervalChanged_: function ( /* i1, t0, t1 */ ) {
34817
34818                 // empty
34819
34820         }
34821
34822     } );
34823
34824     // DECLARE ALIAS AFTER assign prototype
34825     Object.assign( Interpolant.prototype, {
34826
34827         //( 0, t, t0 ), returns this.resultBuffer
34828         beforeStart_: Interpolant.prototype.copySampleValue_,
34829
34830         //( N-1, tN-1, t ), returns this.resultBuffer
34831         afterEnd_: Interpolant.prototype.copySampleValue_,
34832
34833     } );
34834
34835     /**
34836      * Fast and simple cubic spline interpolant.
34837      *
34838      * It was derived from a Hermitian construction setting the first derivative
34839      * at each sample position to the linear slope between neighboring positions
34840      * over their parameter interval.
34841      */
34842
34843     function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34844
34845         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34846
34847         this._weightPrev = - 0;
34848         this._offsetPrev = - 0;
34849         this._weightNext = - 0;
34850         this._offsetNext = - 0;
34851
34852     }
34853
34854     CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34855
34856         constructor: CubicInterpolant,
34857
34858         DefaultSettings_: {
34859
34860                 endingStart: ZeroCurvatureEnding,
34861                 endingEnd: ZeroCurvatureEnding
34862
34863         },
34864
34865         intervalChanged_: function ( i1, t0, t1 ) {
34866
34867                 const pp = this.parameterPositions;
34868                 let iPrev = i1 - 2,
34869                         iNext = i1 + 1,
34870
34871                         tPrev = pp[ iPrev ],
34872                         tNext = pp[ iNext ];
34873
34874                 if ( tPrev === undefined ) {
34875
34876                         switch ( this.getSettings_().endingStart ) {
34877
34878                                 case ZeroSlopeEnding:
34879
34880                                         // f'(t0) = 0
34881                                         iPrev = i1;
34882                                         tPrev = 2 * t0 - t1;
34883
34884                                         break;
34885
34886                                 case WrapAroundEnding:
34887
34888                                         // use the other end of the curve
34889                                         iPrev = pp.length - 2;
34890                                         tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
34891
34892                                         break;
34893
34894                                 default: // ZeroCurvatureEnding
34895
34896                                         // f''(t0) = 0 a.k.a. Natural Spline
34897                                         iPrev = i1;
34898                                         tPrev = t1;
34899
34900                         }
34901
34902                 }
34903
34904                 if ( tNext === undefined ) {
34905
34906                         switch ( this.getSettings_().endingEnd ) {
34907
34908                                 case ZeroSlopeEnding:
34909
34910                                         // f'(tN) = 0
34911                                         iNext = i1;
34912                                         tNext = 2 * t1 - t0;
34913
34914                                         break;
34915
34916                                 case WrapAroundEnding:
34917
34918                                         // use the other end of the curve
34919                                         iNext = 1;
34920                                         tNext = t1 + pp[ 1 ] - pp[ 0 ];
34921
34922                                         break;
34923
34924                                 default: // ZeroCurvatureEnding
34925
34926                                         // f''(tN) = 0, a.k.a. Natural Spline
34927                                         iNext = i1 - 1;
34928                                         tNext = t0;
34929
34930                         }
34931
34932                 }
34933
34934                 const halfDt = ( t1 - t0 ) * 0.5,
34935                         stride = this.valueSize;
34936
34937                 this._weightPrev = halfDt / ( t0 - tPrev );
34938                 this._weightNext = halfDt / ( tNext - t1 );
34939                 this._offsetPrev = iPrev * stride;
34940                 this._offsetNext = iNext * stride;
34941
34942         },
34943
34944         interpolate_: function ( i1, t0, t, t1 ) {
34945
34946                 const result = this.resultBuffer,
34947                         values = this.sampleValues,
34948                         stride = this.valueSize,
34949
34950                         o1 = i1 * stride,               o0 = o1 - stride,
34951                         oP = this._offsetPrev,  oN = this._offsetNext,
34952                         wP = this._weightPrev,  wN = this._weightNext,
34953
34954                         p = ( t - t0 ) / ( t1 - t0 ),
34955                         pp = p * p,
34956                         ppp = pp * p;
34957
34958                 // evaluate polynomials
34959
34960                 const sP = - wP * ppp + 2 * wP * pp - wP * p;
34961                 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
34962                 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
34963                 const sN = wN * ppp - wN * pp;
34964
34965                 // combine data linearly
34966
34967                 for ( let i = 0; i !== stride; ++ i ) {
34968
34969                         result[ i ] =
34970                                         sP * values[ oP + i ] +
34971                                         s0 * values[ o0 + i ] +
34972                                         s1 * values[ o1 + i ] +
34973                                         sN * values[ oN + i ];
34974
34975                 }
34976
34977                 return result;
34978
34979         }
34980
34981     } );
34982
34983     function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34984
34985         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34986
34987     }
34988
34989     LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34990
34991         constructor: LinearInterpolant,
34992
34993         interpolate_: function ( i1, t0, t, t1 ) {
34994
34995                 const result = this.resultBuffer,
34996                         values = this.sampleValues,
34997                         stride = this.valueSize,
34998
34999                         offset1 = i1 * stride,
35000                         offset0 = offset1 - stride,
35001
35002                         weight1 = ( t - t0 ) / ( t1 - t0 ),
35003                         weight0 = 1 - weight1;
35004
35005                 for ( let i = 0; i !== stride; ++ i ) {
35006
35007                         result[ i ] =
35008                                         values[ offset0 + i ] * weight0 +
35009                                         values[ offset1 + i ] * weight1;
35010
35011                 }
35012
35013                 return result;
35014
35015         }
35016
35017     } );
35018
35019     /**
35020      *
35021      * Interpolant that evaluates to the sample value at the position preceeding
35022      * the parameter.
35023      */
35024
35025     function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35026
35027         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35028
35029     }
35030
35031     DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35032
35033         constructor: DiscreteInterpolant,
35034
35035         interpolate_: function ( i1 /*, t0, t, t1 */ ) {
35036
35037                 return this.copySampleValue_( i1 - 1 );
35038
35039         }
35040
35041     } );
35042
35043     function KeyframeTrack( name, times, values, interpolation ) {
35044
35045         if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
35046         if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
35047
35048         this.name = name;
35049
35050         this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
35051         this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
35052
35053         this.setInterpolation( interpolation || this.DefaultInterpolation );
35054
35055     }
35056
35057     // Static methods
35058
35059     Object.assign( KeyframeTrack, {
35060
35061         // Serialization (in static context, because of constructor invocation
35062         // and automatic invocation of .toJSON):
35063
35064         toJSON: function ( track ) {
35065
35066                 const trackType = track.constructor;
35067
35068                 let json;
35069
35070                 // derived classes can define a static toJSON method
35071                 if ( trackType.toJSON !== undefined ) {
35072
35073                         json = trackType.toJSON( track );
35074
35075                 } else {
35076
35077                         // by default, we assume the data can be serialized as-is
35078                         json = {
35079
35080                                 'name': track.name,
35081                                 'times': AnimationUtils.convertArray( track.times, Array ),
35082                                 'values': AnimationUtils.convertArray( track.values, Array )
35083
35084                         };
35085
35086                         const interpolation = track.getInterpolation();
35087
35088                         if ( interpolation !== track.DefaultInterpolation ) {
35089
35090                                 json.interpolation = interpolation;
35091
35092                         }
35093
35094                 }
35095
35096                 json.type = track.ValueTypeName; // mandatory
35097
35098                 return json;
35099
35100         }
35101
35102     } );
35103
35104     Object.assign( KeyframeTrack.prototype, {
35105
35106         constructor: KeyframeTrack,
35107
35108         TimeBufferType: Float32Array,
35109
35110         ValueBufferType: Float32Array,
35111
35112         DefaultInterpolation: InterpolateLinear,
35113
35114         InterpolantFactoryMethodDiscrete: function ( result ) {
35115
35116                 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
35117
35118         },
35119
35120         InterpolantFactoryMethodLinear: function ( result ) {
35121
35122                 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
35123
35124         },
35125
35126         InterpolantFactoryMethodSmooth: function ( result ) {
35127
35128                 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
35129
35130         },
35131
35132         setInterpolation: function ( interpolation ) {
35133
35134                 let factoryMethod;
35135
35136                 switch ( interpolation ) {
35137
35138                         case InterpolateDiscrete:
35139
35140                                 factoryMethod = this.InterpolantFactoryMethodDiscrete;
35141
35142                                 break;
35143
35144                         case InterpolateLinear:
35145
35146                                 factoryMethod = this.InterpolantFactoryMethodLinear;
35147
35148                                 break;
35149
35150                         case InterpolateSmooth:
35151
35152                                 factoryMethod = this.InterpolantFactoryMethodSmooth;
35153
35154                                 break;
35155
35156                 }
35157
35158                 if ( factoryMethod === undefined ) {
35159
35160                         const message = 'unsupported interpolation for ' +
35161                                 this.ValueTypeName + ' keyframe track named ' + this.name;
35162
35163                         if ( this.createInterpolant === undefined ) {
35164
35165                                 // fall back to default, unless the default itself is messed up
35166                                 if ( interpolation !== this.DefaultInterpolation ) {
35167
35168                                         this.setInterpolation( this.DefaultInterpolation );
35169
35170                                 } else {
35171
35172                                         throw new Error( message ); // fatal, in this case
35173
35174                                 }
35175
35176                         }
35177
35178                         console.warn( 'THREE.KeyframeTrack:', message );
35179                         return this;
35180
35181                 }
35182
35183                 this.createInterpolant = factoryMethod;
35184
35185                 return this;
35186
35187         },
35188
35189         getInterpolation: function () {
35190
35191                 switch ( this.createInterpolant ) {
35192
35193                         case this.InterpolantFactoryMethodDiscrete:
35194
35195                                 return InterpolateDiscrete;
35196
35197                         case this.InterpolantFactoryMethodLinear:
35198
35199                                 return InterpolateLinear;
35200
35201                         case this.InterpolantFactoryMethodSmooth:
35202
35203                                 return InterpolateSmooth;
35204
35205                 }
35206
35207         },
35208
35209         getValueSize: function () {
35210
35211                 return this.values.length / this.times.length;
35212
35213         },
35214
35215         // move all keyframes either forwards or backwards in time
35216         shift: function ( timeOffset ) {
35217
35218                 if ( timeOffset !== 0.0 ) {
35219
35220                         const times = this.times;
35221
35222                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
35223
35224                                 times[ i ] += timeOffset;
35225
35226                         }
35227
35228                 }
35229
35230                 return this;
35231
35232         },
35233
35234         // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
35235         scale: function ( timeScale ) {
35236
35237                 if ( timeScale !== 1.0 ) {
35238
35239                         const times = this.times;
35240
35241                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
35242
35243                                 times[ i ] *= timeScale;
35244
35245                         }
35246
35247                 }
35248
35249                 return this;
35250
35251         },
35252
35253         // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
35254         // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
35255         trim: function ( startTime, endTime ) {
35256
35257                 const times = this.times,
35258                         nKeys = times.length;
35259
35260                 let from = 0,
35261                         to = nKeys - 1;
35262
35263                 while ( from !== nKeys && times[ from ] < startTime ) {
35264
35265                         ++ from;
35266
35267                 }
35268
35269                 while ( to !== - 1 && times[ to ] > endTime ) {
35270
35271                         -- to;
35272
35273                 }
35274
35275                 ++ to; // inclusive -> exclusive bound
35276
35277                 if ( from !== 0 || to !== nKeys ) {
35278
35279                         // empty tracks are forbidden, so keep at least one keyframe
35280                         if ( from >= to ) {
35281
35282                                 to = Math.max( to, 1 );
35283                                 from = to - 1;
35284
35285                         }
35286
35287                         const stride = this.getValueSize();
35288                         this.times = AnimationUtils.arraySlice( times, from, to );
35289                         this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
35290
35291                 }
35292
35293                 return this;
35294
35295         },
35296
35297         // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
35298         validate: function () {
35299
35300                 let valid = true;
35301
35302                 const valueSize = this.getValueSize();
35303                 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
35304
35305                         console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
35306                         valid = false;
35307
35308                 }
35309
35310                 const times = this.times,
35311                         values = this.values,
35312
35313                         nKeys = times.length;
35314
35315                 if ( nKeys === 0 ) {
35316
35317                         console.error( 'THREE.KeyframeTrack: Track is empty.', this );
35318                         valid = false;
35319
35320                 }
35321
35322                 let prevTime = null;
35323
35324                 for ( let i = 0; i !== nKeys; i ++ ) {
35325
35326                         const currTime = times[ i ];
35327
35328                         if ( typeof currTime === 'number' && isNaN( currTime ) ) {
35329
35330                                 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
35331                                 valid = false;
35332                                 break;
35333
35334                         }
35335
35336                         if ( prevTime !== null && prevTime > currTime ) {
35337
35338                                 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
35339                                 valid = false;
35340                                 break;
35341
35342                         }
35343
35344                         prevTime = currTime;
35345
35346                 }
35347
35348                 if ( values !== undefined ) {
35349
35350                         if ( AnimationUtils.isTypedArray( values ) ) {
35351
35352                                 for ( let i = 0, n = values.length; i !== n; ++ i ) {
35353
35354                                         const value = values[ i ];
35355
35356                                         if ( isNaN( value ) ) {
35357
35358                                                 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
35359                                                 valid = false;
35360                                                 break;
35361
35362                                         }
35363
35364                                 }
35365
35366                         }
35367
35368                 }
35369
35370                 return valid;
35371
35372         },
35373
35374         // removes equivalent sequential keys as common in morph target sequences
35375         // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
35376         optimize: function () {
35377
35378                 // times or values may be shared with other tracks, so overwriting is unsafe
35379                 const times = AnimationUtils.arraySlice( this.times ),
35380                         values = AnimationUtils.arraySlice( this.values ),
35381                         stride = this.getValueSize(),
35382
35383                         smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
35384
35385                         lastIndex = times.length - 1;
35386
35387                 let writeIndex = 1;
35388
35389                 for ( let i = 1; i < lastIndex; ++ i ) {
35390
35391                         let keep = false;
35392
35393                         const time = times[ i ];
35394                         const timeNext = times[ i + 1 ];
35395
35396                         // remove adjacent keyframes scheduled at the same time
35397
35398                         if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
35399
35400                                 if ( ! smoothInterpolation ) {
35401
35402                                         // remove unnecessary keyframes same as their neighbors
35403
35404                                         const offset = i * stride,
35405                                                 offsetP = offset - stride,
35406                                                 offsetN = offset + stride;
35407
35408                                         for ( let j = 0; j !== stride; ++ j ) {
35409
35410                                                 const value = values[ offset + j ];
35411
35412                                                 if ( value !== values[ offsetP + j ] ||
35413                                                         value !== values[ offsetN + j ] ) {
35414
35415                                                         keep = true;
35416                                                         break;
35417
35418                                                 }
35419
35420                                         }
35421
35422                                 } else {
35423
35424                                         keep = true;
35425
35426                                 }
35427
35428                         }
35429
35430                         // in-place compaction
35431
35432                         if ( keep ) {
35433
35434                                 if ( i !== writeIndex ) {
35435
35436                                         times[ writeIndex ] = times[ i ];
35437
35438                                         const readOffset = i * stride,
35439                                                 writeOffset = writeIndex * stride;
35440
35441                                         for ( let j = 0; j !== stride; ++ j ) {
35442
35443                                                 values[ writeOffset + j ] = values[ readOffset + j ];
35444
35445                                         }
35446
35447                                 }
35448
35449                                 ++ writeIndex;
35450
35451                         }
35452
35453                 }
35454
35455                 // flush last keyframe (compaction looks ahead)
35456
35457                 if ( lastIndex > 0 ) {
35458
35459                         times[ writeIndex ] = times[ lastIndex ];
35460
35461                         for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
35462
35463                                 values[ writeOffset + j ] = values[ readOffset + j ];
35464
35465                         }
35466
35467                         ++ writeIndex;
35468
35469                 }
35470
35471                 if ( writeIndex !== times.length ) {
35472
35473                         this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
35474                         this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
35475
35476                 } else {
35477
35478                         this.times = times;
35479                         this.values = values;
35480
35481                 }
35482
35483                 return this;
35484
35485         },
35486
35487         clone: function () {
35488
35489                 const times = AnimationUtils.arraySlice( this.times, 0 );
35490                 const values = AnimationUtils.arraySlice( this.values, 0 );
35491
35492                 const TypedKeyframeTrack = this.constructor;
35493                 const track = new TypedKeyframeTrack( this.name, times, values );
35494
35495                 // Interpolant argument to constructor is not saved, so copy the factory method directly.
35496                 track.createInterpolant = this.createInterpolant;
35497
35498                 return track;
35499
35500         }
35501
35502     } );
35503
35504     /**
35505      * A Track of Boolean keyframe values.
35506      */
35507
35508     function BooleanKeyframeTrack( name, times, values ) {
35509
35510         KeyframeTrack.call( this, name, times, values );
35511
35512     }
35513
35514     BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35515
35516         constructor: BooleanKeyframeTrack,
35517
35518         ValueTypeName: 'bool',
35519         ValueBufferType: Array,
35520
35521         DefaultInterpolation: InterpolateDiscrete,
35522
35523         InterpolantFactoryMethodLinear: undefined,
35524         InterpolantFactoryMethodSmooth: undefined
35525
35526         // Note: Actually this track could have a optimized / compressed
35527         // representation of a single value and a custom interpolant that
35528         // computes "firstValue ^ isOdd( index )".
35529
35530     } );
35531
35532     /**
35533      * A Track of keyframe values that represent color.
35534      */
35535
35536     function ColorKeyframeTrack( name, times, values, interpolation ) {
35537
35538         KeyframeTrack.call( this, name, times, values, interpolation );
35539
35540     }
35541
35542     ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35543
35544         constructor: ColorKeyframeTrack,
35545
35546         ValueTypeName: 'color'
35547
35548         // ValueBufferType is inherited
35549
35550         // DefaultInterpolation is inherited
35551
35552         // Note: Very basic implementation and nothing special yet.
35553         // However, this is the place for color space parameterization.
35554
35555     } );
35556
35557     /**
35558      * A Track of numeric keyframe values.
35559      */
35560
35561     function NumberKeyframeTrack( name, times, values, interpolation ) {
35562
35563         KeyframeTrack.call( this, name, times, values, interpolation );
35564
35565     }
35566
35567     NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35568
35569         constructor: NumberKeyframeTrack,
35570
35571         ValueTypeName: 'number'
35572
35573         // ValueBufferType is inherited
35574
35575         // DefaultInterpolation is inherited
35576
35577     } );
35578
35579     /**
35580      * Spherical linear unit quaternion interpolant.
35581      */
35582
35583     function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35584
35585         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35586
35587     }
35588
35589     QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35590
35591         constructor: QuaternionLinearInterpolant,
35592
35593         interpolate_: function ( i1, t0, t, t1 ) {
35594
35595                 const result = this.resultBuffer,
35596                         values = this.sampleValues,
35597                         stride = this.valueSize,
35598
35599                         alpha = ( t - t0 ) / ( t1 - t0 );
35600
35601                 let offset = i1 * stride;
35602
35603                 for ( let end = offset + stride; offset !== end; offset += 4 ) {
35604
35605                         Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
35606
35607                 }
35608
35609                 return result;
35610
35611         }
35612
35613     } );
35614
35615     /**
35616      * A Track of quaternion keyframe values.
35617      */
35618
35619     function QuaternionKeyframeTrack( name, times, values, interpolation ) {
35620
35621         KeyframeTrack.call( this, name, times, values, interpolation );
35622
35623     }
35624
35625     QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35626
35627         constructor: QuaternionKeyframeTrack,
35628
35629         ValueTypeName: 'quaternion',
35630
35631         // ValueBufferType is inherited
35632
35633         DefaultInterpolation: InterpolateLinear,
35634
35635         InterpolantFactoryMethodLinear: function ( result ) {
35636
35637                 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
35638
35639         },
35640
35641         InterpolantFactoryMethodSmooth: undefined // not yet implemented
35642
35643     } );
35644
35645     /**
35646      * A Track that interpolates Strings
35647      */
35648
35649     function StringKeyframeTrack( name, times, values, interpolation ) {
35650
35651         KeyframeTrack.call( this, name, times, values, interpolation );
35652
35653     }
35654
35655     StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35656
35657         constructor: StringKeyframeTrack,
35658
35659         ValueTypeName: 'string',
35660         ValueBufferType: Array,
35661
35662         DefaultInterpolation: InterpolateDiscrete,
35663
35664         InterpolantFactoryMethodLinear: undefined,
35665
35666         InterpolantFactoryMethodSmooth: undefined
35667
35668     } );
35669
35670     /**
35671      * A Track of vectored keyframe values.
35672      */
35673
35674     function VectorKeyframeTrack( name, times, values, interpolation ) {
35675
35676         KeyframeTrack.call( this, name, times, values, interpolation );
35677
35678     }
35679
35680     VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35681
35682         constructor: VectorKeyframeTrack,
35683
35684         ValueTypeName: 'vector'
35685
35686         // ValueBufferType is inherited
35687
35688         // DefaultInterpolation is inherited
35689
35690     } );
35691
35692     function AnimationClip( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
35693
35694         this.name = name;
35695         this.tracks = tracks;
35696         this.duration = duration;
35697         this.blendMode = blendMode;
35698
35699         this.uuid = MathUtils.generateUUID();
35700
35701         // this means it should figure out its duration by scanning the tracks
35702         if ( this.duration < 0 ) {
35703
35704                 this.resetDuration();
35705
35706         }
35707
35708     }
35709
35710     function getTrackTypeForValueTypeName( typeName ) {
35711
35712         switch ( typeName.toLowerCase() ) {
35713
35714                 case 'scalar':
35715                 case 'double':
35716                 case 'float':
35717                 case 'number':
35718                 case 'integer':
35719
35720                         return NumberKeyframeTrack;
35721
35722                 case 'vector':
35723                 case 'vector2':
35724                 case 'vector3':
35725                 case 'vector4':
35726
35727                         return VectorKeyframeTrack;
35728
35729                 case 'color':
35730
35731                         return ColorKeyframeTrack;
35732
35733                 case 'quaternion':
35734
35735                         return QuaternionKeyframeTrack;
35736
35737                 case 'bool':
35738                 case 'boolean':
35739
35740                         return BooleanKeyframeTrack;
35741
35742                 case 'string':
35743
35744                         return StringKeyframeTrack;
35745
35746         }
35747
35748         throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
35749
35750     }
35751
35752     function parseKeyframeTrack( json ) {
35753
35754         if ( json.type === undefined ) {
35755
35756                 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
35757
35758         }
35759
35760         const trackType = getTrackTypeForValueTypeName( json.type );
35761
35762         if ( json.times === undefined ) {
35763
35764                 const times = [], values = [];
35765
35766                 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
35767
35768                 json.times = times;
35769                 json.values = values;
35770
35771         }
35772
35773         // derived classes can define a static parse method
35774         if ( trackType.parse !== undefined ) {
35775
35776                 return trackType.parse( json );
35777
35778         } else {
35779
35780                 // by default, we assume a constructor compatible with the base
35781                 return new trackType( json.name, json.times, json.values, json.interpolation );
35782
35783         }
35784
35785     }
35786
35787     Object.assign( AnimationClip, {
35788
35789         parse: function ( json ) {
35790
35791                 const tracks = [],
35792                         jsonTracks = json.tracks,
35793                         frameTime = 1.0 / ( json.fps || 1.0 );
35794
35795                 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
35796
35797                         tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
35798
35799                 }
35800
35801                 const clip = new AnimationClip( json.name, json.duration, tracks, json.blendMode );
35802                 clip.uuid = json.uuid;
35803
35804                 return clip;
35805
35806         },
35807
35808         toJSON: function ( clip ) {
35809
35810                 const tracks = [],
35811                         clipTracks = clip.tracks;
35812
35813                 const json = {
35814
35815                         'name': clip.name,
35816                         'duration': clip.duration,
35817                         'tracks': tracks,
35818                         'uuid': clip.uuid,
35819                         'blendMode': clip.blendMode
35820
35821                 };
35822
35823                 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
35824
35825                         tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
35826
35827                 }
35828
35829                 return json;
35830
35831         },
35832
35833         CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
35834
35835                 const numMorphTargets = morphTargetSequence.length;
35836                 const tracks = [];
35837
35838                 for ( let i = 0; i < numMorphTargets; i ++ ) {
35839
35840                         let times = [];
35841                         let values = [];
35842
35843                         times.push(
35844                                 ( i + numMorphTargets - 1 ) % numMorphTargets,
35845                                 i,
35846                                 ( i + 1 ) % numMorphTargets );
35847
35848                         values.push( 0, 1, 0 );
35849
35850                         const order = AnimationUtils.getKeyframeOrder( times );
35851                         times = AnimationUtils.sortedArray( times, 1, order );
35852                         values = AnimationUtils.sortedArray( values, 1, order );
35853
35854                         // if there is a key at the first frame, duplicate it as the
35855                         // last frame as well for perfect loop.
35856                         if ( ! noLoop && times[ 0 ] === 0 ) {
35857
35858                                 times.push( numMorphTargets );
35859                                 values.push( values[ 0 ] );
35860
35861                         }
35862
35863                         tracks.push(
35864                                 new NumberKeyframeTrack(
35865                                         '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
35866                                         times, values
35867                                 ).scale( 1.0 / fps ) );
35868
35869                 }
35870
35871                 return new AnimationClip( name, - 1, tracks );
35872
35873         },
35874
35875         findByName: function ( objectOrClipArray, name ) {
35876
35877                 let clipArray = objectOrClipArray;
35878
35879                 if ( ! Array.isArray( objectOrClipArray ) ) {
35880
35881                         const o = objectOrClipArray;
35882                         clipArray = o.geometry && o.geometry.animations || o.animations;
35883
35884                 }
35885
35886                 for ( let i = 0; i < clipArray.length; i ++ ) {
35887
35888                         if ( clipArray[ i ].name === name ) {
35889
35890                                 return clipArray[ i ];
35891
35892                         }
35893
35894                 }
35895
35896                 return null;
35897
35898         },
35899
35900         CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
35901
35902                 const animationToMorphTargets = {};
35903
35904                 // tested with https://regex101.com/ on trick sequences
35905                 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
35906                 const pattern = /^([\w-]*?)([\d]+)$/;
35907
35908                 // sort morph target names into animation groups based
35909                 // patterns like Walk_001, Walk_002, Run_001, Run_002
35910                 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
35911
35912                         const morphTarget = morphTargets[ i ];
35913                         const parts = morphTarget.name.match( pattern );
35914
35915                         if ( parts && parts.length > 1 ) {
35916
35917                                 const name = parts[ 1 ];
35918
35919                                 let animationMorphTargets = animationToMorphTargets[ name ];
35920
35921                                 if ( ! animationMorphTargets ) {
35922
35923                                         animationToMorphTargets[ name ] = animationMorphTargets = [];
35924
35925                                 }
35926
35927                                 animationMorphTargets.push( morphTarget );
35928
35929                         }
35930
35931                 }
35932
35933                 const clips = [];
35934
35935                 for ( const name in animationToMorphTargets ) {
35936
35937                         clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
35938
35939                 }
35940
35941                 return clips;
35942
35943         },
35944
35945         // parse the animation.hierarchy format
35946         parseAnimation: function ( animation, bones ) {
35947
35948                 if ( ! animation ) {
35949
35950                         console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
35951                         return null;
35952
35953                 }
35954
35955                 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
35956
35957                         // only return track if there are actually keys.
35958                         if ( animationKeys.length !== 0 ) {
35959
35960                                 const times = [];
35961                                 const values = [];
35962
35963                                 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
35964
35965                                 // empty keys are filtered out, so check again
35966                                 if ( times.length !== 0 ) {
35967
35968                                         destTracks.push( new trackType( trackName, times, values ) );
35969
35970                                 }
35971
35972                         }
35973
35974                 };
35975
35976                 const tracks = [];
35977
35978                 const clipName = animation.name || 'default';
35979                 const fps = animation.fps || 30;
35980                 const blendMode = animation.blendMode;
35981
35982                 // automatic length determination in AnimationClip.
35983                 let duration = animation.length || - 1;
35984
35985                 const hierarchyTracks = animation.hierarchy || [];
35986
35987                 for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
35988
35989                         const animationKeys = hierarchyTracks[ h ].keys;
35990
35991                         // skip empty tracks
35992                         if ( ! animationKeys || animationKeys.length === 0 ) continue;
35993
35994                         // process morph targets
35995                         if ( animationKeys[ 0 ].morphTargets ) {
35996
35997                                 // figure out all morph targets used in this track
35998                                 const morphTargetNames = {};
35999
36000                                 let k;
36001
36002                                 for ( k = 0; k < animationKeys.length; k ++ ) {
36003
36004                                         if ( animationKeys[ k ].morphTargets ) {
36005
36006                                                 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
36007
36008                                                         morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
36009
36010                                                 }
36011
36012                                         }
36013
36014                                 }
36015
36016                                 // create a track for each morph target with all zero
36017                                 // morphTargetInfluences except for the keys in which
36018                                 // the morphTarget is named.
36019                                 for ( const morphTargetName in morphTargetNames ) {
36020
36021                                         const times = [];
36022                                         const values = [];
36023
36024                                         for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
36025
36026                                                 const animationKey = animationKeys[ k ];
36027
36028                                                 times.push( animationKey.time );
36029                                                 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
36030
36031                                         }
36032
36033                                         tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
36034
36035                                 }
36036
36037                                 duration = morphTargetNames.length * ( fps || 1.0 );
36038
36039                         } else {
36040
36041                                 // ...assume skeletal animation
36042
36043                                 const boneName = '.bones[' + bones[ h ].name + ']';
36044
36045                                 addNonemptyTrack(
36046                                         VectorKeyframeTrack, boneName + '.position',
36047                                         animationKeys, 'pos', tracks );
36048
36049                                 addNonemptyTrack(
36050                                         QuaternionKeyframeTrack, boneName + '.quaternion',
36051                                         animationKeys, 'rot', tracks );
36052
36053                                 addNonemptyTrack(
36054                                         VectorKeyframeTrack, boneName + '.scale',
36055                                         animationKeys, 'scl', tracks );
36056
36057                         }
36058
36059                 }
36060
36061                 if ( tracks.length === 0 ) {
36062
36063                         return null;
36064
36065                 }
36066
36067                 const clip = new AnimationClip( clipName, duration, tracks, blendMode );
36068
36069                 return clip;
36070
36071         }
36072
36073     } );
36074
36075     Object.assign( AnimationClip.prototype, {
36076
36077         resetDuration: function () {
36078
36079                 const tracks = this.tracks;
36080                 let duration = 0;
36081
36082                 for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
36083
36084                         const track = this.tracks[ i ];
36085
36086                         duration = Math.max( duration, track.times[ track.times.length - 1 ] );
36087
36088                 }
36089
36090                 this.duration = duration;
36091
36092                 return this;
36093
36094         },
36095
36096         trim: function () {
36097
36098                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36099
36100                         this.tracks[ i ].trim( 0, this.duration );
36101
36102                 }
36103
36104                 return this;
36105
36106         },
36107
36108         validate: function () {
36109
36110                 let valid = true;
36111
36112                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36113
36114                         valid = valid && this.tracks[ i ].validate();
36115
36116                 }
36117
36118                 return valid;
36119
36120         },
36121
36122         optimize: function () {
36123
36124                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36125
36126                         this.tracks[ i ].optimize();
36127
36128                 }
36129
36130                 return this;
36131
36132         },
36133
36134         clone: function () {
36135
36136                 const tracks = [];
36137
36138                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36139
36140                         tracks.push( this.tracks[ i ].clone() );
36141
36142                 }
36143
36144                 return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
36145
36146         },
36147
36148         toJSON: function () {
36149
36150                 return AnimationClip.toJSON( this );
36151
36152         }
36153
36154     } );
36155
36156     const Cache = {
36157
36158         enabled: false,
36159
36160         files: {},
36161
36162         add: function ( key, file ) {
36163
36164                 if ( this.enabled === false ) return;
36165
36166                 // console.log( 'THREE.Cache', 'Adding key:', key );
36167
36168                 this.files[ key ] = file;
36169
36170         },
36171
36172         get: function ( key ) {
36173
36174                 if ( this.enabled === false ) return;
36175
36176                 // console.log( 'THREE.Cache', 'Checking key:', key );
36177
36178                 return this.files[ key ];
36179
36180         },
36181
36182         remove: function ( key ) {
36183
36184                 delete this.files[ key ];
36185
36186         },
36187
36188         clear: function () {
36189
36190                 this.files = {};
36191
36192         }
36193
36194     };
36195
36196     function LoadingManager( onLoad, onProgress, onError ) {
36197
36198         const scope = this;
36199
36200         let isLoading = false;
36201         let itemsLoaded = 0;
36202         let itemsTotal = 0;
36203         let urlModifier = undefined;
36204         const handlers = [];
36205
36206         // Refer to #5689 for the reason why we don't set .onStart
36207         // in the constructor
36208
36209         this.onStart = undefined;
36210         this.onLoad = onLoad;
36211         this.onProgress = onProgress;
36212         this.onError = onError;
36213
36214         this.itemStart = function ( url ) {
36215
36216                 itemsTotal ++;
36217
36218                 if ( isLoading === false ) {
36219
36220                         if ( scope.onStart !== undefined ) {
36221
36222                                 scope.onStart( url, itemsLoaded, itemsTotal );
36223
36224                         }
36225
36226                 }
36227
36228                 isLoading = true;
36229
36230         };
36231
36232         this.itemEnd = function ( url ) {
36233
36234                 itemsLoaded ++;
36235
36236                 if ( scope.onProgress !== undefined ) {
36237
36238                         scope.onProgress( url, itemsLoaded, itemsTotal );
36239
36240                 }
36241
36242                 if ( itemsLoaded === itemsTotal ) {
36243
36244                         isLoading = false;
36245
36246                         if ( scope.onLoad !== undefined ) {
36247
36248                                 scope.onLoad();
36249
36250                         }
36251
36252                 }
36253
36254         };
36255
36256         this.itemError = function ( url ) {
36257
36258                 if ( scope.onError !== undefined ) {
36259
36260                         scope.onError( url );
36261
36262                 }
36263
36264         };
36265
36266         this.resolveURL = function ( url ) {
36267
36268                 if ( urlModifier ) {
36269
36270                         return urlModifier( url );
36271
36272                 }
36273
36274                 return url;
36275
36276         };
36277
36278         this.setURLModifier = function ( transform ) {
36279
36280                 urlModifier = transform;
36281
36282                 return this;
36283
36284         };
36285
36286         this.addHandler = function ( regex, loader ) {
36287
36288                 handlers.push( regex, loader );
36289
36290                 return this;
36291
36292         };
36293
36294         this.removeHandler = function ( regex ) {
36295
36296                 const index = handlers.indexOf( regex );
36297
36298                 if ( index !== - 1 ) {
36299
36300                         handlers.splice( index, 2 );
36301
36302                 }
36303
36304                 return this;
36305
36306         };
36307
36308         this.getHandler = function ( file ) {
36309
36310                 for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
36311
36312                         const regex = handlers[ i ];
36313                         const loader = handlers[ i + 1 ];
36314
36315                         if ( regex.global ) regex.lastIndex = 0; // see #17920
36316
36317                         if ( regex.test( file ) ) {
36318
36319                                 return loader;
36320
36321                         }
36322
36323                 }
36324
36325                 return null;
36326
36327         };
36328
36329     }
36330
36331     const DefaultLoadingManager = new LoadingManager();
36332
36333     function Loader( manager ) {
36334
36335         this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36336
36337         this.crossOrigin = 'anonymous';
36338         this.withCredentials = false;
36339         this.path = '';
36340         this.resourcePath = '';
36341         this.requestHeader = {};
36342
36343     }
36344
36345     Object.assign( Loader.prototype, {
36346
36347         load: function ( /* url, onLoad, onProgress, onError */ ) {},
36348
36349         loadAsync: function ( url, onProgress ) {
36350
36351                 const scope = this;
36352
36353                 return new Promise( function ( resolve, reject ) {
36354
36355                         scope.load( url, resolve, onProgress, reject );
36356
36357                 } );
36358
36359         },
36360
36361         parse: function ( /* data */ ) {},
36362
36363         setCrossOrigin: function ( crossOrigin ) {
36364
36365                 this.crossOrigin = crossOrigin;
36366                 return this;
36367
36368         },
36369
36370         setWithCredentials: function ( value ) {
36371
36372                 this.withCredentials = value;
36373                 return this;
36374
36375         },
36376
36377         setPath: function ( path ) {
36378
36379                 this.path = path;
36380                 return this;
36381
36382         },
36383
36384         setResourcePath: function ( resourcePath ) {
36385
36386                 this.resourcePath = resourcePath;
36387                 return this;
36388
36389         },
36390
36391         setRequestHeader: function ( requestHeader ) {
36392
36393                 this.requestHeader = requestHeader;
36394                 return this;
36395
36396         }
36397
36398     } );
36399
36400     const loading = {};
36401
36402     function FileLoader( manager ) {
36403
36404         Loader.call( this, manager );
36405
36406     }
36407
36408     FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36409
36410         constructor: FileLoader,
36411
36412         load: function ( url, onLoad, onProgress, onError ) {
36413
36414                 if ( url === undefined ) url = '';
36415
36416                 if ( this.path !== undefined ) url = this.path + url;
36417
36418                 url = this.manager.resolveURL( url );
36419
36420                 const scope = this;
36421
36422                 const cached = Cache.get( url );
36423
36424                 if ( cached !== undefined ) {
36425
36426                         scope.manager.itemStart( url );
36427
36428                         setTimeout( function () {
36429
36430                                 if ( onLoad ) onLoad( cached );
36431
36432                                 scope.manager.itemEnd( url );
36433
36434                         }, 0 );
36435
36436                         return cached;
36437
36438                 }
36439
36440                 // Check if request is duplicate
36441
36442                 if ( loading[ url ] !== undefined ) {
36443
36444                         loading[ url ].push( {
36445
36446                                 onLoad: onLoad,
36447                                 onProgress: onProgress,
36448                                 onError: onError
36449
36450                         } );
36451
36452                         return;
36453
36454                 }
36455
36456                 // Check for data: URI
36457                 const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
36458                 const dataUriRegexResult = url.match( dataUriRegex );
36459                 let request;
36460
36461                 // Safari can not handle Data URIs through XMLHttpRequest so process manually
36462                 if ( dataUriRegexResult ) {
36463
36464                         const mimeType = dataUriRegexResult[ 1 ];
36465                         const isBase64 = !! dataUriRegexResult[ 2 ];
36466
36467                         let data = dataUriRegexResult[ 3 ];
36468                         data = decodeURIComponent( data );
36469
36470                         if ( isBase64 ) data = atob( data );
36471
36472                         try {
36473
36474                                 let response;
36475                                 const responseType = ( this.responseType || '' ).toLowerCase();
36476
36477                                 switch ( responseType ) {
36478
36479                                         case 'arraybuffer':
36480                                         case 'blob':
36481
36482                                                 const view = new Uint8Array( data.length );
36483
36484                                                 for ( let i = 0; i < data.length; i ++ ) {
36485
36486                                                         view[ i ] = data.charCodeAt( i );
36487
36488                                                 }
36489
36490                                                 if ( responseType === 'blob' ) {
36491
36492                                                         response = new Blob( [ view.buffer ], { type: mimeType } );
36493
36494                                                 } else {
36495
36496                                                         response = view.buffer;
36497
36498                                                 }
36499
36500                                                 break;
36501
36502                                         case 'document':
36503
36504                                                 const parser = new DOMParser();
36505                                                 response = parser.parseFromString( data, mimeType );
36506
36507                                                 break;
36508
36509                                         case 'json':
36510
36511                                                 response = JSON.parse( data );
36512
36513                                                 break;
36514
36515                                         default: // 'text' or other
36516
36517                                                 response = data;
36518
36519                                                 break;
36520
36521                                 }
36522
36523                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
36524                                 setTimeout( function () {
36525
36526                                         if ( onLoad ) onLoad( response );
36527
36528                                         scope.manager.itemEnd( url );
36529
36530                                 }, 0 );
36531
36532                         } catch ( error ) {
36533
36534                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
36535                                 setTimeout( function () {
36536
36537                                         if ( onError ) onError( error );
36538
36539                                         scope.manager.itemError( url );
36540                                         scope.manager.itemEnd( url );
36541
36542                                 }, 0 );
36543
36544                         }
36545
36546                 } else {
36547
36548                         // Initialise array for duplicate requests
36549
36550                         loading[ url ] = [];
36551
36552                         loading[ url ].push( {
36553
36554                                 onLoad: onLoad,
36555                                 onProgress: onProgress,
36556                                 onError: onError
36557
36558                         } );
36559
36560                         request = new XMLHttpRequest();
36561
36562                         request.open( 'GET', url, true );
36563
36564                         request.addEventListener( 'load', function ( event ) {
36565
36566                                 const response = this.response;
36567
36568                                 const callbacks = loading[ url ];
36569
36570                                 delete loading[ url ];
36571
36572                                 if ( this.status === 200 || this.status === 0 ) {
36573
36574                                         // Some browsers return HTTP Status 0 when using non-http protocol
36575                                         // e.g. 'file://' or 'data://'. Handle as success.
36576
36577                                         if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
36578
36579                                         // Add to cache only on HTTP success, so that we do not cache
36580                                         // error response bodies as proper responses to requests.
36581                                         Cache.add( url, response );
36582
36583                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36584
36585                                                 const callback = callbacks[ i ];
36586                                                 if ( callback.onLoad ) callback.onLoad( response );
36587
36588                                         }
36589
36590                                         scope.manager.itemEnd( url );
36591
36592                                 } else {
36593
36594                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36595
36596                                                 const callback = callbacks[ i ];
36597                                                 if ( callback.onError ) callback.onError( event );
36598
36599                                         }
36600
36601                                         scope.manager.itemError( url );
36602                                         scope.manager.itemEnd( url );
36603
36604                                 }
36605
36606                         }, false );
36607
36608                         request.addEventListener( 'progress', function ( event ) {
36609
36610                                 const callbacks = loading[ url ];
36611
36612                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36613
36614                                         const callback = callbacks[ i ];
36615                                         if ( callback.onProgress ) callback.onProgress( event );
36616
36617                                 }
36618
36619                         }, false );
36620
36621                         request.addEventListener( 'error', function ( event ) {
36622
36623                                 const callbacks = loading[ url ];
36624
36625                                 delete loading[ url ];
36626
36627                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36628
36629                                         const callback = callbacks[ i ];
36630                                         if ( callback.onError ) callback.onError( event );
36631
36632                                 }
36633
36634                                 scope.manager.itemError( url );
36635                                 scope.manager.itemEnd( url );
36636
36637                         }, false );
36638
36639                         request.addEventListener( 'abort', function ( event ) {
36640
36641                                 const callbacks = loading[ url ];
36642
36643                                 delete loading[ url ];
36644
36645                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36646
36647                                         const callback = callbacks[ i ];
36648                                         if ( callback.onError ) callback.onError( event );
36649
36650                                 }
36651
36652                                 scope.manager.itemError( url );
36653                                 scope.manager.itemEnd( url );
36654
36655                         }, false );
36656
36657                         if ( this.responseType !== undefined ) request.responseType = this.responseType;
36658                         if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
36659
36660                         if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
36661
36662                         for ( const header in this.requestHeader ) {
36663
36664                                 request.setRequestHeader( header, this.requestHeader[ header ] );
36665
36666                         }
36667
36668                         request.send( null );
36669
36670                 }
36671
36672                 scope.manager.itemStart( url );
36673
36674                 return request;
36675
36676         },
36677
36678         setResponseType: function ( value ) {
36679
36680                 this.responseType = value;
36681                 return this;
36682
36683         },
36684
36685         setMimeType: function ( value ) {
36686
36687                 this.mimeType = value;
36688                 return this;
36689
36690         }
36691
36692     } );
36693
36694     function AnimationLoader( manager ) {
36695
36696         Loader.call( this, manager );
36697
36698     }
36699
36700     AnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36701
36702         constructor: AnimationLoader,
36703
36704         load: function ( url, onLoad, onProgress, onError ) {
36705
36706                 const scope = this;
36707
36708                 const loader = new FileLoader( scope.manager );
36709                 loader.setPath( scope.path );
36710                 loader.setRequestHeader( scope.requestHeader );
36711                 loader.setWithCredentials( scope.withCredentials );
36712                 loader.load( url, function ( text ) {
36713
36714                         try {
36715
36716                                 onLoad( scope.parse( JSON.parse( text ) ) );
36717
36718                         } catch ( e ) {
36719
36720                                 if ( onError ) {
36721
36722                                         onError( e );
36723
36724                                 } else {
36725
36726                                         console.error( e );
36727
36728                                 }
36729
36730                                 scope.manager.itemError( url );
36731
36732                         }
36733
36734                 }, onProgress, onError );
36735
36736         },
36737
36738         parse: function ( json ) {
36739
36740                 const animations = [];
36741
36742                 for ( let i = 0; i < json.length; i ++ ) {
36743
36744                         const clip = AnimationClip.parse( json[ i ] );
36745
36746                         animations.push( clip );
36747
36748                 }
36749
36750                 return animations;
36751
36752         }
36753
36754     } );
36755
36756     /**
36757      * Abstract Base class to block based textures loader (dds, pvr, ...)
36758      *
36759      * Sub classes have to implement the parse() method which will be used in load().
36760      */
36761
36762     function CompressedTextureLoader( manager ) {
36763
36764         Loader.call( this, manager );
36765
36766     }
36767
36768     CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36769
36770         constructor: CompressedTextureLoader,
36771
36772         load: function ( url, onLoad, onProgress, onError ) {
36773
36774                 const scope = this;
36775
36776                 const images = [];
36777
36778                 const texture = new CompressedTexture();
36779
36780                 const loader = new FileLoader( this.manager );
36781                 loader.setPath( this.path );
36782                 loader.setResponseType( 'arraybuffer' );
36783                 loader.setRequestHeader( this.requestHeader );
36784                 loader.setWithCredentials( scope.withCredentials );
36785
36786                 let loaded = 0;
36787
36788                 function loadTexture( i ) {
36789
36790                         loader.load( url[ i ], function ( buffer ) {
36791
36792                                 const texDatas = scope.parse( buffer, true );
36793
36794                                 images[ i ] = {
36795                                         width: texDatas.width,
36796                                         height: texDatas.height,
36797                                         format: texDatas.format,
36798                                         mipmaps: texDatas.mipmaps
36799                                 };
36800
36801                                 loaded += 1;
36802
36803                                 if ( loaded === 6 ) {
36804
36805                                         if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
36806
36807                                         texture.image = images;
36808                                         texture.format = texDatas.format;
36809                                         texture.needsUpdate = true;
36810
36811                                         if ( onLoad ) onLoad( texture );
36812
36813                                 }
36814
36815                         }, onProgress, onError );
36816
36817                 }
36818
36819                 if ( Array.isArray( url ) ) {
36820
36821                         for ( let i = 0, il = url.length; i < il; ++ i ) {
36822
36823                                 loadTexture( i );
36824
36825                         }
36826
36827                 } else {
36828
36829                         // compressed cubemap texture stored in a single DDS file
36830
36831                         loader.load( url, function ( buffer ) {
36832
36833                                 const texDatas = scope.parse( buffer, true );
36834
36835                                 if ( texDatas.isCubemap ) {
36836
36837                                         const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
36838
36839                                         for ( let f = 0; f < faces; f ++ ) {
36840
36841                                                 images[ f ] = { mipmaps: [] };
36842
36843                                                 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
36844
36845                                                         images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
36846                                                         images[ f ].format = texDatas.format;
36847                                                         images[ f ].width = texDatas.width;
36848                                                         images[ f ].height = texDatas.height;
36849
36850                                                 }
36851
36852                                         }
36853
36854                                         texture.image = images;
36855
36856                                 } else {
36857
36858                                         texture.image.width = texDatas.width;
36859                                         texture.image.height = texDatas.height;
36860                                         texture.mipmaps = texDatas.mipmaps;
36861
36862                                 }
36863
36864                                 if ( texDatas.mipmapCount === 1 ) {
36865
36866                                         texture.minFilter = LinearFilter;
36867
36868                                 }
36869
36870                                 texture.format = texDatas.format;
36871                                 texture.needsUpdate = true;
36872
36873                                 if ( onLoad ) onLoad( texture );
36874
36875                         }, onProgress, onError );
36876
36877                 }
36878
36879                 return texture;
36880
36881         }
36882
36883     } );
36884
36885     function ImageLoader( manager ) {
36886
36887         Loader.call( this, manager );
36888
36889     }
36890
36891     ImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36892
36893         constructor: ImageLoader,
36894
36895         load: function ( url, onLoad, onProgress, onError ) {
36896
36897                 if ( this.path !== undefined ) url = this.path + url;
36898
36899                 url = this.manager.resolveURL( url );
36900
36901                 const scope = this;
36902
36903                 const cached = Cache.get( url );
36904
36905                 if ( cached !== undefined ) {
36906
36907                         scope.manager.itemStart( url );
36908
36909                         setTimeout( function () {
36910
36911                                 if ( onLoad ) onLoad( cached );
36912
36913                                 scope.manager.itemEnd( url );
36914
36915                         }, 0 );
36916
36917                         return cached;
36918
36919                 }
36920
36921                 const image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
36922
36923                 function onImageLoad() {
36924
36925                         image.removeEventListener( 'load', onImageLoad, false );
36926                         image.removeEventListener( 'error', onImageError, false );
36927
36928                         Cache.add( url, this );
36929
36930                         if ( onLoad ) onLoad( this );
36931
36932                         scope.manager.itemEnd( url );
36933
36934                 }
36935
36936                 function onImageError( event ) {
36937
36938                         image.removeEventListener( 'load', onImageLoad, false );
36939                         image.removeEventListener( 'error', onImageError, false );
36940
36941                         if ( onError ) onError( event );
36942
36943                         scope.manager.itemError( url );
36944                         scope.manager.itemEnd( url );
36945
36946                 }
36947
36948                 image.addEventListener( 'load', onImageLoad, false );
36949                 image.addEventListener( 'error', onImageError, false );
36950
36951                 if ( url.substr( 0, 5 ) !== 'data:' ) {
36952
36953                         if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
36954
36955                 }
36956
36957                 scope.manager.itemStart( url );
36958
36959                 image.src = url;
36960
36961                 return image;
36962
36963         }
36964
36965     } );
36966
36967     function CubeTextureLoader( manager ) {
36968
36969         Loader.call( this, manager );
36970
36971     }
36972
36973     CubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36974
36975         constructor: CubeTextureLoader,
36976
36977         load: function ( urls, onLoad, onProgress, onError ) {
36978
36979                 const texture = new CubeTexture();
36980
36981                 const loader = new ImageLoader( this.manager );
36982                 loader.setCrossOrigin( this.crossOrigin );
36983                 loader.setPath( this.path );
36984
36985                 let loaded = 0;
36986
36987                 function loadTexture( i ) {
36988
36989                         loader.load( urls[ i ], function ( image ) {
36990
36991                                 texture.images[ i ] = image;
36992
36993                                 loaded ++;
36994
36995                                 if ( loaded === 6 ) {
36996
36997                                         texture.needsUpdate = true;
36998
36999                                         if ( onLoad ) onLoad( texture );
37000
37001                                 }
37002
37003                         }, undefined, onError );
37004
37005                 }
37006
37007                 for ( let i = 0; i < urls.length; ++ i ) {
37008
37009                         loadTexture( i );
37010
37011                 }
37012
37013                 return texture;
37014
37015         }
37016
37017     } );
37018
37019     /**
37020      * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
37021      *
37022      * Sub classes have to implement the parse() method which will be used in load().
37023      */
37024
37025     function DataTextureLoader( manager ) {
37026
37027         Loader.call( this, manager );
37028
37029     }
37030
37031     DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37032
37033         constructor: DataTextureLoader,
37034
37035         load: function ( url, onLoad, onProgress, onError ) {
37036
37037                 const scope = this;
37038
37039                 const texture = new DataTexture();
37040
37041                 const loader = new FileLoader( this.manager );
37042                 loader.setResponseType( 'arraybuffer' );
37043                 loader.setRequestHeader( this.requestHeader );
37044                 loader.setPath( this.path );
37045                 loader.setWithCredentials( scope.withCredentials );
37046                 loader.load( url, function ( buffer ) {
37047
37048                         const texData = scope.parse( buffer );
37049
37050                         if ( ! texData ) return;
37051
37052                         if ( texData.image !== undefined ) {
37053
37054                                 texture.image = texData.image;
37055
37056                         } else if ( texData.data !== undefined ) {
37057
37058                                 texture.image.width = texData.width;
37059                                 texture.image.height = texData.height;
37060                                 texture.image.data = texData.data;
37061
37062                         }
37063
37064                         texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
37065                         texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
37066
37067                         texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
37068                         texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
37069
37070                         texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
37071
37072                         if ( texData.encoding !== undefined ) {
37073
37074                                 texture.encoding = texData.encoding;
37075
37076                         }
37077
37078                         if ( texData.flipY !== undefined ) {
37079
37080                                 texture.flipY = texData.flipY;
37081
37082                         }
37083
37084                         if ( texData.format !== undefined ) {
37085
37086                                 texture.format = texData.format;
37087
37088                         }
37089
37090                         if ( texData.type !== undefined ) {
37091
37092                                 texture.type = texData.type;
37093
37094                         }
37095
37096                         if ( texData.mipmaps !== undefined ) {
37097
37098                                 texture.mipmaps = texData.mipmaps;
37099                                 texture.minFilter = LinearMipmapLinearFilter; // presumably...
37100
37101                         }
37102
37103                         if ( texData.mipmapCount === 1 ) {
37104
37105                                 texture.minFilter = LinearFilter;
37106
37107                         }
37108
37109                         texture.needsUpdate = true;
37110
37111                         if ( onLoad ) onLoad( texture, texData );
37112
37113                 }, onProgress, onError );
37114
37115
37116                 return texture;
37117
37118         }
37119
37120     } );
37121
37122     function TextureLoader( manager ) {
37123
37124         Loader.call( this, manager );
37125
37126     }
37127
37128     TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37129
37130         constructor: TextureLoader,
37131
37132         load: function ( url, onLoad, onProgress, onError ) {
37133
37134                 const texture = new Texture();
37135
37136                 const loader = new ImageLoader( this.manager );
37137                 loader.setCrossOrigin( this.crossOrigin );
37138                 loader.setPath( this.path );
37139
37140                 loader.load( url, function ( image ) {
37141
37142                         texture.image = image;
37143
37144                         // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
37145                         const isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
37146
37147                         texture.format = isJPEG ? RGBFormat : RGBAFormat;
37148                         texture.needsUpdate = true;
37149
37150                         if ( onLoad !== undefined ) {
37151
37152                                 onLoad( texture );
37153
37154                         }
37155
37156                 }, onProgress, onError );
37157
37158                 return texture;
37159
37160         }
37161
37162     } );
37163
37164     /**
37165      * Extensible curve object.
37166      *
37167      * Some common of curve methods:
37168      * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
37169      * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
37170      * .getPoints(), .getSpacedPoints()
37171      * .getLength()
37172      * .updateArcLengths()
37173      *
37174      * This following curves inherit from THREE.Curve:
37175      *
37176      * -- 2D curves --
37177      * THREE.ArcCurve
37178      * THREE.CubicBezierCurve
37179      * THREE.EllipseCurve
37180      * THREE.LineCurve
37181      * THREE.QuadraticBezierCurve
37182      * THREE.SplineCurve
37183      *
37184      * -- 3D curves --
37185      * THREE.CatmullRomCurve3
37186      * THREE.CubicBezierCurve3
37187      * THREE.LineCurve3
37188      * THREE.QuadraticBezierCurve3
37189      *
37190      * A series of curves can be represented as a THREE.CurvePath.
37191      *
37192      **/
37193
37194     function Curve() {
37195
37196         this.type = 'Curve';
37197
37198         this.arcLengthDivisions = 200;
37199
37200     }
37201
37202     Object.assign( Curve.prototype, {
37203
37204         // Virtual base class method to overwrite and implement in subclasses
37205         //      - t [0 .. 1]
37206
37207         getPoint: function ( /* t, optionalTarget */ ) {
37208
37209                 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
37210                 return null;
37211
37212         },
37213
37214         // Get point at relative position in curve according to arc length
37215         // - u [0 .. 1]
37216
37217         getPointAt: function ( u, optionalTarget ) {
37218
37219                 const t = this.getUtoTmapping( u );
37220                 return this.getPoint( t, optionalTarget );
37221
37222         },
37223
37224         // Get sequence of points using getPoint( t )
37225
37226         getPoints: function ( divisions = 5 ) {
37227
37228                 const points = [];
37229
37230                 for ( let d = 0; d <= divisions; d ++ ) {
37231
37232                         points.push( this.getPoint( d / divisions ) );
37233
37234                 }
37235
37236                 return points;
37237
37238         },
37239
37240         // Get sequence of points using getPointAt( u )
37241
37242         getSpacedPoints: function ( divisions = 5 ) {
37243
37244                 const points = [];
37245
37246                 for ( let d = 0; d <= divisions; d ++ ) {
37247
37248                         points.push( this.getPointAt( d / divisions ) );
37249
37250                 }
37251
37252                 return points;
37253
37254         },
37255
37256         // Get total curve arc length
37257
37258         getLength: function () {
37259
37260                 const lengths = this.getLengths();
37261                 return lengths[ lengths.length - 1 ];
37262
37263         },
37264
37265         // Get list of cumulative segment lengths
37266
37267         getLengths: function ( divisions ) {
37268
37269                 if ( divisions === undefined ) divisions = this.arcLengthDivisions;
37270
37271                 if ( this.cacheArcLengths &&
37272                         ( this.cacheArcLengths.length === divisions + 1 ) &&
37273                         ! this.needsUpdate ) {
37274
37275                         return this.cacheArcLengths;
37276
37277                 }
37278
37279                 this.needsUpdate = false;
37280
37281                 const cache = [];
37282                 let current, last = this.getPoint( 0 );
37283                 let sum = 0;
37284
37285                 cache.push( 0 );
37286
37287                 for ( let p = 1; p <= divisions; p ++ ) {
37288
37289                         current = this.getPoint( p / divisions );
37290                         sum += current.distanceTo( last );
37291                         cache.push( sum );
37292                         last = current;
37293
37294                 }
37295
37296                 this.cacheArcLengths = cache;
37297
37298                 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
37299
37300         },
37301
37302         updateArcLengths: function () {
37303
37304                 this.needsUpdate = true;
37305                 this.getLengths();
37306
37307         },
37308
37309         // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
37310
37311         getUtoTmapping: function ( u, distance ) {
37312
37313                 const arcLengths = this.getLengths();
37314
37315                 let i = 0;
37316                 const il = arcLengths.length;
37317
37318                 let targetArcLength; // The targeted u distance value to get
37319
37320                 if ( distance ) {
37321
37322                         targetArcLength = distance;
37323
37324                 } else {
37325
37326                         targetArcLength = u * arcLengths[ il - 1 ];
37327
37328                 }
37329
37330                 // binary search for the index with largest value smaller than target u distance
37331
37332                 let low = 0, high = il - 1, comparison;
37333
37334                 while ( low <= high ) {
37335
37336                         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
37337
37338                         comparison = arcLengths[ i ] - targetArcLength;
37339
37340                         if ( comparison < 0 ) {
37341
37342                                 low = i + 1;
37343
37344                         } else if ( comparison > 0 ) {
37345
37346                                 high = i - 1;
37347
37348                         } else {
37349
37350                                 high = i;
37351                                 break;
37352
37353                                 // DONE
37354
37355                         }
37356
37357                 }
37358
37359                 i = high;
37360
37361                 if ( arcLengths[ i ] === targetArcLength ) {
37362
37363                         return i / ( il - 1 );
37364
37365                 }
37366
37367                 // we could get finer grain at lengths, or use simple interpolation between two points
37368
37369                 const lengthBefore = arcLengths[ i ];
37370                 const lengthAfter = arcLengths[ i + 1 ];
37371
37372                 const segmentLength = lengthAfter - lengthBefore;
37373
37374                 // determine where we are between the 'before' and 'after' points
37375
37376                 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
37377
37378                 // add that fractional amount to t
37379
37380                 const t = ( i + segmentFraction ) / ( il - 1 );
37381
37382                 return t;
37383
37384         },
37385
37386         // Returns a unit vector tangent at t
37387         // In case any sub curve does not implement its tangent derivation,
37388         // 2 points a small delta apart will be used to find its gradient
37389         // which seems to give a reasonable approximation
37390
37391         getTangent: function ( t, optionalTarget ) {
37392
37393                 const delta = 0.0001;
37394                 let t1 = t - delta;
37395                 let t2 = t + delta;
37396
37397                 // Capping in case of danger
37398
37399                 if ( t1 < 0 ) t1 = 0;
37400                 if ( t2 > 1 ) t2 = 1;
37401
37402                 const pt1 = this.getPoint( t1 );
37403                 const pt2 = this.getPoint( t2 );
37404
37405                 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
37406
37407                 tangent.copy( pt2 ).sub( pt1 ).normalize();
37408
37409                 return tangent;
37410
37411         },
37412
37413         getTangentAt: function ( u, optionalTarget ) {
37414
37415                 const t = this.getUtoTmapping( u );
37416                 return this.getTangent( t, optionalTarget );
37417
37418         },
37419
37420         computeFrenetFrames: function ( segments, closed ) {
37421
37422                 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
37423
37424                 const normal = new Vector3();
37425
37426                 const tangents = [];
37427                 const normals = [];
37428                 const binormals = [];
37429
37430                 const vec = new Vector3();
37431                 const mat = new Matrix4();
37432
37433                 // compute the tangent vectors for each segment on the curve
37434
37435                 for ( let i = 0; i <= segments; i ++ ) {
37436
37437                         const u = i / segments;
37438
37439                         tangents[ i ] = this.getTangentAt( u, new Vector3() );
37440                         tangents[ i ].normalize();
37441
37442                 }
37443
37444                 // select an initial normal vector perpendicular to the first tangent vector,
37445                 // and in the direction of the minimum tangent xyz component
37446
37447                 normals[ 0 ] = new Vector3();
37448                 binormals[ 0 ] = new Vector3();
37449                 let min = Number.MAX_VALUE;
37450                 const tx = Math.abs( tangents[ 0 ].x );
37451                 const ty = Math.abs( tangents[ 0 ].y );
37452                 const tz = Math.abs( tangents[ 0 ].z );
37453
37454                 if ( tx <= min ) {
37455
37456                         min = tx;
37457                         normal.set( 1, 0, 0 );
37458
37459                 }
37460
37461                 if ( ty <= min ) {
37462
37463                         min = ty;
37464                         normal.set( 0, 1, 0 );
37465
37466                 }
37467
37468                 if ( tz <= min ) {
37469
37470                         normal.set( 0, 0, 1 );
37471
37472                 }
37473
37474                 vec.crossVectors( tangents[ 0 ], normal ).normalize();
37475
37476                 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
37477                 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
37478
37479
37480                 // compute the slowly-varying normal and binormal vectors for each segment on the curve
37481
37482                 for ( let i = 1; i <= segments; i ++ ) {
37483
37484                         normals[ i ] = normals[ i - 1 ].clone();
37485
37486                         binormals[ i ] = binormals[ i - 1 ].clone();
37487
37488                         vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
37489
37490                         if ( vec.length() > Number.EPSILON ) {
37491
37492                                 vec.normalize();
37493
37494                                 const theta = Math.acos( MathUtils.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
37495
37496                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
37497
37498                         }
37499
37500                         binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37501
37502                 }
37503
37504                 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
37505
37506                 if ( closed === true ) {
37507
37508                         let theta = Math.acos( MathUtils.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
37509                         theta /= segments;
37510
37511                         if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
37512
37513                                 theta = - theta;
37514
37515                         }
37516
37517                         for ( let i = 1; i <= segments; i ++ ) {
37518
37519                                 // twist a little...
37520                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
37521                                 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37522
37523                         }
37524
37525                 }
37526
37527                 return {
37528                         tangents: tangents,
37529                         normals: normals,
37530                         binormals: binormals
37531                 };
37532
37533         },
37534
37535         clone: function () {
37536
37537                 return new this.constructor().copy( this );
37538
37539         },
37540
37541         copy: function ( source ) {
37542
37543                 this.arcLengthDivisions = source.arcLengthDivisions;
37544
37545                 return this;
37546
37547         },
37548
37549         toJSON: function () {
37550
37551                 const data = {
37552                         metadata: {
37553                                 version: 4.5,
37554                                 type: 'Curve',
37555                                 generator: 'Curve.toJSON'
37556                         }
37557                 };
37558
37559                 data.arcLengthDivisions = this.arcLengthDivisions;
37560                 data.type = this.type;
37561
37562                 return data;
37563
37564         },
37565
37566         fromJSON: function ( json ) {
37567
37568                 this.arcLengthDivisions = json.arcLengthDivisions;
37569
37570                 return this;
37571
37572         }
37573
37574     } );
37575
37576     function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
37577
37578         Curve.call( this );
37579
37580         this.type = 'EllipseCurve';
37581
37582         this.aX = aX || 0;
37583         this.aY = aY || 0;
37584
37585         this.xRadius = xRadius || 1;
37586         this.yRadius = yRadius || 1;
37587
37588         this.aStartAngle = aStartAngle || 0;
37589         this.aEndAngle = aEndAngle || 2 * Math.PI;
37590
37591         this.aClockwise = aClockwise || false;
37592
37593         this.aRotation = aRotation || 0;
37594
37595     }
37596
37597     EllipseCurve.prototype = Object.create( Curve.prototype );
37598     EllipseCurve.prototype.constructor = EllipseCurve;
37599
37600     EllipseCurve.prototype.isEllipseCurve = true;
37601
37602     EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
37603
37604         const point = optionalTarget || new Vector2();
37605
37606         const twoPi = Math.PI * 2;
37607         let deltaAngle = this.aEndAngle - this.aStartAngle;
37608         const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
37609
37610         // ensures that deltaAngle is 0 .. 2 PI
37611         while ( deltaAngle < 0 ) deltaAngle += twoPi;
37612         while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
37613
37614         if ( deltaAngle < Number.EPSILON ) {
37615
37616                 if ( samePoints ) {
37617
37618                         deltaAngle = 0;
37619
37620                 } else {
37621
37622                         deltaAngle = twoPi;
37623
37624                 }
37625
37626         }
37627
37628         if ( this.aClockwise === true && ! samePoints ) {
37629
37630                 if ( deltaAngle === twoPi ) {
37631
37632                         deltaAngle = - twoPi;
37633
37634                 } else {
37635
37636                         deltaAngle = deltaAngle - twoPi;
37637
37638                 }
37639
37640         }
37641
37642         const angle = this.aStartAngle + t * deltaAngle;
37643         let x = this.aX + this.xRadius * Math.cos( angle );
37644         let y = this.aY + this.yRadius * Math.sin( angle );
37645
37646         if ( this.aRotation !== 0 ) {
37647
37648                 const cos = Math.cos( this.aRotation );
37649                 const sin = Math.sin( this.aRotation );
37650
37651                 const tx = x - this.aX;
37652                 const ty = y - this.aY;
37653
37654                 // Rotate the point about the center of the ellipse.
37655                 x = tx * cos - ty * sin + this.aX;
37656                 y = tx * sin + ty * cos + this.aY;
37657
37658         }
37659
37660         return point.set( x, y );
37661
37662     };
37663
37664     EllipseCurve.prototype.copy = function ( source ) {
37665
37666         Curve.prototype.copy.call( this, source );
37667
37668         this.aX = source.aX;
37669         this.aY = source.aY;
37670
37671         this.xRadius = source.xRadius;
37672         this.yRadius = source.yRadius;
37673
37674         this.aStartAngle = source.aStartAngle;
37675         this.aEndAngle = source.aEndAngle;
37676
37677         this.aClockwise = source.aClockwise;
37678
37679         this.aRotation = source.aRotation;
37680
37681         return this;
37682
37683     };
37684
37685
37686     EllipseCurve.prototype.toJSON = function () {
37687
37688         const data = Curve.prototype.toJSON.call( this );
37689
37690         data.aX = this.aX;
37691         data.aY = this.aY;
37692
37693         data.xRadius = this.xRadius;
37694         data.yRadius = this.yRadius;
37695
37696         data.aStartAngle = this.aStartAngle;
37697         data.aEndAngle = this.aEndAngle;
37698
37699         data.aClockwise = this.aClockwise;
37700
37701         data.aRotation = this.aRotation;
37702
37703         return data;
37704
37705     };
37706
37707     EllipseCurve.prototype.fromJSON = function ( json ) {
37708
37709         Curve.prototype.fromJSON.call( this, json );
37710
37711         this.aX = json.aX;
37712         this.aY = json.aY;
37713
37714         this.xRadius = json.xRadius;
37715         this.yRadius = json.yRadius;
37716
37717         this.aStartAngle = json.aStartAngle;
37718         this.aEndAngle = json.aEndAngle;
37719
37720         this.aClockwise = json.aClockwise;
37721
37722         this.aRotation = json.aRotation;
37723
37724         return this;
37725
37726     };
37727
37728     function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
37729
37730         EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
37731
37732         this.type = 'ArcCurve';
37733
37734     }
37735
37736     ArcCurve.prototype = Object.create( EllipseCurve.prototype );
37737     ArcCurve.prototype.constructor = ArcCurve;
37738
37739     ArcCurve.prototype.isArcCurve = true;
37740
37741     /**
37742      * Centripetal CatmullRom Curve - which is useful for avoiding
37743      * cusps and self-intersections in non-uniform catmull rom curves.
37744      * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
37745      *
37746      * curve.type accepts centripetal(default), chordal and catmullrom
37747      * curve.tension is used for catmullrom which defaults to 0.5
37748      */
37749
37750
37751     /*
37752     Based on an optimized c++ solution in
37753      - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
37754      - http://ideone.com/NoEbVM
37755
37756     This CubicPoly class could be used for reusing some variables and calculations,
37757     but for three.js curve use, it could be possible inlined and flatten into a single function call
37758     which can be placed in CurveUtils.
37759     */
37760
37761     function CubicPoly() {
37762
37763         let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
37764
37765         /*
37766          * Compute coefficients for a cubic polynomial
37767          *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
37768          * such that
37769          *   p(0) = x0, p(1) = x1
37770          *  and
37771          *   p'(0) = t0, p'(1) = t1.
37772          */
37773         function init( x0, x1, t0, t1 ) {
37774
37775                 c0 = x0;
37776                 c1 = t0;
37777                 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
37778                 c3 = 2 * x0 - 2 * x1 + t0 + t1;
37779
37780         }
37781
37782         return {
37783
37784                 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
37785
37786                         init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
37787
37788                 },
37789
37790                 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
37791
37792                         // compute tangents when parameterized in [t1,t2]
37793                         let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
37794                         let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
37795
37796                         // rescale tangents for parametrization in [0,1]
37797                         t1 *= dt1;
37798                         t2 *= dt1;
37799
37800                         init( x1, x2, t1, t2 );
37801
37802                 },
37803
37804                 calc: function ( t ) {
37805
37806                         const t2 = t * t;
37807                         const t3 = t2 * t;
37808                         return c0 + c1 * t + c2 * t2 + c3 * t3;
37809
37810                 }
37811
37812         };
37813
37814     }
37815
37816     //
37817
37818     const tmp = new Vector3();
37819     const px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
37820
37821     function CatmullRomCurve3( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
37822
37823         Curve.call( this );
37824
37825         this.type = 'CatmullRomCurve3';
37826
37827         this.points = points;
37828         this.closed = closed;
37829         this.curveType = curveType;
37830         this.tension = tension;
37831
37832     }
37833
37834     CatmullRomCurve3.prototype = Object.create( Curve.prototype );
37835     CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
37836
37837     CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
37838
37839     CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
37840
37841         const point = optionalTarget;
37842
37843         const points = this.points;
37844         const l = points.length;
37845
37846         const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
37847         let intPoint = Math.floor( p );
37848         let weight = p - intPoint;
37849
37850         if ( this.closed ) {
37851
37852                 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
37853
37854         } else if ( weight === 0 && intPoint === l - 1 ) {
37855
37856                 intPoint = l - 2;
37857                 weight = 1;
37858
37859         }
37860
37861         let p0, p3; // 4 points (p1 & p2 defined below)
37862
37863         if ( this.closed || intPoint > 0 ) {
37864
37865                 p0 = points[ ( intPoint - 1 ) % l ];
37866
37867         } else {
37868
37869                 // extrapolate first point
37870                 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
37871                 p0 = tmp;
37872
37873         }
37874
37875         const p1 = points[ intPoint % l ];
37876         const p2 = points[ ( intPoint + 1 ) % l ];
37877
37878         if ( this.closed || intPoint + 2 < l ) {
37879
37880                 p3 = points[ ( intPoint + 2 ) % l ];
37881
37882         } else {
37883
37884                 // extrapolate last point
37885                 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
37886                 p3 = tmp;
37887
37888         }
37889
37890         if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
37891
37892                 // init Centripetal / Chordal Catmull-Rom
37893                 const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
37894                 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
37895                 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
37896                 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
37897
37898                 // safety check for repeated points
37899                 if ( dt1 < 1e-4 ) dt1 = 1.0;
37900                 if ( dt0 < 1e-4 ) dt0 = dt1;
37901                 if ( dt2 < 1e-4 ) dt2 = dt1;
37902
37903                 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
37904                 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
37905                 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
37906
37907         } else if ( this.curveType === 'catmullrom' ) {
37908
37909                 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
37910                 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
37911                 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
37912
37913         }
37914
37915         point.set(
37916                 px.calc( weight ),
37917                 py.calc( weight ),
37918                 pz.calc( weight )
37919         );
37920
37921         return point;
37922
37923     };
37924
37925     CatmullRomCurve3.prototype.copy = function ( source ) {
37926
37927         Curve.prototype.copy.call( this, source );
37928
37929         this.points = [];
37930
37931         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
37932
37933                 const point = source.points[ i ];
37934
37935                 this.points.push( point.clone() );
37936
37937         }
37938
37939         this.closed = source.closed;
37940         this.curveType = source.curveType;
37941         this.tension = source.tension;
37942
37943         return this;
37944
37945     };
37946
37947     CatmullRomCurve3.prototype.toJSON = function () {
37948
37949         const data = Curve.prototype.toJSON.call( this );
37950
37951         data.points = [];
37952
37953         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
37954
37955                 const point = this.points[ i ];
37956                 data.points.push( point.toArray() );
37957
37958         }
37959
37960         data.closed = this.closed;
37961         data.curveType = this.curveType;
37962         data.tension = this.tension;
37963
37964         return data;
37965
37966     };
37967
37968     CatmullRomCurve3.prototype.fromJSON = function ( json ) {
37969
37970         Curve.prototype.fromJSON.call( this, json );
37971
37972         this.points = [];
37973
37974         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
37975
37976                 const point = json.points[ i ];
37977                 this.points.push( new Vector3().fromArray( point ) );
37978
37979         }
37980
37981         this.closed = json.closed;
37982         this.curveType = json.curveType;
37983         this.tension = json.tension;
37984
37985         return this;
37986
37987     };
37988
37989     /**
37990      * Bezier Curves formulas obtained from
37991      * http://en.wikipedia.org/wiki/Bézier_curve
37992      */
37993
37994     function CatmullRom( t, p0, p1, p2, p3 ) {
37995
37996         const v0 = ( p2 - p0 ) * 0.5;
37997         const v1 = ( p3 - p1 ) * 0.5;
37998         const t2 = t * t;
37999         const t3 = t * t2;
38000         return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
38001
38002     }
38003
38004     //
38005
38006     function QuadraticBezierP0( t, p ) {
38007
38008         const k = 1 - t;
38009         return k * k * p;
38010
38011     }
38012
38013     function QuadraticBezierP1( t, p ) {
38014
38015         return 2 * ( 1 - t ) * t * p;
38016
38017     }
38018
38019     function QuadraticBezierP2( t, p ) {
38020
38021         return t * t * p;
38022
38023     }
38024
38025     function QuadraticBezier( t, p0, p1, p2 ) {
38026
38027         return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
38028                 QuadraticBezierP2( t, p2 );
38029
38030     }
38031
38032     //
38033
38034     function CubicBezierP0( t, p ) {
38035
38036         const k = 1 - t;
38037         return k * k * k * p;
38038
38039     }
38040
38041     function CubicBezierP1( t, p ) {
38042
38043         const k = 1 - t;
38044         return 3 * k * k * t * p;
38045
38046     }
38047
38048     function CubicBezierP2( t, p ) {
38049
38050         return 3 * ( 1 - t ) * t * t * p;
38051
38052     }
38053
38054     function CubicBezierP3( t, p ) {
38055
38056         return t * t * t * p;
38057
38058     }
38059
38060     function CubicBezier( t, p0, p1, p2, p3 ) {
38061
38062         return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
38063                 CubicBezierP3( t, p3 );
38064
38065     }
38066
38067     function CubicBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
38068
38069         Curve.call( this );
38070
38071         this.type = 'CubicBezierCurve';
38072
38073         this.v0 = v0;
38074         this.v1 = v1;
38075         this.v2 = v2;
38076         this.v3 = v3;
38077
38078     }
38079
38080     CubicBezierCurve.prototype = Object.create( Curve.prototype );
38081     CubicBezierCurve.prototype.constructor = CubicBezierCurve;
38082
38083     CubicBezierCurve.prototype.isCubicBezierCurve = true;
38084
38085     CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38086
38087         const point = optionalTarget;
38088
38089         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
38090
38091         point.set(
38092                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
38093                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
38094         );
38095
38096         return point;
38097
38098     };
38099
38100     CubicBezierCurve.prototype.copy = function ( source ) {
38101
38102         Curve.prototype.copy.call( this, source );
38103
38104         this.v0.copy( source.v0 );
38105         this.v1.copy( source.v1 );
38106         this.v2.copy( source.v2 );
38107         this.v3.copy( source.v3 );
38108
38109         return this;
38110
38111     };
38112
38113     CubicBezierCurve.prototype.toJSON = function () {
38114
38115         const data = Curve.prototype.toJSON.call( this );
38116
38117         data.v0 = this.v0.toArray();
38118         data.v1 = this.v1.toArray();
38119         data.v2 = this.v2.toArray();
38120         data.v3 = this.v3.toArray();
38121
38122         return data;
38123
38124     };
38125
38126     CubicBezierCurve.prototype.fromJSON = function ( json ) {
38127
38128         Curve.prototype.fromJSON.call( this, json );
38129
38130         this.v0.fromArray( json.v0 );
38131         this.v1.fromArray( json.v1 );
38132         this.v2.fromArray( json.v2 );
38133         this.v3.fromArray( json.v3 );
38134
38135         return this;
38136
38137     };
38138
38139     function CubicBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
38140
38141         Curve.call( this );
38142
38143         this.type = 'CubicBezierCurve3';
38144
38145         this.v0 = v0;
38146         this.v1 = v1;
38147         this.v2 = v2;
38148         this.v3 = v3;
38149
38150     }
38151
38152     CubicBezierCurve3.prototype = Object.create( Curve.prototype );
38153     CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
38154
38155     CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
38156
38157     CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38158
38159         const point = optionalTarget;
38160
38161         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
38162
38163         point.set(
38164                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
38165                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
38166                 CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
38167         );
38168
38169         return point;
38170
38171     };
38172
38173     CubicBezierCurve3.prototype.copy = function ( source ) {
38174
38175         Curve.prototype.copy.call( this, source );
38176
38177         this.v0.copy( source.v0 );
38178         this.v1.copy( source.v1 );
38179         this.v2.copy( source.v2 );
38180         this.v3.copy( source.v3 );
38181
38182         return this;
38183
38184     };
38185
38186     CubicBezierCurve3.prototype.toJSON = function () {
38187
38188         const data = Curve.prototype.toJSON.call( this );
38189
38190         data.v0 = this.v0.toArray();
38191         data.v1 = this.v1.toArray();
38192         data.v2 = this.v2.toArray();
38193         data.v3 = this.v3.toArray();
38194
38195         return data;
38196
38197     };
38198
38199     CubicBezierCurve3.prototype.fromJSON = function ( json ) {
38200
38201         Curve.prototype.fromJSON.call( this, json );
38202
38203         this.v0.fromArray( json.v0 );
38204         this.v1.fromArray( json.v1 );
38205         this.v2.fromArray( json.v2 );
38206         this.v3.fromArray( json.v3 );
38207
38208         return this;
38209
38210     };
38211
38212     function LineCurve( v1 = new Vector2(), v2 = new Vector2() ) {
38213
38214         Curve.call( this );
38215
38216         this.type = 'LineCurve';
38217
38218         this.v1 = v1;
38219         this.v2 = v2;
38220
38221     }
38222
38223     LineCurve.prototype = Object.create( Curve.prototype );
38224     LineCurve.prototype.constructor = LineCurve;
38225
38226     LineCurve.prototype.isLineCurve = true;
38227
38228     LineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38229
38230         const point = optionalTarget;
38231
38232         if ( t === 1 ) {
38233
38234                 point.copy( this.v2 );
38235
38236         } else {
38237
38238                 point.copy( this.v2 ).sub( this.v1 );
38239                 point.multiplyScalar( t ).add( this.v1 );
38240
38241         }
38242
38243         return point;
38244
38245     };
38246
38247     // Line curve is linear, so we can overwrite default getPointAt
38248
38249     LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
38250
38251         return this.getPoint( u, optionalTarget );
38252
38253     };
38254
38255     LineCurve.prototype.getTangent = function ( t, optionalTarget ) {
38256
38257         const tangent = optionalTarget || new Vector2();
38258
38259         tangent.copy( this.v2 ).sub( this.v1 ).normalize();
38260
38261         return tangent;
38262
38263     };
38264
38265     LineCurve.prototype.copy = function ( source ) {
38266
38267         Curve.prototype.copy.call( this, source );
38268
38269         this.v1.copy( source.v1 );
38270         this.v2.copy( source.v2 );
38271
38272         return this;
38273
38274     };
38275
38276     LineCurve.prototype.toJSON = function () {
38277
38278         const data = Curve.prototype.toJSON.call( this );
38279
38280         data.v1 = this.v1.toArray();
38281         data.v2 = this.v2.toArray();
38282
38283         return data;
38284
38285     };
38286
38287     LineCurve.prototype.fromJSON = function ( json ) {
38288
38289         Curve.prototype.fromJSON.call( this, json );
38290
38291         this.v1.fromArray( json.v1 );
38292         this.v2.fromArray( json.v2 );
38293
38294         return this;
38295
38296     };
38297
38298     function LineCurve3( v1 = new Vector3(), v2 = new Vector3() ) {
38299
38300         Curve.call( this );
38301
38302         this.type = 'LineCurve3';
38303
38304         this.v1 = v1;
38305         this.v2 = v2;
38306
38307     }
38308
38309     LineCurve3.prototype = Object.create( Curve.prototype );
38310     LineCurve3.prototype.constructor = LineCurve3;
38311
38312     LineCurve3.prototype.isLineCurve3 = true;
38313
38314     LineCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38315
38316         const point = optionalTarget;
38317
38318         if ( t === 1 ) {
38319
38320                 point.copy( this.v2 );
38321
38322         } else {
38323
38324                 point.copy( this.v2 ).sub( this.v1 );
38325                 point.multiplyScalar( t ).add( this.v1 );
38326
38327         }
38328
38329         return point;
38330
38331     };
38332
38333     // Line curve is linear, so we can overwrite default getPointAt
38334
38335     LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
38336
38337         return this.getPoint( u, optionalTarget );
38338
38339     };
38340
38341     LineCurve3.prototype.copy = function ( source ) {
38342
38343         Curve.prototype.copy.call( this, source );
38344
38345         this.v1.copy( source.v1 );
38346         this.v2.copy( source.v2 );
38347
38348         return this;
38349
38350     };
38351
38352     LineCurve3.prototype.toJSON = function () {
38353
38354         const data = Curve.prototype.toJSON.call( this );
38355
38356         data.v1 = this.v1.toArray();
38357         data.v2 = this.v2.toArray();
38358
38359         return data;
38360
38361     };
38362
38363     LineCurve3.prototype.fromJSON = function ( json ) {
38364
38365         Curve.prototype.fromJSON.call( this, json );
38366
38367         this.v1.fromArray( json.v1 );
38368         this.v2.fromArray( json.v2 );
38369
38370         return this;
38371
38372     };
38373
38374     function QuadraticBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
38375
38376         Curve.call( this );
38377
38378         this.type = 'QuadraticBezierCurve';
38379
38380         this.v0 = v0;
38381         this.v1 = v1;
38382         this.v2 = v2;
38383
38384     }
38385
38386     QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
38387     QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
38388
38389     QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
38390
38391     QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38392
38393         const point = optionalTarget;
38394
38395         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
38396
38397         point.set(
38398                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
38399                 QuadraticBezier( t, v0.y, v1.y, v2.y )
38400         );
38401
38402         return point;
38403
38404     };
38405
38406     QuadraticBezierCurve.prototype.copy = function ( source ) {
38407
38408         Curve.prototype.copy.call( this, source );
38409
38410         this.v0.copy( source.v0 );
38411         this.v1.copy( source.v1 );
38412         this.v2.copy( source.v2 );
38413
38414         return this;
38415
38416     };
38417
38418     QuadraticBezierCurve.prototype.toJSON = function () {
38419
38420         const data = Curve.prototype.toJSON.call( this );
38421
38422         data.v0 = this.v0.toArray();
38423         data.v1 = this.v1.toArray();
38424         data.v2 = this.v2.toArray();
38425
38426         return data;
38427
38428     };
38429
38430     QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
38431
38432         Curve.prototype.fromJSON.call( this, json );
38433
38434         this.v0.fromArray( json.v0 );
38435         this.v1.fromArray( json.v1 );
38436         this.v2.fromArray( json.v2 );
38437
38438         return this;
38439
38440     };
38441
38442     function QuadraticBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
38443
38444         Curve.call( this );
38445
38446         this.type = 'QuadraticBezierCurve3';
38447
38448         this.v0 = v0;
38449         this.v1 = v1;
38450         this.v2 = v2;
38451
38452     }
38453
38454     QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
38455     QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
38456
38457     QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
38458
38459     QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38460
38461         const point = optionalTarget;
38462
38463         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
38464
38465         point.set(
38466                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
38467                 QuadraticBezier( t, v0.y, v1.y, v2.y ),
38468                 QuadraticBezier( t, v0.z, v1.z, v2.z )
38469         );
38470
38471         return point;
38472
38473     };
38474
38475     QuadraticBezierCurve3.prototype.copy = function ( source ) {
38476
38477         Curve.prototype.copy.call( this, source );
38478
38479         this.v0.copy( source.v0 );
38480         this.v1.copy( source.v1 );
38481         this.v2.copy( source.v2 );
38482
38483         return this;
38484
38485     };
38486
38487     QuadraticBezierCurve3.prototype.toJSON = function () {
38488
38489         const data = Curve.prototype.toJSON.call( this );
38490
38491         data.v0 = this.v0.toArray();
38492         data.v1 = this.v1.toArray();
38493         data.v2 = this.v2.toArray();
38494
38495         return data;
38496
38497     };
38498
38499     QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
38500
38501         Curve.prototype.fromJSON.call( this, json );
38502
38503         this.v0.fromArray( json.v0 );
38504         this.v1.fromArray( json.v1 );
38505         this.v2.fromArray( json.v2 );
38506
38507         return this;
38508
38509     };
38510
38511     function SplineCurve( points = [] ) {
38512
38513         Curve.call( this );
38514
38515         this.type = 'SplineCurve';
38516
38517         this.points = points;
38518
38519     }
38520
38521     SplineCurve.prototype = Object.create( Curve.prototype );
38522     SplineCurve.prototype.constructor = SplineCurve;
38523
38524     SplineCurve.prototype.isSplineCurve = true;
38525
38526     SplineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38527
38528         const point = optionalTarget;
38529
38530         const points = this.points;
38531         const p = ( points.length - 1 ) * t;
38532
38533         const intPoint = Math.floor( p );
38534         const weight = p - intPoint;
38535
38536         const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
38537         const p1 = points[ intPoint ];
38538         const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
38539         const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
38540
38541         point.set(
38542                 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
38543                 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
38544         );
38545
38546         return point;
38547
38548     };
38549
38550     SplineCurve.prototype.copy = function ( source ) {
38551
38552         Curve.prototype.copy.call( this, source );
38553
38554         this.points = [];
38555
38556         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
38557
38558                 const point = source.points[ i ];
38559
38560                 this.points.push( point.clone() );
38561
38562         }
38563
38564         return this;
38565
38566     };
38567
38568     SplineCurve.prototype.toJSON = function () {
38569
38570         const data = Curve.prototype.toJSON.call( this );
38571
38572         data.points = [];
38573
38574         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
38575
38576                 const point = this.points[ i ];
38577                 data.points.push( point.toArray() );
38578
38579         }
38580
38581         return data;
38582
38583     };
38584
38585     SplineCurve.prototype.fromJSON = function ( json ) {
38586
38587         Curve.prototype.fromJSON.call( this, json );
38588
38589         this.points = [];
38590
38591         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
38592
38593                 const point = json.points[ i ];
38594                 this.points.push( new Vector2().fromArray( point ) );
38595
38596         }
38597
38598         return this;
38599
38600     };
38601
38602     var Curves = /*#__PURE__*/Object.freeze({
38603         __proto__: null,
38604         ArcCurve: ArcCurve,
38605         CatmullRomCurve3: CatmullRomCurve3,
38606         CubicBezierCurve: CubicBezierCurve,
38607         CubicBezierCurve3: CubicBezierCurve3,
38608         EllipseCurve: EllipseCurve,
38609         LineCurve: LineCurve,
38610         LineCurve3: LineCurve3,
38611         QuadraticBezierCurve: QuadraticBezierCurve,
38612         QuadraticBezierCurve3: QuadraticBezierCurve3,
38613         SplineCurve: SplineCurve
38614     });
38615
38616     /**************************************************************
38617      *  Curved Path - a curve path is simply a array of connected
38618      *  curves, but retains the api of a curve
38619      **************************************************************/
38620
38621     function CurvePath() {
38622
38623         Curve.call( this );
38624
38625         this.type = 'CurvePath';
38626
38627         this.curves = [];
38628         this.autoClose = false; // Automatically closes the path
38629
38630     }
38631
38632     CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
38633
38634         constructor: CurvePath,
38635
38636         add: function ( curve ) {
38637
38638                 this.curves.push( curve );
38639
38640         },
38641
38642         closePath: function () {
38643
38644                 // Add a line curve if start and end of lines are not connected
38645                 const startPoint = this.curves[ 0 ].getPoint( 0 );
38646                 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
38647
38648                 if ( ! startPoint.equals( endPoint ) ) {
38649
38650                         this.curves.push( new LineCurve( endPoint, startPoint ) );
38651
38652                 }
38653
38654         },
38655
38656         // To get accurate point with reference to
38657         // entire path distance at time t,
38658         // following has to be done:
38659
38660         // 1. Length of each sub path have to be known
38661         // 2. Locate and identify type of curve
38662         // 3. Get t for the curve
38663         // 4. Return curve.getPointAt(t')
38664
38665         getPoint: function ( t ) {
38666
38667                 const d = t * this.getLength();
38668                 const curveLengths = this.getCurveLengths();
38669                 let i = 0;
38670
38671                 // To think about boundaries points.
38672
38673                 while ( i < curveLengths.length ) {
38674
38675                         if ( curveLengths[ i ] >= d ) {
38676
38677                                 const diff = curveLengths[ i ] - d;
38678                                 const curve = this.curves[ i ];
38679
38680                                 const segmentLength = curve.getLength();
38681                                 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
38682
38683                                 return curve.getPointAt( u );
38684
38685                         }
38686
38687                         i ++;
38688
38689                 }
38690
38691                 return null;
38692
38693                 // loop where sum != 0, sum > d , sum+1 <d
38694
38695         },
38696
38697         // We cannot use the default THREE.Curve getPoint() with getLength() because in
38698         // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
38699         // getPoint() depends on getLength
38700
38701         getLength: function () {
38702
38703                 const lens = this.getCurveLengths();
38704                 return lens[ lens.length - 1 ];
38705
38706         },
38707
38708         // cacheLengths must be recalculated.
38709         updateArcLengths: function () {
38710
38711                 this.needsUpdate = true;
38712                 this.cacheLengths = null;
38713                 this.getCurveLengths();
38714
38715         },
38716
38717         // Compute lengths and cache them
38718         // We cannot overwrite getLengths() because UtoT mapping uses it.
38719
38720         getCurveLengths: function () {
38721
38722                 // We use cache values if curves and cache array are same length
38723
38724                 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
38725
38726                         return this.cacheLengths;
38727
38728                 }
38729
38730                 // Get length of sub-curve
38731                 // Push sums into cached array
38732
38733                 const lengths = [];
38734                 let sums = 0;
38735
38736                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
38737
38738                         sums += this.curves[ i ].getLength();
38739                         lengths.push( sums );
38740
38741                 }
38742
38743                 this.cacheLengths = lengths;
38744
38745                 return lengths;
38746
38747         },
38748
38749         getSpacedPoints: function ( divisions = 40 ) {
38750
38751                 const points = [];
38752
38753                 for ( let i = 0; i <= divisions; i ++ ) {
38754
38755                         points.push( this.getPoint( i / divisions ) );
38756
38757                 }
38758
38759                 if ( this.autoClose ) {
38760
38761                         points.push( points[ 0 ] );
38762
38763                 }
38764
38765                 return points;
38766
38767         },
38768
38769         getPoints: function ( divisions = 12 ) {
38770
38771                 const points = [];
38772                 let last;
38773
38774                 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
38775
38776                         const curve = curves[ i ];
38777                         const resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
38778                                 : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
38779                                         : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
38780                                                 : divisions;
38781
38782                         const pts = curve.getPoints( resolution );
38783
38784                         for ( let j = 0; j < pts.length; j ++ ) {
38785
38786                                 const point = pts[ j ];
38787
38788                                 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
38789
38790                                 points.push( point );
38791                                 last = point;
38792
38793                         }
38794
38795                 }
38796
38797                 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
38798
38799                         points.push( points[ 0 ] );
38800
38801                 }
38802
38803                 return points;
38804
38805         },
38806
38807         copy: function ( source ) {
38808
38809                 Curve.prototype.copy.call( this, source );
38810
38811                 this.curves = [];
38812
38813                 for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
38814
38815                         const curve = source.curves[ i ];
38816
38817                         this.curves.push( curve.clone() );
38818
38819                 }
38820
38821                 this.autoClose = source.autoClose;
38822
38823                 return this;
38824
38825         },
38826
38827         toJSON: function () {
38828
38829                 const data = Curve.prototype.toJSON.call( this );
38830
38831                 data.autoClose = this.autoClose;
38832                 data.curves = [];
38833
38834                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
38835
38836                         const curve = this.curves[ i ];
38837                         data.curves.push( curve.toJSON() );
38838
38839                 }
38840
38841                 return data;
38842
38843         },
38844
38845         fromJSON: function ( json ) {
38846
38847                 Curve.prototype.fromJSON.call( this, json );
38848
38849                 this.autoClose = json.autoClose;
38850                 this.curves = [];
38851
38852                 for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
38853
38854                         const curve = json.curves[ i ];
38855                         this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
38856
38857                 }
38858
38859                 return this;
38860
38861         }
38862
38863     } );
38864
38865     function Path( points ) {
38866
38867         CurvePath.call( this );
38868
38869         this.type = 'Path';
38870
38871         this.currentPoint = new Vector2();
38872
38873         if ( points ) {
38874
38875                 this.setFromPoints( points );
38876
38877         }
38878
38879     }
38880
38881     Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
38882
38883         constructor: Path,
38884
38885         setFromPoints: function ( points ) {
38886
38887                 this.moveTo( points[ 0 ].x, points[ 0 ].y );
38888
38889                 for ( let i = 1, l = points.length; i < l; i ++ ) {
38890
38891                         this.lineTo( points[ i ].x, points[ i ].y );
38892
38893                 }
38894
38895                 return this;
38896
38897         },
38898
38899         moveTo: function ( x, y ) {
38900
38901                 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
38902
38903                 return this;
38904
38905         },
38906
38907         lineTo: function ( x, y ) {
38908
38909                 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
38910                 this.curves.push( curve );
38911
38912                 this.currentPoint.set( x, y );
38913
38914                 return this;
38915
38916         },
38917
38918         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
38919
38920                 const curve = new QuadraticBezierCurve(
38921                         this.currentPoint.clone(),
38922                         new Vector2( aCPx, aCPy ),
38923                         new Vector2( aX, aY )
38924                 );
38925
38926                 this.curves.push( curve );
38927
38928                 this.currentPoint.set( aX, aY );
38929
38930                 return this;
38931
38932         },
38933
38934         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
38935
38936                 const curve = new CubicBezierCurve(
38937                         this.currentPoint.clone(),
38938                         new Vector2( aCP1x, aCP1y ),
38939                         new Vector2( aCP2x, aCP2y ),
38940                         new Vector2( aX, aY )
38941                 );
38942
38943                 this.curves.push( curve );
38944
38945                 this.currentPoint.set( aX, aY );
38946
38947                 return this;
38948
38949         },
38950
38951         splineThru: function ( pts /*Array of Vector*/ ) {
38952
38953                 const npts = [ this.currentPoint.clone() ].concat( pts );
38954
38955                 const curve = new SplineCurve( npts );
38956                 this.curves.push( curve );
38957
38958                 this.currentPoint.copy( pts[ pts.length - 1 ] );
38959
38960                 return this;
38961
38962         },
38963
38964         arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
38965
38966                 const x0 = this.currentPoint.x;
38967                 const y0 = this.currentPoint.y;
38968
38969                 this.absarc( aX + x0, aY + y0, aRadius,
38970                         aStartAngle, aEndAngle, aClockwise );
38971
38972                 return this;
38973
38974         },
38975
38976         absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
38977
38978                 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
38979
38980                 return this;
38981
38982         },
38983
38984         ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
38985
38986                 const x0 = this.currentPoint.x;
38987                 const y0 = this.currentPoint.y;
38988
38989                 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
38990
38991                 return this;
38992
38993         },
38994
38995         absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
38996
38997                 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
38998
38999                 if ( this.curves.length > 0 ) {
39000
39001                         // if a previous curve is present, attempt to join
39002                         const firstPoint = curve.getPoint( 0 );
39003
39004                         if ( ! firstPoint.equals( this.currentPoint ) ) {
39005
39006                                 this.lineTo( firstPoint.x, firstPoint.y );
39007
39008                         }
39009
39010                 }
39011
39012                 this.curves.push( curve );
39013
39014                 const lastPoint = curve.getPoint( 1 );
39015                 this.currentPoint.copy( lastPoint );
39016
39017                 return this;
39018
39019         },
39020
39021         copy: function ( source ) {
39022
39023                 CurvePath.prototype.copy.call( this, source );
39024
39025                 this.currentPoint.copy( source.currentPoint );
39026
39027                 return this;
39028
39029         },
39030
39031         toJSON: function () {
39032
39033                 const data = CurvePath.prototype.toJSON.call( this );
39034
39035                 data.currentPoint = this.currentPoint.toArray();
39036
39037                 return data;
39038
39039         },
39040
39041         fromJSON: function ( json ) {
39042
39043                 CurvePath.prototype.fromJSON.call( this, json );
39044
39045                 this.currentPoint.fromArray( json.currentPoint );
39046
39047                 return this;
39048
39049         }
39050
39051     } );
39052
39053     function Shape( points ) {
39054
39055         Path.call( this, points );
39056
39057         this.uuid = MathUtils.generateUUID();
39058
39059         this.type = 'Shape';
39060
39061         this.holes = [];
39062
39063     }
39064
39065     Shape.prototype = Object.assign( Object.create( Path.prototype ), {
39066
39067         constructor: Shape,
39068
39069         getPointsHoles: function ( divisions ) {
39070
39071                 const holesPts = [];
39072
39073                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
39074
39075                         holesPts[ i ] = this.holes[ i ].getPoints( divisions );
39076
39077                 }
39078
39079                 return holesPts;
39080
39081         },
39082
39083         // get points of shape and holes (keypoints based on segments parameter)
39084
39085         extractPoints: function ( divisions ) {
39086
39087                 return {
39088
39089                         shape: this.getPoints( divisions ),
39090                         holes: this.getPointsHoles( divisions )
39091
39092                 };
39093
39094         },
39095
39096         copy: function ( source ) {
39097
39098                 Path.prototype.copy.call( this, source );
39099
39100                 this.holes = [];
39101
39102                 for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
39103
39104                         const hole = source.holes[ i ];
39105
39106                         this.holes.push( hole.clone() );
39107
39108                 }
39109
39110                 return this;
39111
39112         },
39113
39114         toJSON: function () {
39115
39116                 const data = Path.prototype.toJSON.call( this );
39117
39118                 data.uuid = this.uuid;
39119                 data.holes = [];
39120
39121                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
39122
39123                         const hole = this.holes[ i ];
39124                         data.holes.push( hole.toJSON() );
39125
39126                 }
39127
39128                 return data;
39129
39130         },
39131
39132         fromJSON: function ( json ) {
39133
39134                 Path.prototype.fromJSON.call( this, json );
39135
39136                 this.uuid = json.uuid;
39137                 this.holes = [];
39138
39139                 for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
39140
39141                         const hole = json.holes[ i ];
39142                         this.holes.push( new Path().fromJSON( hole ) );
39143
39144                 }
39145
39146                 return this;
39147
39148         }
39149
39150     } );
39151
39152     function Light( color, intensity = 1 ) {
39153
39154         Object3D.call( this );
39155
39156         this.type = 'Light';
39157
39158         this.color = new Color( color );
39159         this.intensity = intensity;
39160
39161     }
39162
39163     Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
39164
39165         constructor: Light,
39166
39167         isLight: true,
39168
39169         copy: function ( source ) {
39170
39171                 Object3D.prototype.copy.call( this, source );
39172
39173                 this.color.copy( source.color );
39174                 this.intensity = source.intensity;
39175
39176                 return this;
39177
39178         },
39179
39180         toJSON: function ( meta ) {
39181
39182                 const data = Object3D.prototype.toJSON.call( this, meta );
39183
39184                 data.object.color = this.color.getHex();
39185                 data.object.intensity = this.intensity;
39186
39187                 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
39188
39189                 if ( this.distance !== undefined ) data.object.distance = this.distance;
39190                 if ( this.angle !== undefined ) data.object.angle = this.angle;
39191                 if ( this.decay !== undefined ) data.object.decay = this.decay;
39192                 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
39193
39194                 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
39195
39196                 return data;
39197
39198         }
39199
39200     } );
39201
39202     function HemisphereLight( skyColor, groundColor, intensity ) {
39203
39204         Light.call( this, skyColor, intensity );
39205
39206         this.type = 'HemisphereLight';
39207
39208         this.position.copy( Object3D.DefaultUp );
39209         this.updateMatrix();
39210
39211         this.groundColor = new Color( groundColor );
39212
39213     }
39214
39215     HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
39216
39217         constructor: HemisphereLight,
39218
39219         isHemisphereLight: true,
39220
39221         copy: function ( source ) {
39222
39223                 Light.prototype.copy.call( this, source );
39224
39225                 this.groundColor.copy( source.groundColor );
39226
39227                 return this;
39228
39229         }
39230
39231     } );
39232
39233     function LightShadow( camera ) {
39234
39235         this.camera = camera;
39236
39237         this.bias = 0;
39238         this.normalBias = 0;
39239         this.radius = 1;
39240
39241         this.mapSize = new Vector2( 512, 512 );
39242
39243         this.map = null;
39244         this.mapPass = null;
39245         this.matrix = new Matrix4();
39246
39247         this.autoUpdate = true;
39248         this.needsUpdate = false;
39249
39250         this._frustum = new Frustum();
39251         this._frameExtents = new Vector2( 1, 1 );
39252
39253         this._viewportCount = 1;
39254
39255         this._viewports = [
39256
39257                 new Vector4( 0, 0, 1, 1 )
39258
39259         ];
39260
39261     }
39262
39263     Object.assign( LightShadow.prototype, {
39264
39265         _projScreenMatrix: new Matrix4(),
39266
39267         _lightPositionWorld: new Vector3(),
39268
39269         _lookTarget: new Vector3(),
39270
39271         getViewportCount: function () {
39272
39273                 return this._viewportCount;
39274
39275         },
39276
39277         getFrustum: function () {
39278
39279                 return this._frustum;
39280
39281         },
39282
39283         updateMatrices: function ( light ) {
39284
39285                 const shadowCamera = this.camera,
39286                         shadowMatrix = this.matrix,
39287                         projScreenMatrix = this._projScreenMatrix,
39288                         lookTarget = this._lookTarget,
39289                         lightPositionWorld = this._lightPositionWorld;
39290
39291                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39292                 shadowCamera.position.copy( lightPositionWorld );
39293
39294                 lookTarget.setFromMatrixPosition( light.target.matrixWorld );
39295                 shadowCamera.lookAt( lookTarget );
39296                 shadowCamera.updateMatrixWorld();
39297
39298                 projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
39299                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
39300
39301                 shadowMatrix.set(
39302                         0.5, 0.0, 0.0, 0.5,
39303                         0.0, 0.5, 0.0, 0.5,
39304                         0.0, 0.0, 0.5, 0.5,
39305                         0.0, 0.0, 0.0, 1.0
39306                 );
39307
39308                 shadowMatrix.multiply( shadowCamera.projectionMatrix );
39309                 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
39310
39311         },
39312
39313         getViewport: function ( viewportIndex ) {
39314
39315                 return this._viewports[ viewportIndex ];
39316
39317         },
39318
39319         getFrameExtents: function () {
39320
39321                 return this._frameExtents;
39322
39323         },
39324
39325         copy: function ( source ) {
39326
39327                 this.camera = source.camera.clone();
39328
39329                 this.bias = source.bias;
39330                 this.radius = source.radius;
39331
39332                 this.mapSize.copy( source.mapSize );
39333
39334                 return this;
39335
39336         },
39337
39338         clone: function () {
39339
39340                 return new this.constructor().copy( this );
39341
39342         },
39343
39344         toJSON: function () {
39345
39346                 const object = {};
39347
39348                 if ( this.bias !== 0 ) object.bias = this.bias;
39349                 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
39350                 if ( this.radius !== 1 ) object.radius = this.radius;
39351                 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
39352
39353                 object.camera = this.camera.toJSON( false ).object;
39354                 delete object.camera.matrix;
39355
39356                 return object;
39357
39358         }
39359
39360     } );
39361
39362     function SpotLightShadow() {
39363
39364         LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
39365
39366         this.focus = 1;
39367
39368     }
39369
39370     SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39371
39372         constructor: SpotLightShadow,
39373
39374         isSpotLightShadow: true,
39375
39376         updateMatrices: function ( light ) {
39377
39378                 const camera = this.camera;
39379
39380                 const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus;
39381                 const aspect = this.mapSize.width / this.mapSize.height;
39382                 const far = light.distance || camera.far;
39383
39384                 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
39385
39386                         camera.fov = fov;
39387                         camera.aspect = aspect;
39388                         camera.far = far;
39389                         camera.updateProjectionMatrix();
39390
39391                 }
39392
39393                 LightShadow.prototype.updateMatrices.call( this, light );
39394
39395         }
39396
39397     } );
39398
39399     function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
39400
39401         Light.call( this, color, intensity );
39402
39403         this.type = 'SpotLight';
39404
39405         this.position.copy( Object3D.DefaultUp );
39406         this.updateMatrix();
39407
39408         this.target = new Object3D();
39409
39410         Object.defineProperty( this, 'power', {
39411                 get: function () {
39412
39413                         // intensity = power per solid angle.
39414                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39415                         return this.intensity * Math.PI;
39416
39417                 },
39418                 set: function ( power ) {
39419
39420                         // intensity = power per solid angle.
39421                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39422                         this.intensity = power / Math.PI;
39423
39424                 }
39425         } );
39426
39427         this.distance = ( distance !== undefined ) ? distance : 0;
39428         this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
39429         this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
39430         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
39431
39432         this.shadow = new SpotLightShadow();
39433
39434     }
39435
39436     SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
39437
39438         constructor: SpotLight,
39439
39440         isSpotLight: true,
39441
39442         copy: function ( source ) {
39443
39444                 Light.prototype.copy.call( this, source );
39445
39446                 this.distance = source.distance;
39447                 this.angle = source.angle;
39448                 this.penumbra = source.penumbra;
39449                 this.decay = source.decay;
39450
39451                 this.target = source.target.clone();
39452
39453                 this.shadow = source.shadow.clone();
39454
39455                 return this;
39456
39457         }
39458
39459     } );
39460
39461     function PointLightShadow() {
39462
39463         LightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );
39464
39465         this._frameExtents = new Vector2( 4, 2 );
39466
39467         this._viewportCount = 6;
39468
39469         this._viewports = [
39470                 // These viewports map a cube-map onto a 2D texture with the
39471                 // following orientation:
39472                 //
39473                 //  xzXZ
39474                 //   y Y
39475                 //
39476                 // X - Positive x direction
39477                 // x - Negative x direction
39478                 // Y - Positive y direction
39479                 // y - Negative y direction
39480                 // Z - Positive z direction
39481                 // z - Negative z direction
39482
39483                 // positive X
39484                 new Vector4( 2, 1, 1, 1 ),
39485                 // negative X
39486                 new Vector4( 0, 1, 1, 1 ),
39487                 // positive Z
39488                 new Vector4( 3, 1, 1, 1 ),
39489                 // negative Z
39490                 new Vector4( 1, 1, 1, 1 ),
39491                 // positive Y
39492                 new Vector4( 3, 0, 1, 1 ),
39493                 // negative Y
39494                 new Vector4( 1, 0, 1, 1 )
39495         ];
39496
39497         this._cubeDirections = [
39498                 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
39499                 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
39500         ];
39501
39502         this._cubeUps = [
39503                 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
39504                 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
39505         ];
39506
39507     }
39508
39509     PointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39510
39511         constructor: PointLightShadow,
39512
39513         isPointLightShadow: true,
39514
39515         updateMatrices: function ( light, viewportIndex = 0 ) {
39516
39517                 const camera = this.camera,
39518                         shadowMatrix = this.matrix,
39519                         lightPositionWorld = this._lightPositionWorld,
39520                         lookTarget = this._lookTarget,
39521                         projScreenMatrix = this._projScreenMatrix;
39522
39523                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39524                 camera.position.copy( lightPositionWorld );
39525
39526                 lookTarget.copy( camera.position );
39527                 lookTarget.add( this._cubeDirections[ viewportIndex ] );
39528                 camera.up.copy( this._cubeUps[ viewportIndex ] );
39529                 camera.lookAt( lookTarget );
39530                 camera.updateMatrixWorld();
39531
39532                 shadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );
39533
39534                 projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
39535                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
39536
39537         }
39538
39539     } );
39540
39541     function PointLight( color, intensity, distance, decay ) {
39542
39543         Light.call( this, color, intensity );
39544
39545         this.type = 'PointLight';
39546
39547         Object.defineProperty( this, 'power', {
39548                 get: function () {
39549
39550                         // intensity = power per solid angle.
39551                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39552                         return this.intensity * 4 * Math.PI;
39553
39554                 },
39555                 set: function ( power ) {
39556
39557                         // intensity = power per solid angle.
39558                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39559                         this.intensity = power / ( 4 * Math.PI );
39560
39561                 }
39562         } );
39563
39564         this.distance = ( distance !== undefined ) ? distance : 0;
39565         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
39566
39567         this.shadow = new PointLightShadow();
39568
39569     }
39570
39571     PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
39572
39573         constructor: PointLight,
39574
39575         isPointLight: true,
39576
39577         copy: function ( source ) {
39578
39579                 Light.prototype.copy.call( this, source );
39580
39581                 this.distance = source.distance;
39582                 this.decay = source.decay;
39583
39584                 this.shadow = source.shadow.clone();
39585
39586                 return this;
39587
39588         }
39589
39590     } );
39591
39592     function OrthographicCamera( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
39593
39594         Camera$1.call( this );
39595
39596         this.type = 'OrthographicCamera';
39597
39598         this.zoom = 1;
39599         this.view = null;
39600
39601         this.left = left;
39602         this.right = right;
39603         this.top = top;
39604         this.bottom = bottom;
39605
39606         this.near = near;
39607         this.far = far;
39608
39609         this.updateProjectionMatrix();
39610
39611     }
39612
39613     OrthographicCamera.prototype = Object.assign( Object.create( Camera$1.prototype ), {
39614
39615         constructor: OrthographicCamera,
39616
39617         isOrthographicCamera: true,
39618
39619         copy: function ( source, recursive ) {
39620
39621                 Camera$1.prototype.copy.call( this, source, recursive );
39622
39623                 this.left = source.left;
39624                 this.right = source.right;
39625                 this.top = source.top;
39626                 this.bottom = source.bottom;
39627                 this.near = source.near;
39628                 this.far = source.far;
39629
39630                 this.zoom = source.zoom;
39631                 this.view = source.view === null ? null : Object.assign( {}, source.view );
39632
39633                 return this;
39634
39635         },
39636
39637         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
39638
39639                 if ( this.view === null ) {
39640
39641                         this.view = {
39642                                 enabled: true,
39643                                 fullWidth: 1,
39644                                 fullHeight: 1,
39645                                 offsetX: 0,
39646                                 offsetY: 0,
39647                                 width: 1,
39648                                 height: 1
39649                         };
39650
39651                 }
39652
39653                 this.view.enabled = true;
39654                 this.view.fullWidth = fullWidth;
39655                 this.view.fullHeight = fullHeight;
39656                 this.view.offsetX = x;
39657                 this.view.offsetY = y;
39658                 this.view.width = width;
39659                 this.view.height = height;
39660
39661                 this.updateProjectionMatrix();
39662
39663         },
39664
39665         clearViewOffset: function () {
39666
39667                 if ( this.view !== null ) {
39668
39669                         this.view.enabled = false;
39670
39671                 }
39672
39673                 this.updateProjectionMatrix();
39674
39675         },
39676
39677         updateProjectionMatrix: function () {
39678
39679                 const dx = ( this.right - this.left ) / ( 2 * this.zoom );
39680                 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
39681                 const cx = ( this.right + this.left ) / 2;
39682                 const cy = ( this.top + this.bottom ) / 2;
39683
39684                 let left = cx - dx;
39685                 let right = cx + dx;
39686                 let top = cy + dy;
39687                 let bottom = cy - dy;
39688
39689                 if ( this.view !== null && this.view.enabled ) {
39690
39691                         const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
39692                         const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
39693
39694                         left += scaleW * this.view.offsetX;
39695                         right = left + scaleW * this.view.width;
39696                         top -= scaleH * this.view.offsetY;
39697                         bottom = top - scaleH * this.view.height;
39698
39699                 }
39700
39701                 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
39702
39703                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
39704
39705         },
39706
39707         toJSON: function ( meta ) {
39708
39709                 const data = Object3D.prototype.toJSON.call( this, meta );
39710
39711                 data.object.zoom = this.zoom;
39712                 data.object.left = this.left;
39713                 data.object.right = this.right;
39714                 data.object.top = this.top;
39715                 data.object.bottom = this.bottom;
39716                 data.object.near = this.near;
39717                 data.object.far = this.far;
39718
39719                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
39720
39721                 return data;
39722
39723         }
39724
39725     } );
39726
39727     function DirectionalLightShadow() {
39728
39729         LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
39730
39731     }
39732
39733     DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39734
39735         constructor: DirectionalLightShadow,
39736
39737         isDirectionalLightShadow: true,
39738
39739         updateMatrices: function ( light ) {
39740
39741                 LightShadow.prototype.updateMatrices.call( this, light );
39742
39743         }
39744
39745     } );
39746
39747     function DirectionalLight( color, intensity ) {
39748
39749         Light.call( this, color, intensity );
39750
39751         this.type = 'DirectionalLight';
39752
39753         this.position.copy( Object3D.DefaultUp );
39754         this.updateMatrix();
39755
39756         this.target = new Object3D();
39757
39758         this.shadow = new DirectionalLightShadow();
39759
39760     }
39761
39762     DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
39763
39764         constructor: DirectionalLight,
39765
39766         isDirectionalLight: true,
39767
39768         copy: function ( source ) {
39769
39770                 Light.prototype.copy.call( this, source );
39771
39772                 this.target = source.target.clone();
39773
39774                 this.shadow = source.shadow.clone();
39775
39776                 return this;
39777
39778         }
39779
39780     } );
39781
39782     function AmbientLight( color, intensity ) {
39783
39784         Light.call( this, color, intensity );
39785
39786         this.type = 'AmbientLight';
39787
39788     }
39789
39790     AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
39791
39792         constructor: AmbientLight,
39793
39794         isAmbientLight: true
39795
39796     } );
39797
39798     function RectAreaLight( color, intensity, width, height ) {
39799
39800         Light.call( this, color, intensity );
39801
39802         this.type = 'RectAreaLight';
39803
39804         this.width = ( width !== undefined ) ? width : 10;
39805         this.height = ( height !== undefined ) ? height : 10;
39806
39807     }
39808
39809     RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
39810
39811         constructor: RectAreaLight,
39812
39813         isRectAreaLight: true,
39814
39815         copy: function ( source ) {
39816
39817                 Light.prototype.copy.call( this, source );
39818
39819                 this.width = source.width;
39820                 this.height = source.height;
39821
39822                 return this;
39823
39824         },
39825
39826         toJSON: function ( meta ) {
39827
39828                 const data = Light.prototype.toJSON.call( this, meta );
39829
39830                 data.object.width = this.width;
39831                 data.object.height = this.height;
39832
39833                 return data;
39834
39835         }
39836
39837     } );
39838
39839     /**
39840      * Primary reference:
39841      *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
39842      *
39843      * Secondary reference:
39844      *   https://www.ppsloan.org/publications/StupidSH36.pdf
39845      */
39846
39847     // 3-band SH defined by 9 coefficients
39848
39849     class SphericalHarmonics3 {
39850
39851         constructor() {
39852
39853                 Object.defineProperty( this, 'isSphericalHarmonics3', { value: true } );
39854
39855                 this.coefficients = [];
39856
39857                 for ( let i = 0; i < 9; i ++ ) {
39858
39859                         this.coefficients.push( new Vector3() );
39860
39861                 }
39862
39863         }
39864
39865         set( coefficients ) {
39866
39867                 for ( let i = 0; i < 9; i ++ ) {
39868
39869                         this.coefficients[ i ].copy( coefficients[ i ] );
39870
39871                 }
39872
39873                 return this;
39874
39875         }
39876
39877         zero() {
39878
39879                 for ( let i = 0; i < 9; i ++ ) {
39880
39881                         this.coefficients[ i ].set( 0, 0, 0 );
39882
39883                 }
39884
39885                 return this;
39886
39887         }
39888
39889         // get the radiance in the direction of the normal
39890         // target is a Vector3
39891         getAt( normal, target ) {
39892
39893                 // normal is assumed to be unit length
39894
39895                 const x = normal.x, y = normal.y, z = normal.z;
39896
39897                 const coeff = this.coefficients;
39898
39899                 // band 0
39900                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
39901
39902                 // band 1
39903                 target.addScaledVector( coeff[ 1 ], 0.488603 * y );
39904                 target.addScaledVector( coeff[ 2 ], 0.488603 * z );
39905                 target.addScaledVector( coeff[ 3 ], 0.488603 * x );
39906
39907                 // band 2
39908                 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
39909                 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
39910                 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
39911                 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
39912                 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
39913
39914                 return target;
39915
39916         }
39917
39918         // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
39919         // target is a Vector3
39920         // https://graphics.stanford.edu/papers/envmap/envmap.pdf
39921         getIrradianceAt( normal, target ) {
39922
39923                 // normal is assumed to be unit length
39924
39925                 const x = normal.x, y = normal.y, z = normal.z;
39926
39927                 const coeff = this.coefficients;
39928
39929                 // band 0
39930                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï€ * 0.282095
39931
39932                 // band 1
39933                 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï€ / 3 ) * 0.488603
39934                 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
39935                 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
39936
39937                 // band 2
39938                 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï€ / 4 ) * 1.092548
39939                 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
39940                 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï€ / 4 ) * 0.315392 * 3
39941                 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
39942                 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï€ / 4 ) * 0.546274
39943
39944                 return target;
39945
39946         }
39947
39948         add( sh ) {
39949
39950                 for ( let i = 0; i < 9; i ++ ) {
39951
39952                         this.coefficients[ i ].add( sh.coefficients[ i ] );
39953
39954                 }
39955
39956                 return this;
39957
39958         }
39959
39960         addScaledSH( sh, s ) {
39961
39962                 for ( let i = 0; i < 9; i ++ ) {
39963
39964                         this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
39965
39966                 }
39967
39968                 return this;
39969
39970         }
39971
39972         scale( s ) {
39973
39974                 for ( let i = 0; i < 9; i ++ ) {
39975
39976                         this.coefficients[ i ].multiplyScalar( s );
39977
39978                 }
39979
39980                 return this;
39981
39982         }
39983
39984         lerp( sh, alpha ) {
39985
39986                 for ( let i = 0; i < 9; i ++ ) {
39987
39988                         this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
39989
39990                 }
39991
39992                 return this;
39993
39994         }
39995
39996         equals( sh ) {
39997
39998                 for ( let i = 0; i < 9; i ++ ) {
39999
40000                         if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
40001
40002                                 return false;
40003
40004                         }
40005
40006                 }
40007
40008                 return true;
40009
40010         }
40011
40012         copy( sh ) {
40013
40014                 return this.set( sh.coefficients );
40015
40016         }
40017
40018         clone() {
40019
40020                 return new this.constructor().copy( this );
40021
40022         }
40023
40024         fromArray( array, offset = 0 ) {
40025
40026                 const coefficients = this.coefficients;
40027
40028                 for ( let i = 0; i < 9; i ++ ) {
40029
40030                         coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
40031
40032                 }
40033
40034                 return this;
40035
40036         }
40037
40038         toArray( array = [], offset = 0 ) {
40039
40040                 const coefficients = this.coefficients;
40041
40042                 for ( let i = 0; i < 9; i ++ ) {
40043
40044                         coefficients[ i ].toArray( array, offset + ( i * 3 ) );
40045
40046                 }
40047
40048                 return array;
40049
40050         }
40051
40052         // evaluate the basis functions
40053         // shBasis is an Array[ 9 ]
40054         static getBasisAt( normal, shBasis ) {
40055
40056                 // normal is assumed to be unit length
40057
40058                 const x = normal.x, y = normal.y, z = normal.z;
40059
40060                 // band 0
40061                 shBasis[ 0 ] = 0.282095;
40062
40063                 // band 1
40064                 shBasis[ 1 ] = 0.488603 * y;
40065                 shBasis[ 2 ] = 0.488603 * z;
40066                 shBasis[ 3 ] = 0.488603 * x;
40067
40068                 // band 2
40069                 shBasis[ 4 ] = 1.092548 * x * y;
40070                 shBasis[ 5 ] = 1.092548 * y * z;
40071                 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
40072                 shBasis[ 7 ] = 1.092548 * x * z;
40073                 shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
40074
40075         }
40076
40077     }
40078
40079     function LightProbe( sh, intensity ) {
40080
40081         Light.call( this, undefined, intensity );
40082
40083         this.type = 'LightProbe';
40084
40085         this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
40086
40087     }
40088
40089     LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
40090
40091         constructor: LightProbe,
40092
40093         isLightProbe: true,
40094
40095         copy: function ( source ) {
40096
40097                 Light.prototype.copy.call( this, source );
40098
40099                 this.sh.copy( source.sh );
40100
40101                 return this;
40102
40103         },
40104
40105         fromJSON: function ( json ) {
40106
40107                 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
40108                 this.sh.fromArray( json.sh );
40109
40110                 return this;
40111
40112         },
40113
40114         toJSON: function ( meta ) {
40115
40116                 const data = Light.prototype.toJSON.call( this, meta );
40117
40118                 data.object.sh = this.sh.toArray();
40119
40120                 return data;
40121
40122         }
40123
40124     } );
40125
40126     function MaterialLoader( manager ) {
40127
40128         Loader.call( this, manager );
40129
40130         this.textures = {};
40131
40132     }
40133
40134     MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40135
40136         constructor: MaterialLoader,
40137
40138         load: function ( url, onLoad, onProgress, onError ) {
40139
40140                 const scope = this;
40141
40142                 const loader = new FileLoader( scope.manager );
40143                 loader.setPath( scope.path );
40144                 loader.setRequestHeader( scope.requestHeader );
40145                 loader.setWithCredentials( scope.withCredentials );
40146                 loader.load( url, function ( text ) {
40147
40148                         try {
40149
40150                                 onLoad( scope.parse( JSON.parse( text ) ) );
40151
40152                         } catch ( e ) {
40153
40154                                 if ( onError ) {
40155
40156                                         onError( e );
40157
40158                                 } else {
40159
40160                                         console.error( e );
40161
40162                                 }
40163
40164                                 scope.manager.itemError( url );
40165
40166                         }
40167
40168                 }, onProgress, onError );
40169
40170         },
40171
40172         parse: function ( json ) {
40173
40174                 const textures = this.textures;
40175
40176                 function getTexture( name ) {
40177
40178                         if ( textures[ name ] === undefined ) {
40179
40180                                 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
40181
40182                         }
40183
40184                         return textures[ name ];
40185
40186                 }
40187
40188                 const material = new Materials[ json.type ]();
40189
40190                 if ( json.uuid !== undefined ) material.uuid = json.uuid;
40191                 if ( json.name !== undefined ) material.name = json.name;
40192                 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
40193                 if ( json.roughness !== undefined ) material.roughness = json.roughness;
40194                 if ( json.metalness !== undefined ) material.metalness = json.metalness;
40195                 if ( json.sheen !== undefined ) material.sheen = new Color().setHex( json.sheen );
40196                 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
40197                 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
40198                 if ( json.shininess !== undefined ) material.shininess = json.shininess;
40199                 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
40200                 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
40201                 if ( json.fog !== undefined ) material.fog = json.fog;
40202                 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
40203                 if ( json.blending !== undefined ) material.blending = json.blending;
40204                 if ( json.combine !== undefined ) material.combine = json.combine;
40205                 if ( json.side !== undefined ) material.side = json.side;
40206                 if ( json.opacity !== undefined ) material.opacity = json.opacity;
40207                 if ( json.transparent !== undefined ) material.transparent = json.transparent;
40208                 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
40209                 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
40210                 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
40211                 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
40212
40213                 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
40214                 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
40215                 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
40216                 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
40217                 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
40218                 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
40219                 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
40220                 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
40221
40222                 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
40223                 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
40224                 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
40225                 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
40226
40227                 if ( json.rotation !== undefined ) material.rotation = json.rotation;
40228
40229                 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
40230                 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
40231                 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
40232                 if ( json.scale !== undefined ) material.scale = json.scale;
40233
40234                 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
40235                 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
40236                 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
40237
40238                 if ( json.skinning !== undefined ) material.skinning = json.skinning;
40239                 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
40240                 if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
40241                 if ( json.dithering !== undefined ) material.dithering = json.dithering;
40242
40243                 if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
40244
40245                 if ( json.visible !== undefined ) material.visible = json.visible;
40246
40247                 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
40248
40249                 if ( json.userData !== undefined ) material.userData = json.userData;
40250
40251                 if ( json.vertexColors !== undefined ) {
40252
40253                         if ( typeof json.vertexColors === 'number' ) {
40254
40255                                 material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
40256
40257                         } else {
40258
40259                                 material.vertexColors = json.vertexColors;
40260
40261                         }
40262
40263                 }
40264
40265                 // Shader Material
40266
40267                 if ( json.uniforms !== undefined ) {
40268
40269                         for ( const name in json.uniforms ) {
40270
40271                                 const uniform = json.uniforms[ name ];
40272
40273                                 material.uniforms[ name ] = {};
40274
40275                                 switch ( uniform.type ) {
40276
40277                                         case 't':
40278                                                 material.uniforms[ name ].value = getTexture( uniform.value );
40279                                                 break;
40280
40281                                         case 'c':
40282                                                 material.uniforms[ name ].value = new Color().setHex( uniform.value );
40283                                                 break;
40284
40285                                         case 'v2':
40286                                                 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
40287                                                 break;
40288
40289                                         case 'v3':
40290                                                 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
40291                                                 break;
40292
40293                                         case 'v4':
40294                                                 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
40295                                                 break;
40296
40297                                         case 'm3':
40298                                                 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
40299                                                 break;
40300
40301                                         case 'm4':
40302                                                 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
40303                                                 break;
40304
40305                                         default:
40306                                                 material.uniforms[ name ].value = uniform.value;
40307
40308                                 }
40309
40310                         }
40311
40312                 }
40313
40314                 if ( json.defines !== undefined ) material.defines = json.defines;
40315                 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
40316                 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
40317
40318                 if ( json.extensions !== undefined ) {
40319
40320                         for ( const key in json.extensions ) {
40321
40322                                 material.extensions[ key ] = json.extensions[ key ];
40323
40324                         }
40325
40326                 }
40327
40328                 // Deprecated
40329
40330                 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
40331
40332                 // for PointsMaterial
40333
40334                 if ( json.size !== undefined ) material.size = json.size;
40335                 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
40336
40337                 // maps
40338
40339                 if ( json.map !== undefined ) material.map = getTexture( json.map );
40340                 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
40341
40342                 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
40343
40344                 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
40345                 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
40346
40347                 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
40348                 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
40349                 if ( json.normalScale !== undefined ) {
40350
40351                         let normalScale = json.normalScale;
40352
40353                         if ( Array.isArray( normalScale ) === false ) {
40354
40355                                 // Blender exporter used to export a scalar. See #7459
40356
40357                                 normalScale = [ normalScale, normalScale ];
40358
40359                         }
40360
40361                         material.normalScale = new Vector2().fromArray( normalScale );
40362
40363                 }
40364
40365                 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
40366                 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
40367                 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
40368
40369                 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
40370                 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
40371
40372                 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
40373                 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
40374
40375                 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
40376
40377                 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
40378                 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
40379
40380                 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
40381                 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
40382
40383                 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
40384                 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
40385
40386                 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
40387                 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
40388
40389                 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
40390
40391                 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
40392                 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
40393                 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
40394                 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
40395
40396                 if ( json.transmission !== undefined ) material.transmission = json.transmission;
40397                 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
40398
40399                 return material;
40400
40401         },
40402
40403         setTextures: function ( value ) {
40404
40405                 this.textures = value;
40406                 return this;
40407
40408         }
40409
40410     } );
40411
40412     const LoaderUtils = {
40413
40414         decodeText: function ( array ) {
40415
40416                 if ( typeof TextDecoder !== 'undefined' ) {
40417
40418                         return new TextDecoder().decode( array );
40419
40420                 }
40421
40422                 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
40423                 // throws a "maximum call stack size exceeded" error for large arrays.
40424
40425                 let s = '';
40426
40427                 for ( let i = 0, il = array.length; i < il; i ++ ) {
40428
40429                         // Implicitly assumes little-endian.
40430                         s += String.fromCharCode( array[ i ] );
40431
40432                 }
40433
40434                 try {
40435
40436                         // merges multi-byte utf-8 characters.
40437
40438                         return decodeURIComponent( escape( s ) );
40439
40440                 } catch ( e ) { // see #16358
40441
40442                         return s;
40443
40444                 }
40445
40446         },
40447
40448         extractUrlBase: function ( url ) {
40449
40450                 const index = url.lastIndexOf( '/' );
40451
40452                 if ( index === - 1 ) return './';
40453
40454                 return url.substr( 0, index + 1 );
40455
40456         }
40457
40458     };
40459
40460     function InstancedBufferGeometry() {
40461
40462         BufferGeometry.call( this );
40463
40464         this.type = 'InstancedBufferGeometry';
40465         this.instanceCount = Infinity;
40466
40467     }
40468
40469     InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
40470
40471         constructor: InstancedBufferGeometry,
40472
40473         isInstancedBufferGeometry: true,
40474
40475         copy: function ( source ) {
40476
40477                 BufferGeometry.prototype.copy.call( this, source );
40478
40479                 this.instanceCount = source.instanceCount;
40480
40481                 return this;
40482
40483         },
40484
40485         clone: function () {
40486
40487                 return new this.constructor().copy( this );
40488
40489         },
40490
40491         toJSON: function () {
40492
40493                 const data = BufferGeometry.prototype.toJSON.call( this );
40494
40495                 data.instanceCount = this.instanceCount;
40496
40497                 data.isInstancedBufferGeometry = true;
40498
40499                 return data;
40500
40501         }
40502
40503     } );
40504
40505     function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
40506
40507         if ( typeof ( normalized ) === 'number' ) {
40508
40509                 meshPerAttribute = normalized;
40510
40511                 normalized = false;
40512
40513                 console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
40514
40515         }
40516
40517         BufferAttribute.call( this, array, itemSize, normalized );
40518
40519         this.meshPerAttribute = meshPerAttribute || 1;
40520
40521     }
40522
40523     InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
40524
40525         constructor: InstancedBufferAttribute,
40526
40527         isInstancedBufferAttribute: true,
40528
40529         copy: function ( source ) {
40530
40531                 BufferAttribute.prototype.copy.call( this, source );
40532
40533                 this.meshPerAttribute = source.meshPerAttribute;
40534
40535                 return this;
40536
40537         },
40538
40539         toJSON: function ()     {
40540
40541                 const data = BufferAttribute.prototype.toJSON.call( this );
40542
40543                 data.meshPerAttribute = this.meshPerAttribute;
40544
40545                 data.isInstancedBufferAttribute = true;
40546
40547                 return data;
40548
40549         }
40550
40551     } );
40552
40553     function BufferGeometryLoader( manager ) {
40554
40555         Loader.call( this, manager );
40556
40557     }
40558
40559     BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40560
40561         constructor: BufferGeometryLoader,
40562
40563         load: function ( url, onLoad, onProgress, onError ) {
40564
40565                 const scope = this;
40566
40567                 const loader = new FileLoader( scope.manager );
40568                 loader.setPath( scope.path );
40569                 loader.setRequestHeader( scope.requestHeader );
40570                 loader.setWithCredentials( scope.withCredentials );
40571                 loader.load( url, function ( text ) {
40572
40573                         try {
40574
40575                                 onLoad( scope.parse( JSON.parse( text ) ) );
40576
40577                         } catch ( e ) {
40578
40579                                 if ( onError ) {
40580
40581                                         onError( e );
40582
40583                                 } else {
40584
40585                                         console.error( e );
40586
40587                                 }
40588
40589                                 scope.manager.itemError( url );
40590
40591                         }
40592
40593                 }, onProgress, onError );
40594
40595         },
40596
40597         parse: function ( json ) {
40598
40599                 const interleavedBufferMap = {};
40600                 const arrayBufferMap = {};
40601
40602                 function getInterleavedBuffer( json, uuid ) {
40603
40604                         if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
40605
40606                         const interleavedBuffers = json.interleavedBuffers;
40607                         const interleavedBuffer = interleavedBuffers[ uuid ];
40608
40609                         const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
40610
40611                         const array = getTypedArray( interleavedBuffer.type, buffer );
40612                         const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
40613                         ib.uuid = interleavedBuffer.uuid;
40614
40615                         interleavedBufferMap[ uuid ] = ib;
40616
40617                         return ib;
40618
40619                 }
40620
40621                 function getArrayBuffer( json, uuid ) {
40622
40623                         if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
40624
40625                         const arrayBuffers = json.arrayBuffers;
40626                         const arrayBuffer = arrayBuffers[ uuid ];
40627
40628                         const ab = new Uint32Array( arrayBuffer ).buffer;
40629
40630                         arrayBufferMap[ uuid ] = ab;
40631
40632                         return ab;
40633
40634                 }
40635
40636                 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
40637
40638                 const index = json.data.index;
40639
40640                 if ( index !== undefined ) {
40641
40642                         const typedArray = getTypedArray( index.type, index.array );
40643                         geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
40644
40645                 }
40646
40647                 const attributes = json.data.attributes;
40648
40649                 for ( const key in attributes ) {
40650
40651                         const attribute = attributes[ key ];
40652                         let bufferAttribute;
40653
40654                         if ( attribute.isInterleavedBufferAttribute ) {
40655
40656                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
40657                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
40658
40659                         } else {
40660
40661                                 const typedArray = getTypedArray( attribute.type, attribute.array );
40662                                 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
40663                                 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
40664
40665                         }
40666
40667                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40668                         geometry.setAttribute( key, bufferAttribute );
40669
40670                 }
40671
40672                 const morphAttributes = json.data.morphAttributes;
40673
40674                 if ( morphAttributes ) {
40675
40676                         for ( const key in morphAttributes ) {
40677
40678                                 const attributeArray = morphAttributes[ key ];
40679
40680                                 const array = [];
40681
40682                                 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
40683
40684                                         const attribute = attributeArray[ i ];
40685                                         let bufferAttribute;
40686
40687                                         if ( attribute.isInterleavedBufferAttribute ) {
40688
40689                                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
40690                                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
40691
40692                                         } else {
40693
40694                                                 const typedArray = getTypedArray( attribute.type, attribute.array );
40695                                                 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
40696
40697                                         }
40698
40699                                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40700                                         array.push( bufferAttribute );
40701
40702                                 }
40703
40704                                 geometry.morphAttributes[ key ] = array;
40705
40706                         }
40707
40708                 }
40709
40710                 const morphTargetsRelative = json.data.morphTargetsRelative;
40711
40712                 if ( morphTargetsRelative ) {
40713
40714                         geometry.morphTargetsRelative = true;
40715
40716                 }
40717
40718                 const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
40719
40720                 if ( groups !== undefined ) {
40721
40722                         for ( let i = 0, n = groups.length; i !== n; ++ i ) {
40723
40724                                 const group = groups[ i ];
40725
40726                                 geometry.addGroup( group.start, group.count, group.materialIndex );
40727
40728                         }
40729
40730                 }
40731
40732                 const boundingSphere = json.data.boundingSphere;
40733
40734                 if ( boundingSphere !== undefined ) {
40735
40736                         const center = new Vector3();
40737
40738                         if ( boundingSphere.center !== undefined ) {
40739
40740                                 center.fromArray( boundingSphere.center );
40741
40742                         }
40743
40744                         geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
40745
40746                 }
40747
40748                 if ( json.name ) geometry.name = json.name;
40749                 if ( json.userData ) geometry.userData = json.userData;
40750
40751                 return geometry;
40752
40753         }
40754
40755     } );
40756
40757     function ImageBitmapLoader( manager ) {
40758
40759         if ( typeof createImageBitmap === 'undefined' ) {
40760
40761                 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
40762
40763         }
40764
40765         if ( typeof fetch === 'undefined' ) {
40766
40767                 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
40768
40769         }
40770
40771         Loader.call( this, manager );
40772
40773         this.options = { premultiplyAlpha: 'none' };
40774
40775     }
40776
40777     ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40778
40779         constructor: ImageBitmapLoader,
40780
40781         isImageBitmapLoader: true,
40782
40783         setOptions: function setOptions( options ) {
40784
40785                 this.options = options;
40786
40787                 return this;
40788
40789         },
40790
40791         load: function ( url, onLoad, onProgress, onError ) {
40792
40793                 if ( url === undefined ) url = '';
40794
40795                 if ( this.path !== undefined ) url = this.path + url;
40796
40797                 url = this.manager.resolveURL( url );
40798
40799                 const scope = this;
40800
40801                 const cached = Cache.get( url );
40802
40803                 if ( cached !== undefined ) {
40804
40805                         scope.manager.itemStart( url );
40806
40807                         setTimeout( function () {
40808
40809                                 if ( onLoad ) onLoad( cached );
40810
40811                                 scope.manager.itemEnd( url );
40812
40813                         }, 0 );
40814
40815                         return cached;
40816
40817                 }
40818
40819                 const fetchOptions = {};
40820                 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
40821
40822                 fetch( url, fetchOptions ).then( function ( res ) {
40823
40824                         return res.blob();
40825
40826                 } ).then( function ( blob ) {
40827
40828                         return createImageBitmap( blob, scope.options );
40829
40830                 } ).then( function ( imageBitmap ) {
40831
40832                         Cache.add( url, imageBitmap );
40833
40834                         if ( onLoad ) onLoad( imageBitmap );
40835
40836                         scope.manager.itemEnd( url );
40837
40838                 } ).catch( function ( e ) {
40839
40840                         if ( onError ) onError( e );
40841
40842                         scope.manager.itemError( url );
40843                         scope.manager.itemEnd( url );
40844
40845                 } );
40846
40847                 scope.manager.itemStart( url );
40848
40849         }
40850
40851     } );
40852
40853     function ShapePath() {
40854
40855         this.type = 'ShapePath';
40856
40857         this.color = new Color();
40858
40859         this.subPaths = [];
40860         this.currentPath = null;
40861
40862     }
40863
40864     Object.assign( ShapePath.prototype, {
40865
40866         moveTo: function ( x, y ) {
40867
40868                 this.currentPath = new Path();
40869                 this.subPaths.push( this.currentPath );
40870                 this.currentPath.moveTo( x, y );
40871
40872                 return this;
40873
40874         },
40875
40876         lineTo: function ( x, y ) {
40877
40878                 this.currentPath.lineTo( x, y );
40879
40880                 return this;
40881
40882         },
40883
40884         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
40885
40886                 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
40887
40888                 return this;
40889
40890         },
40891
40892         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
40893
40894                 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
40895
40896                 return this;
40897
40898         },
40899
40900         splineThru: function ( pts ) {
40901
40902                 this.currentPath.splineThru( pts );
40903
40904                 return this;
40905
40906         },
40907
40908         toShapes: function ( isCCW, noHoles ) {
40909
40910                 function toShapesNoHoles( inSubpaths ) {
40911
40912                         const shapes = [];
40913
40914                         for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
40915
40916                                 const tmpPath = inSubpaths[ i ];
40917
40918                                 const tmpShape = new Shape();
40919                                 tmpShape.curves = tmpPath.curves;
40920
40921                                 shapes.push( tmpShape );
40922
40923                         }
40924
40925                         return shapes;
40926
40927                 }
40928
40929                 function isPointInsidePolygon( inPt, inPolygon ) {
40930
40931                         const polyLen = inPolygon.length;
40932
40933                         // inPt on polygon contour => immediate success    or
40934                         // toggling of inside/outside at every single! intersection point of an edge
40935                         //  with the horizontal line through inPt, left of inPt
40936                         //  not counting lowerY endpoints of edges and whole edges on that line
40937                         let inside = false;
40938                         for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
40939
40940                                 let edgeLowPt = inPolygon[ p ];
40941                                 let edgeHighPt = inPolygon[ q ];
40942
40943                                 let edgeDx = edgeHighPt.x - edgeLowPt.x;
40944                                 let edgeDy = edgeHighPt.y - edgeLowPt.y;
40945
40946                                 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
40947
40948                                         // not parallel
40949                                         if ( edgeDy < 0 ) {
40950
40951                                                 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
40952                                                 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
40953
40954                                         }
40955
40956                                         if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) )            continue;
40957
40958                                         if ( inPt.y === edgeLowPt.y ) {
40959
40960                                                 if ( inPt.x === edgeLowPt.x )           return  true;           // inPt is on contour ?
40961                                                 // continue;                            // no intersection or edgeLowPt => doesn't count !!!
40962
40963                                         } else {
40964
40965                                                 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
40966                                                 if ( perpEdge === 0 )                           return  true;           // inPt is on contour ?
40967                                                 if ( perpEdge < 0 )                             continue;
40968                                                 inside = ! inside;              // true intersection left of inPt
40969
40970                                         }
40971
40972                                 } else {
40973
40974                                         // parallel or collinear
40975                                         if ( inPt.y !== edgeLowPt.y )           continue;                       // parallel
40976                                         // edge lies on the same horizontal line as inPt
40977                                         if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
40978                                                  ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )          return  true;   // inPt: Point on contour !
40979                                         // continue;
40980
40981                                 }
40982
40983                         }
40984
40985                         return  inside;
40986
40987                 }
40988
40989                 const isClockWise = ShapeUtils.isClockWise;
40990
40991                 const subPaths = this.subPaths;
40992                 if ( subPaths.length === 0 ) return [];
40993
40994                 if ( noHoles === true ) return  toShapesNoHoles( subPaths );
40995
40996
40997                 let solid, tmpPath, tmpShape;
40998                 const shapes = [];
40999
41000                 if ( subPaths.length === 1 ) {
41001
41002                         tmpPath = subPaths[ 0 ];
41003                         tmpShape = new Shape();
41004                         tmpShape.curves = tmpPath.curves;
41005                         shapes.push( tmpShape );
41006                         return shapes;
41007
41008                 }
41009
41010                 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
41011                 holesFirst = isCCW ? ! holesFirst : holesFirst;
41012
41013                 // console.log("Holes first", holesFirst);
41014
41015                 const betterShapeHoles = [];
41016                 const newShapes = [];
41017                 let newShapeHoles = [];
41018                 let mainIdx = 0;
41019                 let tmpPoints;
41020
41021                 newShapes[ mainIdx ] = undefined;
41022                 newShapeHoles[ mainIdx ] = [];
41023
41024                 for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
41025
41026                         tmpPath = subPaths[ i ];
41027                         tmpPoints = tmpPath.getPoints();
41028                         solid = isClockWise( tmpPoints );
41029                         solid = isCCW ? ! solid : solid;
41030
41031                         if ( solid ) {
41032
41033                                 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )     mainIdx ++;
41034
41035                                 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
41036                                 newShapes[ mainIdx ].s.curves = tmpPath.curves;
41037
41038                                 if ( holesFirst )       mainIdx ++;
41039                                 newShapeHoles[ mainIdx ] = [];
41040
41041                                 //console.log('cw', i);
41042
41043                         } else {
41044
41045                                 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
41046
41047                                 //console.log('ccw', i);
41048
41049                         }
41050
41051                 }
41052
41053                 // only Holes? -> probably all Shapes with wrong orientation
41054                 if ( ! newShapes[ 0 ] ) return  toShapesNoHoles( subPaths );
41055
41056
41057                 if ( newShapes.length > 1 ) {
41058
41059                         let ambiguous = false;
41060                         const toChange = [];
41061
41062                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
41063
41064                                 betterShapeHoles[ sIdx ] = [];
41065
41066                         }
41067
41068                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
41069
41070                                 const sho = newShapeHoles[ sIdx ];
41071
41072                                 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
41073
41074                                         const ho = sho[ hIdx ];
41075                                         let hole_unassigned = true;
41076
41077                                         for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
41078
41079                                                 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
41080
41081                                                         if ( sIdx !== s2Idx )   toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
41082                                                         if ( hole_unassigned ) {
41083
41084                                                                 hole_unassigned = false;
41085                                                                 betterShapeHoles[ s2Idx ].push( ho );
41086
41087                                                         } else {
41088
41089                                                                 ambiguous = true;
41090
41091                                                         }
41092
41093                                                 }
41094
41095                                         }
41096
41097                                         if ( hole_unassigned ) {
41098
41099                                                 betterShapeHoles[ sIdx ].push( ho );
41100
41101                                         }
41102
41103                                 }
41104
41105                         }
41106                         // console.log("ambiguous: ", ambiguous);
41107
41108                         if ( toChange.length > 0 ) {
41109
41110                                 // console.log("to change: ", toChange);
41111                                 if ( ! ambiguous )      newShapeHoles = betterShapeHoles;
41112
41113                         }
41114
41115                 }
41116
41117                 let tmpHoles;
41118
41119                 for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
41120
41121                         tmpShape = newShapes[ i ].s;
41122                         shapes.push( tmpShape );
41123                         tmpHoles = newShapeHoles[ i ];
41124
41125                         for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
41126
41127                                 tmpShape.holes.push( tmpHoles[ j ].h );
41128
41129                         }
41130
41131                 }
41132
41133                 //console.log("shape", shapes);
41134
41135                 return shapes;
41136
41137         }
41138
41139     } );
41140
41141     class Font {
41142
41143         constructor( data ) {
41144
41145                 Object.defineProperty( this, 'isFont', { value: true } );
41146
41147                 this.type = 'Font';
41148
41149                 this.data = data;
41150
41151         }
41152
41153         generateShapes( text, size = 100 ) {
41154
41155                 const shapes = [];
41156                 const paths = createPaths( text, size, this.data );
41157
41158                 for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
41159
41160                         Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
41161
41162                 }
41163
41164                 return shapes;
41165
41166         }
41167
41168     }
41169
41170     function createPaths( text, size, data ) {
41171
41172         const chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // workaround for IE11, see #13988
41173         const scale = size / data.resolution;
41174         const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
41175
41176         const paths = [];
41177
41178         let offsetX = 0, offsetY = 0;
41179
41180         for ( let i = 0; i < chars.length; i ++ ) {
41181
41182                 const char = chars[ i ];
41183
41184                 if ( char === '\n' ) {
41185
41186                         offsetX = 0;
41187                         offsetY -= line_height;
41188
41189                 } else {
41190
41191                         const ret = createPath( char, scale, offsetX, offsetY, data );
41192                         offsetX += ret.offsetX;
41193                         paths.push( ret.path );
41194
41195                 }
41196
41197         }
41198
41199         return paths;
41200
41201     }
41202
41203     function createPath( char, scale, offsetX, offsetY, data ) {
41204
41205         const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
41206
41207         if ( ! glyph ) {
41208
41209                 console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
41210
41211                 return;
41212
41213         }
41214
41215         const path = new ShapePath();
41216
41217         let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
41218
41219         if ( glyph.o ) {
41220
41221                 const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
41222
41223                 for ( let i = 0, l = outline.length; i < l; ) {
41224
41225                         const action = outline[ i ++ ];
41226
41227                         switch ( action ) {
41228
41229                                 case 'm': // moveTo
41230
41231                                         x = outline[ i ++ ] * scale + offsetX;
41232                                         y = outline[ i ++ ] * scale + offsetY;
41233
41234                                         path.moveTo( x, y );
41235
41236                                         break;
41237
41238                                 case 'l': // lineTo
41239
41240                                         x = outline[ i ++ ] * scale + offsetX;
41241                                         y = outline[ i ++ ] * scale + offsetY;
41242
41243                                         path.lineTo( x, y );
41244
41245                                         break;
41246
41247                                 case 'q': // quadraticCurveTo
41248
41249                                         cpx = outline[ i ++ ] * scale + offsetX;
41250                                         cpy = outline[ i ++ ] * scale + offsetY;
41251                                         cpx1 = outline[ i ++ ] * scale + offsetX;
41252                                         cpy1 = outline[ i ++ ] * scale + offsetY;
41253
41254                                         path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
41255
41256                                         break;
41257
41258                                 case 'b': // bezierCurveTo
41259
41260                                         cpx = outline[ i ++ ] * scale + offsetX;
41261                                         cpy = outline[ i ++ ] * scale + offsetY;
41262                                         cpx1 = outline[ i ++ ] * scale + offsetX;
41263                                         cpy1 = outline[ i ++ ] * scale + offsetY;
41264                                         cpx2 = outline[ i ++ ] * scale + offsetX;
41265                                         cpy2 = outline[ i ++ ] * scale + offsetY;
41266
41267                                         path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
41268
41269                                         break;
41270
41271                         }
41272
41273                 }
41274
41275         }
41276
41277         return { offsetX: glyph.ha * scale, path: path };
41278
41279     }
41280
41281     function FontLoader( manager ) {
41282
41283         Loader.call( this, manager );
41284
41285     }
41286
41287     FontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41288
41289         constructor: FontLoader,
41290
41291         load: function ( url, onLoad, onProgress, onError ) {
41292
41293                 const scope = this;
41294
41295                 const loader = new FileLoader( this.manager );
41296                 loader.setPath( this.path );
41297                 loader.setRequestHeader( this.requestHeader );
41298                 loader.setWithCredentials( scope.withCredentials );
41299                 loader.load( url, function ( text ) {
41300
41301                         let json;
41302
41303                         try {
41304
41305                                 json = JSON.parse( text );
41306
41307                         } catch ( e ) {
41308
41309                                 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
41310                                 json = JSON.parse( text.substring( 65, text.length - 2 ) );
41311
41312                         }
41313
41314                         const font = scope.parse( json );
41315
41316                         if ( onLoad ) onLoad( font );
41317
41318                 }, onProgress, onError );
41319
41320         },
41321
41322         parse: function ( json ) {
41323
41324                 return new Font( json );
41325
41326         }
41327
41328     } );
41329
41330     let _context;
41331
41332     const AudioContext = {
41333
41334         getContext: function () {
41335
41336                 if ( _context === undefined ) {
41337
41338                         _context = new ( window.AudioContext || window.webkitAudioContext )();
41339
41340                 }
41341
41342                 return _context;
41343
41344         },
41345
41346         setContext: function ( value ) {
41347
41348                 _context = value;
41349
41350         }
41351
41352     };
41353
41354     function AudioLoader( manager ) {
41355
41356         Loader.call( this, manager );
41357
41358     }
41359
41360     AudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41361
41362         constructor: AudioLoader,
41363
41364         load: function ( url, onLoad, onProgress, onError ) {
41365
41366                 const scope = this;
41367
41368                 const loader = new FileLoader( scope.manager );
41369                 loader.setResponseType( 'arraybuffer' );
41370                 loader.setPath( scope.path );
41371                 loader.setRequestHeader( scope.requestHeader );
41372                 loader.setWithCredentials( scope.withCredentials );
41373                 loader.load( url, function ( buffer ) {
41374
41375                         try {
41376
41377                                 // Create a copy of the buffer. The `decodeAudioData` method
41378                                 // detaches the buffer when complete, preventing reuse.
41379                                 const bufferCopy = buffer.slice( 0 );
41380
41381                                 const context = AudioContext.getContext();
41382                                 context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
41383
41384                                         onLoad( audioBuffer );
41385
41386                                 } );
41387
41388                         } catch ( e ) {
41389
41390                                 if ( onError ) {
41391
41392                                         onError( e );
41393
41394                                 } else {
41395
41396                                         console.error( e );
41397
41398                                 }
41399
41400                                 scope.manager.itemError( url );
41401
41402                         }
41403
41404                 }, onProgress, onError );
41405
41406         }
41407
41408     } );
41409
41410     function HemisphereLightProbe( skyColor, groundColor, intensity ) {
41411
41412         LightProbe.call( this, undefined, intensity );
41413
41414         const color1 = new Color().set( skyColor );
41415         const color2 = new Color().set( groundColor );
41416
41417         const sky = new Vector3( color1.r, color1.g, color1.b );
41418         const ground = new Vector3( color2.r, color2.g, color2.b );
41419
41420         // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
41421         const c0 = Math.sqrt( Math.PI );
41422         const c1 = c0 * Math.sqrt( 0.75 );
41423
41424         this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
41425         this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
41426
41427     }
41428
41429     HemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
41430
41431         constructor: HemisphereLightProbe,
41432
41433         isHemisphereLightProbe: true,
41434
41435         copy: function ( source ) { // modifying colors not currently supported
41436
41437                 LightProbe.prototype.copy.call( this, source );
41438
41439                 return this;
41440
41441         },
41442
41443         toJSON: function ( meta ) {
41444
41445                 const data = LightProbe.prototype.toJSON.call( this, meta );
41446
41447                 // data.sh = this.sh.toArray(); // todo
41448
41449                 return data;
41450
41451         }
41452
41453     } );
41454
41455     function AmbientLightProbe( color, intensity ) {
41456
41457         LightProbe.call( this, undefined, intensity );
41458
41459         const color1 = new Color().set( color );
41460
41461         // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
41462         this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
41463
41464     }
41465
41466     AmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
41467
41468         constructor: AmbientLightProbe,
41469
41470         isAmbientLightProbe: true,
41471
41472         copy: function ( source ) { // modifying color not currently supported
41473
41474                 LightProbe.prototype.copy.call( this, source );
41475
41476                 return this;
41477
41478         },
41479
41480         toJSON: function ( meta ) {
41481
41482                 const data = LightProbe.prototype.toJSON.call( this, meta );
41483
41484                 // data.sh = this.sh.toArray(); // todo
41485
41486                 return data;
41487
41488         }
41489
41490     } );
41491
41492     const _eyeRight = new Matrix4();
41493     const _eyeLeft = new Matrix4();
41494
41495     function StereoCamera() {
41496
41497         this.type = 'StereoCamera';
41498
41499         this.aspect = 1;
41500
41501         this.eyeSep = 0.064;
41502
41503         this.cameraL = new PerspectiveCamera();
41504         this.cameraL.layers.enable( 1 );
41505         this.cameraL.matrixAutoUpdate = false;
41506
41507         this.cameraR = new PerspectiveCamera();
41508         this.cameraR.layers.enable( 2 );
41509         this.cameraR.matrixAutoUpdate = false;
41510
41511         this._cache = {
41512                 focus: null,
41513                 fov: null,
41514                 aspect: null,
41515                 near: null,
41516                 far: null,
41517                 zoom: null,
41518                 eyeSep: null
41519         };
41520
41521     }
41522
41523     Object.assign( StereoCamera.prototype, {
41524
41525         update: function ( camera ) {
41526
41527                 const cache = this._cache;
41528
41529                 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
41530                         cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
41531                         cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
41532
41533                 if ( needsUpdate ) {
41534
41535                         cache.focus = camera.focus;
41536                         cache.fov = camera.fov;
41537                         cache.aspect = camera.aspect * this.aspect;
41538                         cache.near = camera.near;
41539                         cache.far = camera.far;
41540                         cache.zoom = camera.zoom;
41541                         cache.eyeSep = this.eyeSep;
41542
41543                         // Off-axis stereoscopic effect based on
41544                         // http://paulbourke.net/stereographics/stereorender/
41545
41546                         const projectionMatrix = camera.projectionMatrix.clone();
41547                         const eyeSepHalf = cache.eyeSep / 2;
41548                         const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
41549                         const ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
41550                         let xmin, xmax;
41551
41552                         // translate xOffset
41553
41554                         _eyeLeft.elements[ 12 ] = - eyeSepHalf;
41555                         _eyeRight.elements[ 12 ] = eyeSepHalf;
41556
41557                         // for left eye
41558
41559                         xmin = - ymax * cache.aspect + eyeSepOnProjection;
41560                         xmax = ymax * cache.aspect + eyeSepOnProjection;
41561
41562                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
41563                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
41564
41565                         this.cameraL.projectionMatrix.copy( projectionMatrix );
41566
41567                         // for right eye
41568
41569                         xmin = - ymax * cache.aspect - eyeSepOnProjection;
41570                         xmax = ymax * cache.aspect - eyeSepOnProjection;
41571
41572                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
41573                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
41574
41575                         this.cameraR.projectionMatrix.copy( projectionMatrix );
41576
41577                 }
41578
41579                 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
41580                 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
41581
41582         }
41583
41584     } );
41585
41586     class Audio extends Object3D {
41587
41588         constructor( listener ) {
41589
41590                 super();
41591
41592                 this.type = 'Audio';
41593
41594                 this.listener = listener;
41595                 this.context = listener.context;
41596
41597                 this.gain = this.context.createGain();
41598                 this.gain.connect( listener.getInput() );
41599
41600                 this.autoplay = false;
41601
41602                 this.buffer = null;
41603                 this.detune = 0;
41604                 this.loop = false;
41605                 this.loopStart = 0;
41606                 this.loopEnd = 0;
41607                 this.offset = 0;
41608                 this.duration = undefined;
41609                 this.playbackRate = 1;
41610                 this.isPlaying = false;
41611                 this.hasPlaybackControl = true;
41612                 this.source = null;
41613                 this.sourceType = 'empty';
41614
41615                 this._startedAt = 0;
41616                 this._progress = 0;
41617                 this._connected = false;
41618
41619                 this.filters = [];
41620
41621         }
41622
41623         getOutput() {
41624
41625                 return this.gain;
41626
41627         }
41628
41629         setNodeSource( audioNode ) {
41630
41631                 this.hasPlaybackControl = false;
41632                 this.sourceType = 'audioNode';
41633                 this.source = audioNode;
41634                 this.connect();
41635
41636                 return this;
41637
41638         }
41639
41640         setMediaElementSource( mediaElement ) {
41641
41642                 this.hasPlaybackControl = false;
41643                 this.sourceType = 'mediaNode';
41644                 this.source = this.context.createMediaElementSource( mediaElement );
41645                 this.connect();
41646
41647                 return this;
41648
41649         }
41650
41651         setMediaStreamSource( mediaStream ) {
41652
41653                 this.hasPlaybackControl = false;
41654                 this.sourceType = 'mediaStreamNode';
41655                 this.source = this.context.createMediaStreamSource( mediaStream );
41656                 this.connect();
41657
41658                 return this;
41659
41660         }
41661
41662         setBuffer( audioBuffer ) {
41663
41664                 this.buffer = audioBuffer;
41665                 this.sourceType = 'buffer';
41666
41667                 if ( this.autoplay ) this.play();
41668
41669                 return this;
41670
41671         }
41672
41673         play( delay = 0 ) {
41674
41675                 if ( this.isPlaying === true ) {
41676
41677                         console.warn( 'THREE.Audio: Audio is already playing.' );
41678                         return;
41679
41680                 }
41681
41682                 if ( this.hasPlaybackControl === false ) {
41683
41684                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41685                         return;
41686
41687                 }
41688
41689                 this._startedAt = this.context.currentTime + delay;
41690
41691                 const source = this.context.createBufferSource();
41692                 source.buffer = this.buffer;
41693                 source.loop = this.loop;
41694                 source.loopStart = this.loopStart;
41695                 source.loopEnd = this.loopEnd;
41696                 source.onended = this.onEnded.bind( this );
41697                 source.start( this._startedAt, this._progress + this.offset, this.duration );
41698
41699                 this.isPlaying = true;
41700
41701                 this.source = source;
41702
41703                 this.setDetune( this.detune );
41704                 this.setPlaybackRate( this.playbackRate );
41705
41706                 return this.connect();
41707
41708         }
41709
41710         pause() {
41711
41712                 if ( this.hasPlaybackControl === false ) {
41713
41714                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41715                         return;
41716
41717                 }
41718
41719                 if ( this.isPlaying === true ) {
41720
41721                         // update current progress
41722
41723                         this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
41724
41725                         if ( this.loop === true ) {
41726
41727                                 // ensure _progress does not exceed duration with looped audios
41728
41729                                 this._progress = this._progress % ( this.duration || this.buffer.duration );
41730
41731                         }
41732
41733                         this.source.stop();
41734                         this.source.onended = null;
41735
41736                         this.isPlaying = false;
41737
41738                 }
41739
41740                 return this;
41741
41742         }
41743
41744         stop() {
41745
41746                 if ( this.hasPlaybackControl === false ) {
41747
41748                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41749                         return;
41750
41751                 }
41752
41753                 this._progress = 0;
41754
41755                 this.source.stop();
41756                 this.source.onended = null;
41757                 this.isPlaying = false;
41758
41759                 return this;
41760
41761         }
41762
41763         connect() {
41764
41765                 if ( this.filters.length > 0 ) {
41766
41767                         this.source.connect( this.filters[ 0 ] );
41768
41769                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
41770
41771                                 this.filters[ i - 1 ].connect( this.filters[ i ] );
41772
41773                         }
41774
41775                         this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
41776
41777                 } else {
41778
41779                         this.source.connect( this.getOutput() );
41780
41781                 }
41782
41783                 this._connected = true;
41784
41785                 return this;
41786
41787         }
41788
41789         disconnect() {
41790
41791                 if ( this.filters.length > 0 ) {
41792
41793                         this.source.disconnect( this.filters[ 0 ] );
41794
41795                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
41796
41797                                 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
41798
41799                         }
41800
41801                         this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
41802
41803                 } else {
41804
41805                         this.source.disconnect( this.getOutput() );
41806
41807                 }
41808
41809                 this._connected = false;
41810
41811                 return this;
41812
41813         }
41814
41815         getFilters() {
41816
41817                 return this.filters;
41818
41819         }
41820
41821         setFilters( value ) {
41822
41823                 if ( ! value ) value = [];
41824
41825                 if ( this._connected === true ) {
41826
41827                         this.disconnect();
41828                         this.filters = value.slice();
41829                         this.connect();
41830
41831                 } else {
41832
41833                         this.filters = value.slice();
41834
41835                 }
41836
41837                 return this;
41838
41839         }
41840
41841         setDetune( value ) {
41842
41843                 this.detune = value;
41844
41845                 if ( this.source.detune === undefined ) return; // only set detune when available
41846
41847                 if ( this.isPlaying === true ) {
41848
41849                         this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
41850
41851                 }
41852
41853                 return this;
41854
41855         }
41856
41857         getDetune() {
41858
41859                 return this.detune;
41860
41861         }
41862
41863         getFilter() {
41864
41865                 return this.getFilters()[ 0 ];
41866
41867         }
41868
41869         setFilter( filter ) {
41870
41871                 return this.setFilters( filter ? [ filter ] : [] );
41872
41873         }
41874
41875         setPlaybackRate( value ) {
41876
41877                 if ( this.hasPlaybackControl === false ) {
41878
41879                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41880                         return;
41881
41882                 }
41883
41884                 this.playbackRate = value;
41885
41886                 if ( this.isPlaying === true ) {
41887
41888                         this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
41889
41890                 }
41891
41892                 return this;
41893
41894         }
41895
41896         getPlaybackRate() {
41897
41898                 return this.playbackRate;
41899
41900         }
41901
41902         onEnded() {
41903
41904                 this.isPlaying = false;
41905
41906         }
41907
41908         getLoop() {
41909
41910                 if ( this.hasPlaybackControl === false ) {
41911
41912                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41913                         return false;
41914
41915                 }
41916
41917                 return this.loop;
41918
41919         }
41920
41921         setLoop( value ) {
41922
41923                 if ( this.hasPlaybackControl === false ) {
41924
41925                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
41926                         return;
41927
41928                 }
41929
41930                 this.loop = value;
41931
41932                 if ( this.isPlaying === true ) {
41933
41934                         this.source.loop = this.loop;
41935
41936                 }
41937
41938                 return this;
41939
41940         }
41941
41942         setLoopStart( value ) {
41943
41944                 this.loopStart = value;
41945
41946                 return this;
41947
41948         }
41949
41950         setLoopEnd( value ) {
41951
41952                 this.loopEnd = value;
41953
41954                 return this;
41955
41956         }
41957
41958         getVolume() {
41959
41960                 return this.gain.gain.value;
41961
41962         }
41963
41964         setVolume( value ) {
41965
41966                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
41967
41968                 return this;
41969
41970         }
41971
41972     }
41973
41974     function PropertyMixer( binding, typeName, valueSize ) {
41975
41976         this.binding = binding;
41977         this.valueSize = valueSize;
41978
41979         let mixFunction,
41980                 mixFunctionAdditive,
41981                 setIdentity;
41982
41983         // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
41984         //
41985         // interpolators can use .buffer as their .result
41986         // the data then goes to 'incoming'
41987         //
41988         // 'accu0' and 'accu1' are used frame-interleaved for
41989         // the cumulative result and are compared to detect
41990         // changes
41991         //
41992         // 'orig' stores the original state of the property
41993         //
41994         // 'add' is used for additive cumulative results
41995         //
41996         // 'work' is optional and is only present for quaternion types. It is used
41997         // to store intermediate quaternion multiplication results
41998
41999         switch ( typeName ) {
42000
42001                 case 'quaternion':
42002                         mixFunction = this._slerp;
42003                         mixFunctionAdditive = this._slerpAdditive;
42004                         setIdentity = this._setAdditiveIdentityQuaternion;
42005
42006                         this.buffer = new Float64Array( valueSize * 6 );
42007                         this._workIndex = 5;
42008                         break;
42009
42010                 case 'string':
42011                 case 'bool':
42012                         mixFunction = this._select;
42013
42014                         // Use the regular mix function and for additive on these types,
42015                         // additive is not relevant for non-numeric types
42016                         mixFunctionAdditive = this._select;
42017
42018                         setIdentity = this._setAdditiveIdentityOther;
42019
42020                         this.buffer = new Array( valueSize * 5 );
42021                         break;
42022
42023                 default:
42024                         mixFunction = this._lerp;
42025                         mixFunctionAdditive = this._lerpAdditive;
42026                         setIdentity = this._setAdditiveIdentityNumeric;
42027
42028                         this.buffer = new Float64Array( valueSize * 5 );
42029
42030         }
42031
42032         this._mixBufferRegion = mixFunction;
42033         this._mixBufferRegionAdditive = mixFunctionAdditive;
42034         this._setIdentity = setIdentity;
42035         this._origIndex = 3;
42036         this._addIndex = 4;
42037
42038         this.cumulativeWeight = 0;
42039         this.cumulativeWeightAdditive = 0;
42040
42041         this.useCount = 0;
42042         this.referenceCount = 0;
42043
42044     }
42045
42046     Object.assign( PropertyMixer.prototype, {
42047
42048         // accumulate data in the 'incoming' region into 'accu<i>'
42049         accumulate: function ( accuIndex, weight ) {
42050
42051                 // note: happily accumulating nothing when weight = 0, the caller knows
42052                 // the weight and shouldn't have made the call in the first place
42053
42054                 const buffer = this.buffer,
42055                         stride = this.valueSize,
42056                         offset = accuIndex * stride + stride;
42057
42058                 let currentWeight = this.cumulativeWeight;
42059
42060                 if ( currentWeight === 0 ) {
42061
42062                         // accuN := incoming * weight
42063
42064                         for ( let i = 0; i !== stride; ++ i ) {
42065
42066                                 buffer[ offset + i ] = buffer[ i ];
42067
42068                         }
42069
42070                         currentWeight = weight;
42071
42072                 } else {
42073
42074                         // accuN := accuN + incoming * weight
42075
42076                         currentWeight += weight;
42077                         const mix = weight / currentWeight;
42078                         this._mixBufferRegion( buffer, offset, 0, mix, stride );
42079
42080                 }
42081
42082                 this.cumulativeWeight = currentWeight;
42083
42084         },
42085
42086         // accumulate data in the 'incoming' region into 'add'
42087         accumulateAdditive: function ( weight ) {
42088
42089                 const buffer = this.buffer,
42090                         stride = this.valueSize,
42091                         offset = stride * this._addIndex;
42092
42093                 if ( this.cumulativeWeightAdditive === 0 ) {
42094
42095                         // add = identity
42096
42097                         this._setIdentity();
42098
42099                 }
42100
42101                 // add := add + incoming * weight
42102
42103                 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
42104                 this.cumulativeWeightAdditive += weight;
42105
42106         },
42107
42108         // apply the state of 'accu<i>' to the binding when accus differ
42109         apply: function ( accuIndex ) {
42110
42111                 const stride = this.valueSize,
42112                         buffer = this.buffer,
42113                         offset = accuIndex * stride + stride,
42114
42115                         weight = this.cumulativeWeight,
42116                         weightAdditive = this.cumulativeWeightAdditive,
42117
42118                         binding = this.binding;
42119
42120                 this.cumulativeWeight = 0;
42121                 this.cumulativeWeightAdditive = 0;
42122
42123                 if ( weight < 1 ) {
42124
42125                         // accuN := accuN + original * ( 1 - cumulativeWeight )
42126
42127                         const originalValueOffset = stride * this._origIndex;
42128
42129                         this._mixBufferRegion(
42130                                 buffer, offset, originalValueOffset, 1 - weight, stride );
42131
42132                 }
42133
42134                 if ( weightAdditive > 0 ) {
42135
42136                         // accuN := accuN + additive accuN
42137
42138                         this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
42139
42140                 }
42141
42142                 for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
42143
42144                         if ( buffer[ i ] !== buffer[ i + stride ] ) {
42145
42146                                 // value has changed -> update scene graph
42147
42148                                 binding.setValue( buffer, offset );
42149                                 break;
42150
42151                         }
42152
42153                 }
42154
42155         },
42156
42157         // remember the state of the bound property and copy it to both accus
42158         saveOriginalState: function () {
42159
42160                 const binding = this.binding;
42161
42162                 const buffer = this.buffer,
42163                         stride = this.valueSize,
42164
42165                         originalValueOffset = stride * this._origIndex;
42166
42167                 binding.getValue( buffer, originalValueOffset );
42168
42169                 // accu[0..1] := orig -- initially detect changes against the original
42170                 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
42171
42172                         buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
42173
42174                 }
42175
42176                 // Add to identity for additive
42177                 this._setIdentity();
42178
42179                 this.cumulativeWeight = 0;
42180                 this.cumulativeWeightAdditive = 0;
42181
42182         },
42183
42184         // apply the state previously taken via 'saveOriginalState' to the binding
42185         restoreOriginalState: function () {
42186
42187                 const originalValueOffset = this.valueSize * 3;
42188                 this.binding.setValue( this.buffer, originalValueOffset );
42189
42190         },
42191
42192         _setAdditiveIdentityNumeric: function () {
42193
42194                 const startIndex = this._addIndex * this.valueSize;
42195                 const endIndex = startIndex + this.valueSize;
42196
42197                 for ( let i = startIndex; i < endIndex; i ++ ) {
42198
42199                         this.buffer[ i ] = 0;
42200
42201                 }
42202
42203         },
42204
42205         _setAdditiveIdentityQuaternion: function () {
42206
42207                 this._setAdditiveIdentityNumeric();
42208                 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
42209
42210         },
42211
42212         _setAdditiveIdentityOther: function () {
42213
42214                 const startIndex = this._origIndex * this.valueSize;
42215                 const targetIndex = this._addIndex * this.valueSize;
42216
42217                 for ( let i = 0; i < this.valueSize; i ++ ) {
42218
42219                         this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
42220
42221                 }
42222
42223         },
42224
42225
42226         // mix functions
42227
42228         _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
42229
42230                 if ( t >= 0.5 ) {
42231
42232                         for ( let i = 0; i !== stride; ++ i ) {
42233
42234                                 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
42235
42236                         }
42237
42238                 }
42239
42240         },
42241
42242         _slerp: function ( buffer, dstOffset, srcOffset, t ) {
42243
42244                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
42245
42246         },
42247
42248         _slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
42249
42250                 const workOffset = this._workIndex * stride;
42251
42252                 // Store result in intermediate buffer offset
42253                 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
42254
42255                 // Slerp to the intermediate result
42256                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
42257
42258         },
42259
42260         _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
42261
42262                 const s = 1 - t;
42263
42264                 for ( let i = 0; i !== stride; ++ i ) {
42265
42266                         const j = dstOffset + i;
42267
42268                         buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
42269
42270                 }
42271
42272         },
42273
42274         _lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
42275
42276                 for ( let i = 0; i !== stride; ++ i ) {
42277
42278                         const j = dstOffset + i;
42279
42280                         buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
42281
42282                 }
42283
42284         }
42285
42286     } );
42287
42288     // Characters [].:/ are reserved for track binding syntax.
42289     const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
42290     const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
42291
42292     // Attempts to allow node names from any language. ES5's `\w` regexp matches
42293     // only latin characters, and the unicode \p{L} is not yet supported. So
42294     // instead, we exclude reserved characters and match everything else.
42295     const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
42296     const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
42297
42298     // Parent directories, delimited by '/' or ':'. Currently unused, but must
42299     // be matched to parse the rest of the track name.
42300     const _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
42301
42302     // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
42303     const _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
42304
42305     // Object on target node, and accessor. May not contain reserved
42306     // characters. Accessor may contain any character except closing bracket.
42307     const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
42308
42309     // Property and accessor. May not contain reserved characters. Accessor may
42310     // contain any non-bracket characters.
42311     const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
42312
42313     const _trackRe = new RegExp( ''
42314         + '^'
42315         + _directoryRe
42316         + _nodeRe
42317         + _objectRe
42318         + _propertyRe
42319         + '$'
42320     );
42321
42322     const _supportedObjectNames = [ 'material', 'materials', 'bones' ];
42323
42324     function Composite( targetGroup, path, optionalParsedPath ) {
42325
42326         const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
42327
42328         this._targetGroup = targetGroup;
42329         this._bindings = targetGroup.subscribe_( path, parsedPath );
42330
42331     }
42332
42333     Object.assign( Composite.prototype, {
42334
42335         getValue: function ( array, offset ) {
42336
42337                 this.bind(); // bind all binding
42338
42339                 const firstValidIndex = this._targetGroup.nCachedObjects_,
42340                         binding = this._bindings[ firstValidIndex ];
42341
42342                 // and only call .getValue on the first
42343                 if ( binding !== undefined ) binding.getValue( array, offset );
42344
42345         },
42346
42347         setValue: function ( array, offset ) {
42348
42349                 const bindings = this._bindings;
42350
42351                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
42352
42353                         bindings[ i ].setValue( array, offset );
42354
42355                 }
42356
42357         },
42358
42359         bind: function () {
42360
42361                 const bindings = this._bindings;
42362
42363                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
42364
42365                         bindings[ i ].bind();
42366
42367                 }
42368
42369         },
42370
42371         unbind: function () {
42372
42373                 const bindings = this._bindings;
42374
42375                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
42376
42377                         bindings[ i ].unbind();
42378
42379                 }
42380
42381         }
42382
42383     } );
42384
42385
42386     function PropertyBinding( rootNode, path, parsedPath ) {
42387
42388         this.path = path;
42389         this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
42390
42391         this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
42392
42393         this.rootNode = rootNode;
42394
42395     }
42396
42397     Object.assign( PropertyBinding, {
42398
42399         Composite: Composite,
42400
42401         create: function ( root, path, parsedPath ) {
42402
42403                 if ( ! ( root && root.isAnimationObjectGroup ) ) {
42404
42405                         return new PropertyBinding( root, path, parsedPath );
42406
42407                 } else {
42408
42409                         return new PropertyBinding.Composite( root, path, parsedPath );
42410
42411                 }
42412
42413         },
42414
42415         /**
42416          * Replaces spaces with underscores and removes unsupported characters from
42417          * node names, to ensure compatibility with parseTrackName().
42418          *
42419          * @param {string} name Node name to be sanitized.
42420          * @return {string}
42421          */
42422         sanitizeNodeName: function ( name ) {
42423
42424                 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
42425
42426         },
42427
42428         parseTrackName: function ( trackName ) {
42429
42430                 const matches = _trackRe.exec( trackName );
42431
42432                 if ( ! matches ) {
42433
42434                         throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
42435
42436                 }
42437
42438                 const results = {
42439                         // directoryName: matches[ 1 ], // (tschw) currently unused
42440                         nodeName: matches[ 2 ],
42441                         objectName: matches[ 3 ],
42442                         objectIndex: matches[ 4 ],
42443                         propertyName: matches[ 5 ], // required
42444                         propertyIndex: matches[ 6 ]
42445                 };
42446
42447                 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
42448
42449                 if ( lastDot !== undefined && lastDot !== - 1 ) {
42450
42451                         const objectName = results.nodeName.substring( lastDot + 1 );
42452
42453                         // Object names must be checked against an allowlist. Otherwise, there
42454                         // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
42455                         // 'bar' could be the objectName, or part of a nodeName (which can
42456                         // include '.' characters).
42457                         if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
42458
42459                                 results.nodeName = results.nodeName.substring( 0, lastDot );
42460                                 results.objectName = objectName;
42461
42462                         }
42463
42464                 }
42465
42466                 if ( results.propertyName === null || results.propertyName.length === 0 ) {
42467
42468                         throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
42469
42470                 }
42471
42472                 return results;
42473
42474         },
42475
42476         findNode: function ( root, nodeName ) {
42477
42478                 if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
42479
42480                         return root;
42481
42482                 }
42483
42484                 // search into skeleton bones.
42485                 if ( root.skeleton ) {
42486
42487                         const bone = root.skeleton.getBoneByName( nodeName );
42488
42489                         if ( bone !== undefined ) {
42490
42491                                 return bone;
42492
42493                         }
42494
42495                 }
42496
42497                 // search into node subtree.
42498                 if ( root.children ) {
42499
42500                         const searchNodeSubtree = function ( children ) {
42501
42502                                 for ( let i = 0; i < children.length; i ++ ) {
42503
42504                                         const childNode = children[ i ];
42505
42506                                         if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
42507
42508                                                 return childNode;
42509
42510                                         }
42511
42512                                         const result = searchNodeSubtree( childNode.children );
42513
42514                                         if ( result ) return result;
42515
42516                                 }
42517
42518                                 return null;
42519
42520                         };
42521
42522                         const subTreeNode = searchNodeSubtree( root.children );
42523
42524                         if ( subTreeNode ) {
42525
42526                                 return subTreeNode;
42527
42528                         }
42529
42530                 }
42531
42532                 return null;
42533
42534         }
42535
42536     } );
42537
42538     Object.assign( PropertyBinding.prototype, { // prototype, continued
42539
42540         // these are used to "bind" a nonexistent property
42541         _getValue_unavailable: function () {},
42542         _setValue_unavailable: function () {},
42543
42544         BindingType: {
42545                 Direct: 0,
42546                 EntireArray: 1,
42547                 ArrayElement: 2,
42548                 HasFromToArray: 3
42549         },
42550
42551         Versioning: {
42552                 None: 0,
42553                 NeedsUpdate: 1,
42554                 MatrixWorldNeedsUpdate: 2
42555         },
42556
42557         GetterByBindingType: [
42558
42559                 function getValue_direct( buffer, offset ) {
42560
42561                         buffer[ offset ] = this.node[ this.propertyName ];
42562
42563                 },
42564
42565                 function getValue_array( buffer, offset ) {
42566
42567                         const source = this.resolvedProperty;
42568
42569                         for ( let i = 0, n = source.length; i !== n; ++ i ) {
42570
42571                                 buffer[ offset ++ ] = source[ i ];
42572
42573                         }
42574
42575                 },
42576
42577                 function getValue_arrayElement( buffer, offset ) {
42578
42579                         buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
42580
42581                 },
42582
42583                 function getValue_toArray( buffer, offset ) {
42584
42585                         this.resolvedProperty.toArray( buffer, offset );
42586
42587                 }
42588
42589         ],
42590
42591         SetterByBindingTypeAndVersioning: [
42592
42593                 [
42594                         // Direct
42595
42596                         function setValue_direct( buffer, offset ) {
42597
42598                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
42599
42600                         },
42601
42602                         function setValue_direct_setNeedsUpdate( buffer, offset ) {
42603
42604                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
42605                                 this.targetObject.needsUpdate = true;
42606
42607                         },
42608
42609                         function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
42610
42611                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
42612                                 this.targetObject.matrixWorldNeedsUpdate = true;
42613
42614                         }
42615
42616                 ], [
42617
42618                         // EntireArray
42619
42620                         function setValue_array( buffer, offset ) {
42621
42622                                 const dest = this.resolvedProperty;
42623
42624                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
42625
42626                                         dest[ i ] = buffer[ offset ++ ];
42627
42628                                 }
42629
42630                         },
42631
42632                         function setValue_array_setNeedsUpdate( buffer, offset ) {
42633
42634                                 const dest = this.resolvedProperty;
42635
42636                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
42637
42638                                         dest[ i ] = buffer[ offset ++ ];
42639
42640                                 }
42641
42642                                 this.targetObject.needsUpdate = true;
42643
42644                         },
42645
42646                         function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
42647
42648                                 const dest = this.resolvedProperty;
42649
42650                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
42651
42652                                         dest[ i ] = buffer[ offset ++ ];
42653
42654                                 }
42655
42656                                 this.targetObject.matrixWorldNeedsUpdate = true;
42657
42658                         }
42659
42660                 ], [
42661
42662                         // ArrayElement
42663
42664                         function setValue_arrayElement( buffer, offset ) {
42665
42666                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
42667
42668                         },
42669
42670                         function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
42671
42672                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
42673                                 this.targetObject.needsUpdate = true;
42674
42675                         },
42676
42677                         function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
42678
42679                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
42680                                 this.targetObject.matrixWorldNeedsUpdate = true;
42681
42682                         }
42683
42684                 ], [
42685
42686                         // HasToFromArray
42687
42688                         function setValue_fromArray( buffer, offset ) {
42689
42690                                 this.resolvedProperty.fromArray( buffer, offset );
42691
42692                         },
42693
42694                         function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
42695
42696                                 this.resolvedProperty.fromArray( buffer, offset );
42697                                 this.targetObject.needsUpdate = true;
42698
42699                         },
42700
42701                         function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
42702
42703                                 this.resolvedProperty.fromArray( buffer, offset );
42704                                 this.targetObject.matrixWorldNeedsUpdate = true;
42705
42706                         }
42707
42708                 ]
42709
42710         ],
42711
42712         getValue: function getValue_unbound( targetArray, offset ) {
42713
42714                 this.bind();
42715                 this.getValue( targetArray, offset );
42716
42717                 // Note: This class uses a State pattern on a per-method basis:
42718                 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
42719                 // prototype version of these methods with one that represents
42720                 // the bound state. When the property is not found, the methods
42721                 // become no-ops.
42722
42723         },
42724
42725         setValue: function getValue_unbound( sourceArray, offset ) {
42726
42727                 this.bind();
42728                 this.setValue( sourceArray, offset );
42729
42730         },
42731
42732         // create getter / setter pair for a property in the scene graph
42733         bind: function () {
42734
42735                 let targetObject = this.node;
42736                 const parsedPath = this.parsedPath;
42737
42738                 const objectName = parsedPath.objectName;
42739                 const propertyName = parsedPath.propertyName;
42740                 let propertyIndex = parsedPath.propertyIndex;
42741
42742                 if ( ! targetObject ) {
42743
42744                         targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
42745
42746                         this.node = targetObject;
42747
42748                 }
42749
42750                 // set fail state so we can just 'return' on error
42751                 this.getValue = this._getValue_unavailable;
42752                 this.setValue = this._setValue_unavailable;
42753
42754                 // ensure there is a value node
42755                 if ( ! targetObject ) {
42756
42757                         console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
42758                         return;
42759
42760                 }
42761
42762                 if ( objectName ) {
42763
42764                         let objectIndex = parsedPath.objectIndex;
42765
42766                         // special cases were we need to reach deeper into the hierarchy to get the face materials....
42767                         switch ( objectName ) {
42768
42769                                 case 'materials':
42770
42771                                         if ( ! targetObject.material ) {
42772
42773                                                 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
42774                                                 return;
42775
42776                                         }
42777
42778                                         if ( ! targetObject.material.materials ) {
42779
42780                                                 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
42781                                                 return;
42782
42783                                         }
42784
42785                                         targetObject = targetObject.material.materials;
42786
42787                                         break;
42788
42789                                 case 'bones':
42790
42791                                         if ( ! targetObject.skeleton ) {
42792
42793                                                 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
42794                                                 return;
42795
42796                                         }
42797
42798                                         // potential future optimization: skip this if propertyIndex is already an integer
42799                                         // and convert the integer string to a true integer.
42800
42801                                         targetObject = targetObject.skeleton.bones;
42802
42803                                         // support resolving morphTarget names into indices.
42804                                         for ( let i = 0; i < targetObject.length; i ++ ) {
42805
42806                                                 if ( targetObject[ i ].name === objectIndex ) {
42807
42808                                                         objectIndex = i;
42809                                                         break;
42810
42811                                                 }
42812
42813                                         }
42814
42815                                         break;
42816
42817                                 default:
42818
42819                                         if ( targetObject[ objectName ] === undefined ) {
42820
42821                                                 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
42822                                                 return;
42823
42824                                         }
42825
42826                                         targetObject = targetObject[ objectName ];
42827
42828                         }
42829
42830
42831                         if ( objectIndex !== undefined ) {
42832
42833                                 if ( targetObject[ objectIndex ] === undefined ) {
42834
42835                                         console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
42836                                         return;
42837
42838                                 }
42839
42840                                 targetObject = targetObject[ objectIndex ];
42841
42842                         }
42843
42844                 }
42845
42846                 // resolve property
42847                 const nodeProperty = targetObject[ propertyName ];
42848
42849                 if ( nodeProperty === undefined ) {
42850
42851                         const nodeName = parsedPath.nodeName;
42852
42853                         console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
42854                                 '.' + propertyName + ' but it wasn\'t found.', targetObject );
42855                         return;
42856
42857                 }
42858
42859                 // determine versioning scheme
42860                 let versioning = this.Versioning.None;
42861
42862                 this.targetObject = targetObject;
42863
42864                 if ( targetObject.needsUpdate !== undefined ) { // material
42865
42866                         versioning = this.Versioning.NeedsUpdate;
42867
42868                 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
42869
42870                         versioning = this.Versioning.MatrixWorldNeedsUpdate;
42871
42872                 }
42873
42874                 // determine how the property gets bound
42875                 let bindingType = this.BindingType.Direct;
42876
42877                 if ( propertyIndex !== undefined ) {
42878
42879                         // access a sub element of the property array (only primitives are supported right now)
42880
42881                         if ( propertyName === 'morphTargetInfluences' ) {
42882
42883                                 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
42884
42885                                 // support resolving morphTarget names into indices.
42886                                 if ( ! targetObject.geometry ) {
42887
42888                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
42889                                         return;
42890
42891                                 }
42892
42893                                 if ( targetObject.geometry.isBufferGeometry ) {
42894
42895                                         if ( ! targetObject.geometry.morphAttributes ) {
42896
42897                                                 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
42898                                                 return;
42899
42900                                         }
42901
42902                                         if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
42903
42904                                                 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
42905
42906                                         }
42907
42908
42909                                 } else {
42910
42911                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.', this );
42912                                         return;
42913
42914                                 }
42915
42916                         }
42917
42918                         bindingType = this.BindingType.ArrayElement;
42919
42920                         this.resolvedProperty = nodeProperty;
42921                         this.propertyIndex = propertyIndex;
42922
42923                 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
42924
42925                         // must use copy for Object3D.Euler/Quaternion
42926
42927                         bindingType = this.BindingType.HasFromToArray;
42928
42929                         this.resolvedProperty = nodeProperty;
42930
42931                 } else if ( Array.isArray( nodeProperty ) ) {
42932
42933                         bindingType = this.BindingType.EntireArray;
42934
42935                         this.resolvedProperty = nodeProperty;
42936
42937                 } else {
42938
42939                         this.propertyName = propertyName;
42940
42941                 }
42942
42943                 // select getter / setter
42944                 this.getValue = this.GetterByBindingType[ bindingType ];
42945                 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
42946
42947         },
42948
42949         unbind: function () {
42950
42951                 this.node = null;
42952
42953                 // back to the prototype version of getValue / setValue
42954                 // note: avoiding to mutate the shape of 'this' via 'delete'
42955                 this.getValue = this._getValue_unbound;
42956                 this.setValue = this._setValue_unbound;
42957
42958         }
42959
42960     } );
42961
42962     // DECLARE ALIAS AFTER assign prototype
42963     Object.assign( PropertyBinding.prototype, {
42964
42965         // initial state of these methods that calls 'bind'
42966         _getValue_unbound: PropertyBinding.prototype.getValue,
42967         _setValue_unbound: PropertyBinding.prototype.setValue,
42968
42969     } );
42970
42971     /**
42972      *
42973      * A group of objects that receives a shared animation state.
42974      *
42975      * Usage:
42976      *
42977      *  - Add objects you would otherwise pass as 'root' to the
42978      *    constructor or the .clipAction method of AnimationMixer.
42979      *
42980      *  - Instead pass this object as 'root'.
42981      *
42982      *  - You can also add and remove objects later when the mixer
42983      *    is running.
42984      *
42985      * Note:
42986      *
42987      *    Objects of this class appear as one object to the mixer,
42988      *    so cache control of the individual objects must be done
42989      *    on the group.
42990      *
42991      * Limitation:
42992      *
42993      *  - The animated properties must be compatible among the
42994      *    all objects in the group.
42995      *
42996      *  - A single property can either be controlled through a
42997      *    target group or directly, but not both.
42998      */
42999
43000     function AnimationObjectGroup() {
43001
43002         this.uuid = MathUtils.generateUUID();
43003
43004         // cached objects followed by the active ones
43005         this._objects = Array.prototype.slice.call( arguments );
43006
43007         this.nCachedObjects_ = 0; // threshold
43008         // note: read by PropertyBinding.Composite
43009
43010         const indices = {};
43011         this._indicesByUUID = indices; // for bookkeeping
43012
43013         for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
43014
43015                 indices[ arguments[ i ].uuid ] = i;
43016
43017         }
43018
43019         this._paths = []; // inside: string
43020         this._parsedPaths = []; // inside: { we don't care, here }
43021         this._bindings = []; // inside: Array< PropertyBinding >
43022         this._bindingsIndicesByPath = {}; // inside: indices in these arrays
43023
43024         const scope = this;
43025
43026         this.stats = {
43027
43028                 objects: {
43029                         get total() {
43030
43031                                 return scope._objects.length;
43032
43033                         },
43034                         get inUse() {
43035
43036                                 return this.total - scope.nCachedObjects_;
43037
43038                         }
43039                 },
43040                 get bindingsPerObject() {
43041
43042                         return scope._bindings.length;
43043
43044                 }
43045
43046         };
43047
43048     }
43049
43050     Object.assign( AnimationObjectGroup.prototype, {
43051
43052         isAnimationObjectGroup: true,
43053
43054         add: function () {
43055
43056                 const objects = this._objects,
43057                         indicesByUUID = this._indicesByUUID,
43058                         paths = this._paths,
43059                         parsedPaths = this._parsedPaths,
43060                         bindings = this._bindings,
43061                         nBindings = bindings.length;
43062
43063                 let knownObject = undefined,
43064                         nObjects = objects.length,
43065                         nCachedObjects = this.nCachedObjects_;
43066
43067                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
43068
43069                         const object = arguments[ i ],
43070                                 uuid = object.uuid;
43071                         let index = indicesByUUID[ uuid ];
43072
43073                         if ( index === undefined ) {
43074
43075                                 // unknown object -> add it to the ACTIVE region
43076
43077                                 index = nObjects ++;
43078                                 indicesByUUID[ uuid ] = index;
43079                                 objects.push( object );
43080
43081                                 // accounting is done, now do the same for all bindings
43082
43083                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
43084
43085                                         bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
43086
43087                                 }
43088
43089                         } else if ( index < nCachedObjects ) {
43090
43091                                 knownObject = objects[ index ];
43092
43093                                 // move existing object to the ACTIVE region
43094
43095                                 const firstActiveIndex = -- nCachedObjects,
43096                                         lastCachedObject = objects[ firstActiveIndex ];
43097
43098                                 indicesByUUID[ lastCachedObject.uuid ] = index;
43099                                 objects[ index ] = lastCachedObject;
43100
43101                                 indicesByUUID[ uuid ] = firstActiveIndex;
43102                                 objects[ firstActiveIndex ] = object;
43103
43104                                 // accounting is done, now do the same for all bindings
43105
43106                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
43107
43108                                         const bindingsForPath = bindings[ j ],
43109                                                 lastCached = bindingsForPath[ firstActiveIndex ];
43110
43111                                         let binding = bindingsForPath[ index ];
43112
43113                                         bindingsForPath[ index ] = lastCached;
43114
43115                                         if ( binding === undefined ) {
43116
43117                                                 // since we do not bother to create new bindings
43118                                                 // for objects that are cached, the binding may
43119                                                 // or may not exist
43120
43121                                                 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
43122
43123                                         }
43124
43125                                         bindingsForPath[ firstActiveIndex ] = binding;
43126
43127                                 }
43128
43129                         } else if ( objects[ index ] !== knownObject ) {
43130
43131                                 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
43132                                         'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
43133
43134                         } // else the object is already where we want it to be
43135
43136                 } // for arguments
43137
43138                 this.nCachedObjects_ = nCachedObjects;
43139
43140         },
43141
43142         remove: function () {
43143
43144                 const objects = this._objects,
43145                         indicesByUUID = this._indicesByUUID,
43146                         bindings = this._bindings,
43147                         nBindings = bindings.length;
43148
43149                 let nCachedObjects = this.nCachedObjects_;
43150
43151                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
43152
43153                         const object = arguments[ i ],
43154                                 uuid = object.uuid,
43155                                 index = indicesByUUID[ uuid ];
43156
43157                         if ( index !== undefined && index >= nCachedObjects ) {
43158
43159                                 // move existing object into the CACHED region
43160
43161                                 const lastCachedIndex = nCachedObjects ++,
43162                                         firstActiveObject = objects[ lastCachedIndex ];
43163
43164                                 indicesByUUID[ firstActiveObject.uuid ] = index;
43165                                 objects[ index ] = firstActiveObject;
43166
43167                                 indicesByUUID[ uuid ] = lastCachedIndex;
43168                                 objects[ lastCachedIndex ] = object;
43169
43170                                 // accounting is done, now do the same for all bindings
43171
43172                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
43173
43174                                         const bindingsForPath = bindings[ j ],
43175                                                 firstActive = bindingsForPath[ lastCachedIndex ],
43176                                                 binding = bindingsForPath[ index ];
43177
43178                                         bindingsForPath[ index ] = firstActive;
43179                                         bindingsForPath[ lastCachedIndex ] = binding;
43180
43181                                 }
43182
43183                         }
43184
43185                 } // for arguments
43186
43187                 this.nCachedObjects_ = nCachedObjects;
43188
43189         },
43190
43191         // remove & forget
43192         uncache: function () {
43193
43194                 const objects = this._objects,
43195                         indicesByUUID = this._indicesByUUID,
43196                         bindings = this._bindings,
43197                         nBindings = bindings.length;
43198
43199                 let nCachedObjects = this.nCachedObjects_,
43200                         nObjects = objects.length;
43201
43202                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
43203
43204                         const object = arguments[ i ],
43205                                 uuid = object.uuid,
43206                                 index = indicesByUUID[ uuid ];
43207
43208                         if ( index !== undefined ) {
43209
43210                                 delete indicesByUUID[ uuid ];
43211
43212                                 if ( index < nCachedObjects ) {
43213
43214                                         // object is cached, shrink the CACHED region
43215
43216                                         const firstActiveIndex = -- nCachedObjects,
43217                                                 lastCachedObject = objects[ firstActiveIndex ],
43218                                                 lastIndex = -- nObjects,
43219                                                 lastObject = objects[ lastIndex ];
43220
43221                                         // last cached object takes this object's place
43222                                         indicesByUUID[ lastCachedObject.uuid ] = index;
43223                                         objects[ index ] = lastCachedObject;
43224
43225                                         // last object goes to the activated slot and pop
43226                                         indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
43227                                         objects[ firstActiveIndex ] = lastObject;
43228                                         objects.pop();
43229
43230                                         // accounting is done, now do the same for all bindings
43231
43232                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
43233
43234                                                 const bindingsForPath = bindings[ j ],
43235                                                         lastCached = bindingsForPath[ firstActiveIndex ],
43236                                                         last = bindingsForPath[ lastIndex ];
43237
43238                                                 bindingsForPath[ index ] = lastCached;
43239                                                 bindingsForPath[ firstActiveIndex ] = last;
43240                                                 bindingsForPath.pop();
43241
43242                                         }
43243
43244                                 } else {
43245
43246                                         // object is active, just swap with the last and pop
43247
43248                                         const lastIndex = -- nObjects,
43249                                                 lastObject = objects[ lastIndex ];
43250
43251                                         if ( lastIndex > 0 ) {
43252
43253                                                 indicesByUUID[ lastObject.uuid ] = index;
43254
43255                                         }
43256
43257                                         objects[ index ] = lastObject;
43258                                         objects.pop();
43259
43260                                         // accounting is done, now do the same for all bindings
43261
43262                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
43263
43264                                                 const bindingsForPath = bindings[ j ];
43265
43266                                                 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
43267                                                 bindingsForPath.pop();
43268
43269                                         }
43270
43271                                 } // cached or active
43272
43273                         } // if object is known
43274
43275                 } // for arguments
43276
43277                 this.nCachedObjects_ = nCachedObjects;
43278
43279         },
43280
43281         // Internal interface used by befriended PropertyBinding.Composite:
43282
43283         subscribe_: function ( path, parsedPath ) {
43284
43285                 // returns an array of bindings for the given path that is changed
43286                 // according to the contained objects in the group
43287
43288                 const indicesByPath = this._bindingsIndicesByPath;
43289                 let index = indicesByPath[ path ];
43290                 const bindings = this._bindings;
43291
43292                 if ( index !== undefined ) return bindings[ index ];
43293
43294                 const paths = this._paths,
43295                         parsedPaths = this._parsedPaths,
43296                         objects = this._objects,
43297                         nObjects = objects.length,
43298                         nCachedObjects = this.nCachedObjects_,
43299                         bindingsForPath = new Array( nObjects );
43300
43301                 index = bindings.length;
43302
43303                 indicesByPath[ path ] = index;
43304
43305                 paths.push( path );
43306                 parsedPaths.push( parsedPath );
43307                 bindings.push( bindingsForPath );
43308
43309                 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
43310
43311                         const object = objects[ i ];
43312                         bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
43313
43314                 }
43315
43316                 return bindingsForPath;
43317
43318         },
43319
43320         unsubscribe_: function ( path ) {
43321
43322                 // tells the group to forget about a property path and no longer
43323                 // update the array previously obtained with 'subscribe_'
43324
43325                 const indicesByPath = this._bindingsIndicesByPath,
43326                         index = indicesByPath[ path ];
43327
43328                 if ( index !== undefined ) {
43329
43330                         const paths = this._paths,
43331                                 parsedPaths = this._parsedPaths,
43332                                 bindings = this._bindings,
43333                                 lastBindingsIndex = bindings.length - 1,
43334                                 lastBindings = bindings[ lastBindingsIndex ],
43335                                 lastBindingsPath = path[ lastBindingsIndex ];
43336
43337                         indicesByPath[ lastBindingsPath ] = index;
43338
43339                         bindings[ index ] = lastBindings;
43340                         bindings.pop();
43341
43342                         parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
43343                         parsedPaths.pop();
43344
43345                         paths[ index ] = paths[ lastBindingsIndex ];
43346                         paths.pop();
43347
43348                 }
43349
43350         }
43351
43352     } );
43353
43354     class AnimationAction {
43355
43356         constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
43357
43358                 this._mixer = mixer;
43359                 this._clip = clip;
43360                 this._localRoot = localRoot;
43361                 this.blendMode = blendMode;
43362
43363                 const tracks = clip.tracks,
43364                         nTracks = tracks.length,
43365                         interpolants = new Array( nTracks );
43366
43367                 const interpolantSettings = {
43368                         endingStart: ZeroCurvatureEnding,
43369                         endingEnd: ZeroCurvatureEnding
43370                 };
43371
43372                 for ( let i = 0; i !== nTracks; ++ i ) {
43373
43374                         const interpolant = tracks[ i ].createInterpolant( null );
43375                         interpolants[ i ] = interpolant;
43376                         interpolant.settings = interpolantSettings;
43377
43378                 }
43379
43380                 this._interpolantSettings = interpolantSettings;
43381
43382                 this._interpolants = interpolants; // bound by the mixer
43383
43384                 // inside: PropertyMixer (managed by the mixer)
43385                 this._propertyBindings = new Array( nTracks );
43386
43387                 this._cacheIndex = null; // for the memory manager
43388                 this._byClipCacheIndex = null; // for the memory manager
43389
43390                 this._timeScaleInterpolant = null;
43391                 this._weightInterpolant = null;
43392
43393                 this.loop = LoopRepeat;
43394                 this._loopCount = - 1;
43395
43396                 // global mixer time when the action is to be started
43397                 // it's set back to 'null' upon start of the action
43398                 this._startTime = null;
43399
43400                 // scaled local time of the action
43401                 // gets clamped or wrapped to 0..clip.duration according to loop
43402                 this.time = 0;
43403
43404                 this.timeScale = 1;
43405                 this._effectiveTimeScale = 1;
43406
43407                 this.weight = 1;
43408                 this._effectiveWeight = 1;
43409
43410                 this.repetitions = Infinity; // no. of repetitions when looping
43411
43412                 this.paused = false; // true -> zero effective time scale
43413                 this.enabled = true; // false -> zero effective weight
43414
43415                 this.clampWhenFinished = false;// keep feeding the last frame?
43416
43417                 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
43418                 this.zeroSlopeAtEnd = true;// clips for start, loop and end
43419
43420         }
43421
43422         // State & Scheduling
43423
43424         play() {
43425
43426                 this._mixer._activateAction( this );
43427
43428                 return this;
43429
43430         }
43431
43432         stop() {
43433
43434                 this._mixer._deactivateAction( this );
43435
43436                 return this.reset();
43437
43438         }
43439
43440         reset() {
43441
43442                 this.paused = false;
43443                 this.enabled = true;
43444
43445                 this.time = 0; // restart clip
43446                 this._loopCount = - 1;// forget previous loops
43447                 this._startTime = null;// forget scheduling
43448
43449                 return this.stopFading().stopWarping();
43450
43451         }
43452
43453         isRunning() {
43454
43455                 return this.enabled && ! this.paused && this.timeScale !== 0 &&
43456                         this._startTime === null && this._mixer._isActiveAction( this );
43457
43458         }
43459
43460         // return true when play has been called
43461         isScheduled() {
43462
43463                 return this._mixer._isActiveAction( this );
43464
43465         }
43466
43467         startAt( time ) {
43468
43469                 this._startTime = time;
43470
43471                 return this;
43472
43473         }
43474
43475         setLoop( mode, repetitions ) {
43476
43477                 this.loop = mode;
43478                 this.repetitions = repetitions;
43479
43480                 return this;
43481
43482         }
43483
43484         // Weight
43485
43486         // set the weight stopping any scheduled fading
43487         // although .enabled = false yields an effective weight of zero, this
43488         // method does *not* change .enabled, because it would be confusing
43489         setEffectiveWeight( weight ) {
43490
43491                 this.weight = weight;
43492
43493                 // note: same logic as when updated at runtime
43494                 this._effectiveWeight = this.enabled ? weight : 0;
43495
43496                 return this.stopFading();
43497
43498         }
43499
43500         // return the weight considering fading and .enabled
43501         getEffectiveWeight() {
43502
43503                 return this._effectiveWeight;
43504
43505         }
43506
43507         fadeIn( duration ) {
43508
43509                 return this._scheduleFading( duration, 0, 1 );
43510
43511         }
43512
43513         fadeOut( duration ) {
43514
43515                 return this._scheduleFading( duration, 1, 0 );
43516
43517         }
43518
43519         crossFadeFrom( fadeOutAction, duration, warp ) {
43520
43521                 fadeOutAction.fadeOut( duration );
43522                 this.fadeIn( duration );
43523
43524                 if ( warp ) {
43525
43526                         const fadeInDuration = this._clip.duration,
43527                                 fadeOutDuration = fadeOutAction._clip.duration,
43528
43529                                 startEndRatio = fadeOutDuration / fadeInDuration,
43530                                 endStartRatio = fadeInDuration / fadeOutDuration;
43531
43532                         fadeOutAction.warp( 1.0, startEndRatio, duration );
43533                         this.warp( endStartRatio, 1.0, duration );
43534
43535                 }
43536
43537                 return this;
43538
43539         }
43540
43541         crossFadeTo( fadeInAction, duration, warp ) {
43542
43543                 return fadeInAction.crossFadeFrom( this, duration, warp );
43544
43545         }
43546
43547         stopFading() {
43548
43549                 const weightInterpolant = this._weightInterpolant;
43550
43551                 if ( weightInterpolant !== null ) {
43552
43553                         this._weightInterpolant = null;
43554                         this._mixer._takeBackControlInterpolant( weightInterpolant );
43555
43556                 }
43557
43558                 return this;
43559
43560         }
43561
43562         // Time Scale Control
43563
43564         // set the time scale stopping any scheduled warping
43565         // although .paused = true yields an effective time scale of zero, this
43566         // method does *not* change .paused, because it would be confusing
43567         setEffectiveTimeScale( timeScale ) {
43568
43569                 this.timeScale = timeScale;
43570                 this._effectiveTimeScale = this.paused ? 0 : timeScale;
43571
43572                 return this.stopWarping();
43573
43574         }
43575
43576         // return the time scale considering warping and .paused
43577         getEffectiveTimeScale() {
43578
43579                 return this._effectiveTimeScale;
43580
43581         }
43582
43583         setDuration( duration ) {
43584
43585                 this.timeScale = this._clip.duration / duration;
43586
43587                 return this.stopWarping();
43588
43589         }
43590
43591         syncWith( action ) {
43592
43593                 this.time = action.time;
43594                 this.timeScale = action.timeScale;
43595
43596                 return this.stopWarping();
43597
43598         }
43599
43600         halt( duration ) {
43601
43602                 return this.warp( this._effectiveTimeScale, 0, duration );
43603
43604         }
43605
43606         warp( startTimeScale, endTimeScale, duration ) {
43607
43608                 const mixer = this._mixer,
43609                         now = mixer.time,
43610                         timeScale = this.timeScale;
43611
43612                 let interpolant = this._timeScaleInterpolant;
43613
43614                 if ( interpolant === null ) {
43615
43616                         interpolant = mixer._lendControlInterpolant();
43617                         this._timeScaleInterpolant = interpolant;
43618
43619                 }
43620
43621                 const times = interpolant.parameterPositions,
43622                         values = interpolant.sampleValues;
43623
43624                 times[ 0 ] = now;
43625                 times[ 1 ] = now + duration;
43626
43627                 values[ 0 ] = startTimeScale / timeScale;
43628                 values[ 1 ] = endTimeScale / timeScale;
43629
43630                 return this;
43631
43632         }
43633
43634         stopWarping() {
43635
43636                 const timeScaleInterpolant = this._timeScaleInterpolant;
43637
43638                 if ( timeScaleInterpolant !== null ) {
43639
43640                         this._timeScaleInterpolant = null;
43641                         this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
43642
43643                 }
43644
43645                 return this;
43646
43647         }
43648
43649         // Object Accessors
43650
43651         getMixer() {
43652
43653                 return this._mixer;
43654
43655         }
43656
43657         getClip() {
43658
43659                 return this._clip;
43660
43661         }
43662
43663         getRoot() {
43664
43665                 return this._localRoot || this._mixer._root;
43666
43667         }
43668
43669         // Interna
43670
43671         _update( time, deltaTime, timeDirection, accuIndex ) {
43672
43673                 // called by the mixer
43674
43675                 if ( ! this.enabled ) {
43676
43677                         // call ._updateWeight() to update ._effectiveWeight
43678
43679                         this._updateWeight( time );
43680                         return;
43681
43682                 }
43683
43684                 const startTime = this._startTime;
43685
43686                 if ( startTime !== null ) {
43687
43688                         // check for scheduled start of action
43689
43690                         const timeRunning = ( time - startTime ) * timeDirection;
43691                         if ( timeRunning < 0 || timeDirection === 0 ) {
43692
43693                                 return; // yet to come / don't decide when delta = 0
43694
43695                         }
43696
43697                         // start
43698
43699                         this._startTime = null; // unschedule
43700                         deltaTime = timeDirection * timeRunning;
43701
43702                 }
43703
43704                 // apply time scale and advance time
43705
43706                 deltaTime *= this._updateTimeScale( time );
43707                 const clipTime = this._updateTime( deltaTime );
43708
43709                 // note: _updateTime may disable the action resulting in
43710                 // an effective weight of 0
43711
43712                 const weight = this._updateWeight( time );
43713
43714                 if ( weight > 0 ) {
43715
43716                         const interpolants = this._interpolants;
43717                         const propertyMixers = this._propertyBindings;
43718
43719                         switch ( this.blendMode ) {
43720
43721                                 case AdditiveAnimationBlendMode:
43722
43723                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
43724
43725                                                 interpolants[ j ].evaluate( clipTime );
43726                                                 propertyMixers[ j ].accumulateAdditive( weight );
43727
43728                                         }
43729
43730                                         break;
43731
43732                                 case NormalAnimationBlendMode:
43733                                 default:
43734
43735                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
43736
43737                                                 interpolants[ j ].evaluate( clipTime );
43738                                                 propertyMixers[ j ].accumulate( accuIndex, weight );
43739
43740                                         }
43741
43742                         }
43743
43744                 }
43745
43746         }
43747
43748         _updateWeight( time ) {
43749
43750                 let weight = 0;
43751
43752                 if ( this.enabled ) {
43753
43754                         weight = this.weight;
43755                         const interpolant = this._weightInterpolant;
43756
43757                         if ( interpolant !== null ) {
43758
43759                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
43760
43761                                 weight *= interpolantValue;
43762
43763                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
43764
43765                                         this.stopFading();
43766
43767                                         if ( interpolantValue === 0 ) {
43768
43769                                                 // faded out, disable
43770                                                 this.enabled = false;
43771
43772                                         }
43773
43774                                 }
43775
43776                         }
43777
43778                 }
43779
43780                 this._effectiveWeight = weight;
43781                 return weight;
43782
43783         }
43784
43785         _updateTimeScale( time ) {
43786
43787                 let timeScale = 0;
43788
43789                 if ( ! this.paused ) {
43790
43791                         timeScale = this.timeScale;
43792
43793                         const interpolant = this._timeScaleInterpolant;
43794
43795                         if ( interpolant !== null ) {
43796
43797                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
43798
43799                                 timeScale *= interpolantValue;
43800
43801                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
43802
43803                                         this.stopWarping();
43804
43805                                         if ( timeScale === 0 ) {
43806
43807                                                 // motion has halted, pause
43808                                                 this.paused = true;
43809
43810                                         } else {
43811
43812                                                 // warp done - apply final time scale
43813                                                 this.timeScale = timeScale;
43814
43815                                         }
43816
43817                                 }
43818
43819                         }
43820
43821                 }
43822
43823                 this._effectiveTimeScale = timeScale;
43824                 return timeScale;
43825
43826         }
43827
43828         _updateTime( deltaTime ) {
43829
43830                 const duration = this._clip.duration;
43831                 const loop = this.loop;
43832
43833                 let time = this.time + deltaTime;
43834                 let loopCount = this._loopCount;
43835
43836                 const pingPong = ( loop === LoopPingPong );
43837
43838                 if ( deltaTime === 0 ) {
43839
43840                         if ( loopCount === - 1 ) return time;
43841
43842                         return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
43843
43844                 }
43845
43846                 if ( loop === LoopOnce ) {
43847
43848                         if ( loopCount === - 1 ) {
43849
43850                                 // just started
43851
43852                                 this._loopCount = 0;
43853                                 this._setEndings( true, true, false );
43854
43855                         }
43856
43857                         handle_stop: {
43858
43859                                 if ( time >= duration ) {
43860
43861                                         time = duration;
43862
43863                                 } else if ( time < 0 ) {
43864
43865                                         time = 0;
43866
43867                                 } else {
43868
43869                                         this.time = time;
43870
43871                                         break handle_stop;
43872
43873                                 }
43874
43875                                 if ( this.clampWhenFinished ) this.paused = true;
43876                                 else this.enabled = false;
43877
43878                                 this.time = time;
43879
43880                                 this._mixer.dispatchEvent( {
43881                                         type: 'finished', action: this,
43882                                         direction: deltaTime < 0 ? - 1 : 1
43883                                 } );
43884
43885                         }
43886
43887                 } else { // repetitive Repeat or PingPong
43888
43889                         if ( loopCount === - 1 ) {
43890
43891                                 // just started
43892
43893                                 if ( deltaTime >= 0 ) {
43894
43895                                         loopCount = 0;
43896
43897                                         this._setEndings( true, this.repetitions === 0, pingPong );
43898
43899                                 } else {
43900
43901                                         // when looping in reverse direction, the initial
43902                                         // transition through zero counts as a repetition,
43903                                         // so leave loopCount at -1
43904
43905                                         this._setEndings( this.repetitions === 0, true, pingPong );
43906
43907                                 }
43908
43909                         }
43910
43911                         if ( time >= duration || time < 0 ) {
43912
43913                                 // wrap around
43914
43915                                 const loopDelta = Math.floor( time / duration ); // signed
43916                                 time -= duration * loopDelta;
43917
43918                                 loopCount += Math.abs( loopDelta );
43919
43920                                 const pending = this.repetitions - loopCount;
43921
43922                                 if ( pending <= 0 ) {
43923
43924                                         // have to stop (switch state, clamp time, fire event)
43925
43926                                         if ( this.clampWhenFinished ) this.paused = true;
43927                                         else this.enabled = false;
43928
43929                                         time = deltaTime > 0 ? duration : 0;
43930
43931                                         this.time = time;
43932
43933                                         this._mixer.dispatchEvent( {
43934                                                 type: 'finished', action: this,
43935                                                 direction: deltaTime > 0 ? 1 : - 1
43936                                         } );
43937
43938                                 } else {
43939
43940                                         // keep running
43941
43942                                         if ( pending === 1 ) {
43943
43944                                                 // entering the last round
43945
43946                                                 const atStart = deltaTime < 0;
43947                                                 this._setEndings( atStart, ! atStart, pingPong );
43948
43949                                         } else {
43950
43951                                                 this._setEndings( false, false, pingPong );
43952
43953                                         }
43954
43955                                         this._loopCount = loopCount;
43956
43957                                         this.time = time;
43958
43959                                         this._mixer.dispatchEvent( {
43960                                                 type: 'loop', action: this, loopDelta: loopDelta
43961                                         } );
43962
43963                                 }
43964
43965                         } else {
43966
43967                                 this.time = time;
43968
43969                         }
43970
43971                         if ( pingPong && ( loopCount & 1 ) === 1 ) {
43972
43973                                 // invert time for the "pong round"
43974
43975                                 return duration - time;
43976
43977                         }
43978
43979                 }
43980
43981                 return time;
43982
43983         }
43984
43985         _setEndings( atStart, atEnd, pingPong ) {
43986
43987                 const settings = this._interpolantSettings;
43988
43989                 if ( pingPong ) {
43990
43991                         settings.endingStart = ZeroSlopeEnding;
43992                         settings.endingEnd = ZeroSlopeEnding;
43993
43994                 } else {
43995
43996                         // assuming for LoopOnce atStart == atEnd == true
43997
43998                         if ( atStart ) {
43999
44000                                 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
44001
44002                         } else {
44003
44004                                 settings.endingStart = WrapAroundEnding;
44005
44006                         }
44007
44008                         if ( atEnd ) {
44009
44010                                 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
44011
44012                         } else {
44013
44014                                 settings.endingEnd       = WrapAroundEnding;
44015
44016                         }
44017
44018                 }
44019
44020         }
44021
44022         _scheduleFading( duration, weightNow, weightThen ) {
44023
44024                 const mixer = this._mixer, now = mixer.time;
44025                 let interpolant = this._weightInterpolant;
44026
44027                 if ( interpolant === null ) {
44028
44029                         interpolant = mixer._lendControlInterpolant();
44030                         this._weightInterpolant = interpolant;
44031
44032                 }
44033
44034                 const times = interpolant.parameterPositions,
44035                         values = interpolant.sampleValues;
44036
44037                 times[ 0 ] = now;
44038                 values[ 0 ] = weightNow;
44039                 times[ 1 ] = now + duration;
44040                 values[ 1 ] = weightThen;
44041
44042                 return this;
44043
44044         }
44045
44046     }
44047
44048     function AnimationMixer( root ) {
44049
44050         this._root = root;
44051         this._initMemoryManager();
44052         this._accuIndex = 0;
44053
44054         this.time = 0;
44055
44056         this.timeScale = 1.0;
44057
44058     }
44059
44060     AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
44061
44062         constructor: AnimationMixer,
44063
44064         _bindAction: function ( action, prototypeAction ) {
44065
44066                 const root = action._localRoot || this._root,
44067                         tracks = action._clip.tracks,
44068                         nTracks = tracks.length,
44069                         bindings = action._propertyBindings,
44070                         interpolants = action._interpolants,
44071                         rootUuid = root.uuid,
44072                         bindingsByRoot = this._bindingsByRootAndName;
44073
44074                 let bindingsByName = bindingsByRoot[ rootUuid ];
44075
44076                 if ( bindingsByName === undefined ) {
44077
44078                         bindingsByName = {};
44079                         bindingsByRoot[ rootUuid ] = bindingsByName;
44080
44081                 }
44082
44083                 for ( let i = 0; i !== nTracks; ++ i ) {
44084
44085                         const track = tracks[ i ],
44086                                 trackName = track.name;
44087
44088                         let binding = bindingsByName[ trackName ];
44089
44090                         if ( binding !== undefined ) {
44091
44092                                 bindings[ i ] = binding;
44093
44094                         } else {
44095
44096                                 binding = bindings[ i ];
44097
44098                                 if ( binding !== undefined ) {
44099
44100                                         // existing binding, make sure the cache knows
44101
44102                                         if ( binding._cacheIndex === null ) {
44103
44104                                                 ++ binding.referenceCount;
44105                                                 this._addInactiveBinding( binding, rootUuid, trackName );
44106
44107                                         }
44108
44109                                         continue;
44110
44111                                 }
44112
44113                                 const path = prototypeAction && prototypeAction.
44114                                         _propertyBindings[ i ].binding.parsedPath;
44115
44116                                 binding = new PropertyMixer(
44117                                         PropertyBinding.create( root, trackName, path ),
44118                                         track.ValueTypeName, track.getValueSize() );
44119
44120                                 ++ binding.referenceCount;
44121                                 this._addInactiveBinding( binding, rootUuid, trackName );
44122
44123                                 bindings[ i ] = binding;
44124
44125                         }
44126
44127                         interpolants[ i ].resultBuffer = binding.buffer;
44128
44129                 }
44130
44131         },
44132
44133         _activateAction: function ( action ) {
44134
44135                 if ( ! this._isActiveAction( action ) ) {
44136
44137                         if ( action._cacheIndex === null ) {
44138
44139                                 // this action has been forgotten by the cache, but the user
44140                                 // appears to be still using it -> rebind
44141
44142                                 const rootUuid = ( action._localRoot || this._root ).uuid,
44143                                         clipUuid = action._clip.uuid,
44144                                         actionsForClip = this._actionsByClip[ clipUuid ];
44145
44146                                 this._bindAction( action,
44147                                         actionsForClip && actionsForClip.knownActions[ 0 ] );
44148
44149                                 this._addInactiveAction( action, clipUuid, rootUuid );
44150
44151                         }
44152
44153                         const bindings = action._propertyBindings;
44154
44155                         // increment reference counts / sort out state
44156                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
44157
44158                                 const binding = bindings[ i ];
44159
44160                                 if ( binding.useCount ++ === 0 ) {
44161
44162                                         this._lendBinding( binding );
44163                                         binding.saveOriginalState();
44164
44165                                 }
44166
44167                         }
44168
44169                         this._lendAction( action );
44170
44171                 }
44172
44173         },
44174
44175         _deactivateAction: function ( action ) {
44176
44177                 if ( this._isActiveAction( action ) ) {
44178
44179                         const bindings = action._propertyBindings;
44180
44181                         // decrement reference counts / sort out state
44182                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
44183
44184                                 const binding = bindings[ i ];
44185
44186                                 if ( -- binding.useCount === 0 ) {
44187
44188                                         binding.restoreOriginalState();
44189                                         this._takeBackBinding( binding );
44190
44191                                 }
44192
44193                         }
44194
44195                         this._takeBackAction( action );
44196
44197                 }
44198
44199         },
44200
44201         // Memory manager
44202
44203         _initMemoryManager: function () {
44204
44205                 this._actions = []; // 'nActiveActions' followed by inactive ones
44206                 this._nActiveActions = 0;
44207
44208                 this._actionsByClip = {};
44209                 // inside:
44210                 // {
44211                 //      knownActions: Array< AnimationAction > - used as prototypes
44212                 //      actionByRoot: AnimationAction - lookup
44213                 // }
44214
44215
44216                 this._bindings = []; // 'nActiveBindings' followed by inactive ones
44217                 this._nActiveBindings = 0;
44218
44219                 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
44220
44221
44222                 this._controlInterpolants = []; // same game as above
44223                 this._nActiveControlInterpolants = 0;
44224
44225                 const scope = this;
44226
44227                 this.stats = {
44228
44229                         actions: {
44230                                 get total() {
44231
44232                                         return scope._actions.length;
44233
44234                                 },
44235                                 get inUse() {
44236
44237                                         return scope._nActiveActions;
44238
44239                                 }
44240                         },
44241                         bindings: {
44242                                 get total() {
44243
44244                                         return scope._bindings.length;
44245
44246                                 },
44247                                 get inUse() {
44248
44249                                         return scope._nActiveBindings;
44250
44251                                 }
44252                         },
44253                         controlInterpolants: {
44254                                 get total() {
44255
44256                                         return scope._controlInterpolants.length;
44257
44258                                 },
44259                                 get inUse() {
44260
44261                                         return scope._nActiveControlInterpolants;
44262
44263                                 }
44264                         }
44265
44266                 };
44267
44268         },
44269
44270         // Memory management for AnimationAction objects
44271
44272         _isActiveAction: function ( action ) {
44273
44274                 const index = action._cacheIndex;
44275                 return index !== null && index < this._nActiveActions;
44276
44277         },
44278
44279         _addInactiveAction: function ( action, clipUuid, rootUuid ) {
44280
44281                 const actions = this._actions,
44282                         actionsByClip = this._actionsByClip;
44283
44284                 let actionsForClip = actionsByClip[ clipUuid ];
44285
44286                 if ( actionsForClip === undefined ) {
44287
44288                         actionsForClip = {
44289
44290                                 knownActions: [ action ],
44291                                 actionByRoot: {}
44292
44293                         };
44294
44295                         action._byClipCacheIndex = 0;
44296
44297                         actionsByClip[ clipUuid ] = actionsForClip;
44298
44299                 } else {
44300
44301                         const knownActions = actionsForClip.knownActions;
44302
44303                         action._byClipCacheIndex = knownActions.length;
44304                         knownActions.push( action );
44305
44306                 }
44307
44308                 action._cacheIndex = actions.length;
44309                 actions.push( action );
44310
44311                 actionsForClip.actionByRoot[ rootUuid ] = action;
44312
44313         },
44314
44315         _removeInactiveAction: function ( action ) {
44316
44317                 const actions = this._actions,
44318                         lastInactiveAction = actions[ actions.length - 1 ],
44319                         cacheIndex = action._cacheIndex;
44320
44321                 lastInactiveAction._cacheIndex = cacheIndex;
44322                 actions[ cacheIndex ] = lastInactiveAction;
44323                 actions.pop();
44324
44325                 action._cacheIndex = null;
44326
44327
44328                 const clipUuid = action._clip.uuid,
44329                         actionsByClip = this._actionsByClip,
44330                         actionsForClip = actionsByClip[ clipUuid ],
44331                         knownActionsForClip = actionsForClip.knownActions,
44332
44333                         lastKnownAction =
44334                                 knownActionsForClip[ knownActionsForClip.length - 1 ],
44335
44336                         byClipCacheIndex = action._byClipCacheIndex;
44337
44338                 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
44339                 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
44340                 knownActionsForClip.pop();
44341
44342                 action._byClipCacheIndex = null;
44343
44344
44345                 const actionByRoot = actionsForClip.actionByRoot,
44346                         rootUuid = ( action._localRoot || this._root ).uuid;
44347
44348                 delete actionByRoot[ rootUuid ];
44349
44350                 if ( knownActionsForClip.length === 0 ) {
44351
44352                         delete actionsByClip[ clipUuid ];
44353
44354                 }
44355
44356                 this._removeInactiveBindingsForAction( action );
44357
44358         },
44359
44360         _removeInactiveBindingsForAction: function ( action ) {
44361
44362                 const bindings = action._propertyBindings;
44363
44364                 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
44365
44366                         const binding = bindings[ i ];
44367
44368                         if ( -- binding.referenceCount === 0 ) {
44369
44370                                 this._removeInactiveBinding( binding );
44371
44372                         }
44373
44374                 }
44375
44376         },
44377
44378         _lendAction: function ( action ) {
44379
44380                 // [ active actions |  inactive actions  ]
44381                 // [  active actions >| inactive actions ]
44382                 //                 s        a
44383                 //                  <-swap->
44384                 //                 a        s
44385
44386                 const actions = this._actions,
44387                         prevIndex = action._cacheIndex,
44388
44389                         lastActiveIndex = this._nActiveActions ++,
44390
44391                         firstInactiveAction = actions[ lastActiveIndex ];
44392
44393                 action._cacheIndex = lastActiveIndex;
44394                 actions[ lastActiveIndex ] = action;
44395
44396                 firstInactiveAction._cacheIndex = prevIndex;
44397                 actions[ prevIndex ] = firstInactiveAction;
44398
44399         },
44400
44401         _takeBackAction: function ( action ) {
44402
44403                 // [  active actions  | inactive actions ]
44404                 // [ active actions |< inactive actions  ]
44405                 //        a        s
44406                 //         <-swap->
44407                 //        s        a
44408
44409                 const actions = this._actions,
44410                         prevIndex = action._cacheIndex,
44411
44412                         firstInactiveIndex = -- this._nActiveActions,
44413
44414                         lastActiveAction = actions[ firstInactiveIndex ];
44415
44416                 action._cacheIndex = firstInactiveIndex;
44417                 actions[ firstInactiveIndex ] = action;
44418
44419                 lastActiveAction._cacheIndex = prevIndex;
44420                 actions[ prevIndex ] = lastActiveAction;
44421
44422         },
44423
44424         // Memory management for PropertyMixer objects
44425
44426         _addInactiveBinding: function ( binding, rootUuid, trackName ) {
44427
44428                 const bindingsByRoot = this._bindingsByRootAndName,
44429                         bindings = this._bindings;
44430
44431                 let bindingByName = bindingsByRoot[ rootUuid ];
44432
44433                 if ( bindingByName === undefined ) {
44434
44435                         bindingByName = {};
44436                         bindingsByRoot[ rootUuid ] = bindingByName;
44437
44438                 }
44439
44440                 bindingByName[ trackName ] = binding;
44441
44442                 binding._cacheIndex = bindings.length;
44443                 bindings.push( binding );
44444
44445         },
44446
44447         _removeInactiveBinding: function ( binding ) {
44448
44449                 const bindings = this._bindings,
44450                         propBinding = binding.binding,
44451                         rootUuid = propBinding.rootNode.uuid,
44452                         trackName = propBinding.path,
44453                         bindingsByRoot = this._bindingsByRootAndName,
44454                         bindingByName = bindingsByRoot[ rootUuid ],
44455
44456                         lastInactiveBinding = bindings[ bindings.length - 1 ],
44457                         cacheIndex = binding._cacheIndex;
44458
44459                 lastInactiveBinding._cacheIndex = cacheIndex;
44460                 bindings[ cacheIndex ] = lastInactiveBinding;
44461                 bindings.pop();
44462
44463                 delete bindingByName[ trackName ];
44464
44465                 if ( Object.keys( bindingByName ).length === 0 ) {
44466
44467                         delete bindingsByRoot[ rootUuid ];
44468
44469                 }
44470
44471         },
44472
44473         _lendBinding: function ( binding ) {
44474
44475                 const bindings = this._bindings,
44476                         prevIndex = binding._cacheIndex,
44477
44478                         lastActiveIndex = this._nActiveBindings ++,
44479
44480                         firstInactiveBinding = bindings[ lastActiveIndex ];
44481
44482                 binding._cacheIndex = lastActiveIndex;
44483                 bindings[ lastActiveIndex ] = binding;
44484
44485                 firstInactiveBinding._cacheIndex = prevIndex;
44486                 bindings[ prevIndex ] = firstInactiveBinding;
44487
44488         },
44489
44490         _takeBackBinding: function ( binding ) {
44491
44492                 const bindings = this._bindings,
44493                         prevIndex = binding._cacheIndex,
44494
44495                         firstInactiveIndex = -- this._nActiveBindings,
44496
44497                         lastActiveBinding = bindings[ firstInactiveIndex ];
44498
44499                 binding._cacheIndex = firstInactiveIndex;
44500                 bindings[ firstInactiveIndex ] = binding;
44501
44502                 lastActiveBinding._cacheIndex = prevIndex;
44503                 bindings[ prevIndex ] = lastActiveBinding;
44504
44505         },
44506
44507
44508         // Memory management of Interpolants for weight and time scale
44509
44510         _lendControlInterpolant: function () {
44511
44512                 const interpolants = this._controlInterpolants,
44513                         lastActiveIndex = this._nActiveControlInterpolants ++;
44514
44515                 let interpolant = interpolants[ lastActiveIndex ];
44516
44517                 if ( interpolant === undefined ) {
44518
44519                         interpolant = new LinearInterpolant(
44520                                 new Float32Array( 2 ), new Float32Array( 2 ),
44521                                 1, this._controlInterpolantsResultBuffer );
44522
44523                         interpolant.__cacheIndex = lastActiveIndex;
44524                         interpolants[ lastActiveIndex ] = interpolant;
44525
44526                 }
44527
44528                 return interpolant;
44529
44530         },
44531
44532         _takeBackControlInterpolant: function ( interpolant ) {
44533
44534                 const interpolants = this._controlInterpolants,
44535                         prevIndex = interpolant.__cacheIndex,
44536
44537                         firstInactiveIndex = -- this._nActiveControlInterpolants,
44538
44539                         lastActiveInterpolant = interpolants[ firstInactiveIndex ];
44540
44541                 interpolant.__cacheIndex = firstInactiveIndex;
44542                 interpolants[ firstInactiveIndex ] = interpolant;
44543
44544                 lastActiveInterpolant.__cacheIndex = prevIndex;
44545                 interpolants[ prevIndex ] = lastActiveInterpolant;
44546
44547         },
44548
44549         _controlInterpolantsResultBuffer: new Float32Array( 1 ),
44550
44551         // return an action for a clip optionally using a custom root target
44552         // object (this method allocates a lot of dynamic memory in case a
44553         // previously unknown clip/root combination is specified)
44554         clipAction: function ( clip, optionalRoot, blendMode ) {
44555
44556                 const root = optionalRoot || this._root,
44557                         rootUuid = root.uuid;
44558
44559                 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
44560
44561                 const clipUuid = clipObject !== null ? clipObject.uuid : clip;
44562
44563                 const actionsForClip = this._actionsByClip[ clipUuid ];
44564                 let prototypeAction = null;
44565
44566                 if ( blendMode === undefined ) {
44567
44568                         if ( clipObject !== null ) {
44569
44570                                 blendMode = clipObject.blendMode;
44571
44572                         } else {
44573
44574                                 blendMode = NormalAnimationBlendMode;
44575
44576                         }
44577
44578                 }
44579
44580                 if ( actionsForClip !== undefined ) {
44581
44582                         const existingAction = actionsForClip.actionByRoot[ rootUuid ];
44583
44584                         if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
44585
44586                                 return existingAction;
44587
44588                         }
44589
44590                         // we know the clip, so we don't have to parse all
44591                         // the bindings again but can just copy
44592                         prototypeAction = actionsForClip.knownActions[ 0 ];
44593
44594                         // also, take the clip from the prototype action
44595                         if ( clipObject === null )
44596                                 clipObject = prototypeAction._clip;
44597
44598                 }
44599
44600                 // clip must be known when specified via string
44601                 if ( clipObject === null ) return null;
44602
44603                 // allocate all resources required to run it
44604                 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
44605
44606                 this._bindAction( newAction, prototypeAction );
44607
44608                 // and make the action known to the memory manager
44609                 this._addInactiveAction( newAction, clipUuid, rootUuid );
44610
44611                 return newAction;
44612
44613         },
44614
44615         // get an existing action
44616         existingAction: function ( clip, optionalRoot ) {
44617
44618                 const root = optionalRoot || this._root,
44619                         rootUuid = root.uuid,
44620
44621                         clipObject = typeof clip === 'string' ?
44622                                 AnimationClip.findByName( root, clip ) : clip,
44623
44624                         clipUuid = clipObject ? clipObject.uuid : clip,
44625
44626                         actionsForClip = this._actionsByClip[ clipUuid ];
44627
44628                 if ( actionsForClip !== undefined ) {
44629
44630                         return actionsForClip.actionByRoot[ rootUuid ] || null;
44631
44632                 }
44633
44634                 return null;
44635
44636         },
44637
44638         // deactivates all previously scheduled actions
44639         stopAllAction: function () {
44640
44641                 const actions = this._actions,
44642                         nActions = this._nActiveActions;
44643
44644                 for ( let i = nActions - 1; i >= 0; -- i ) {
44645
44646                         actions[ i ].stop();
44647
44648                 }
44649
44650                 return this;
44651
44652         },
44653
44654         // advance the time and update apply the animation
44655         update: function ( deltaTime ) {
44656
44657                 deltaTime *= this.timeScale;
44658
44659                 const actions = this._actions,
44660                         nActions = this._nActiveActions,
44661
44662                         time = this.time += deltaTime,
44663                         timeDirection = Math.sign( deltaTime ),
44664
44665                         accuIndex = this._accuIndex ^= 1;
44666
44667                 // run active actions
44668
44669                 for ( let i = 0; i !== nActions; ++ i ) {
44670
44671                         const action = actions[ i ];
44672
44673                         action._update( time, deltaTime, timeDirection, accuIndex );
44674
44675                 }
44676
44677                 // update scene graph
44678
44679                 const bindings = this._bindings,
44680                         nBindings = this._nActiveBindings;
44681
44682                 for ( let i = 0; i !== nBindings; ++ i ) {
44683
44684                         bindings[ i ].apply( accuIndex );
44685
44686                 }
44687
44688                 return this;
44689
44690         },
44691
44692         // Allows you to seek to a specific time in an animation.
44693         setTime: function ( timeInSeconds ) {
44694
44695                 this.time = 0; // Zero out time attribute for AnimationMixer object;
44696                 for ( let i = 0; i < this._actions.length; i ++ ) {
44697
44698                         this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
44699
44700                 }
44701
44702                 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
44703
44704         },
44705
44706         // return this mixer's root target object
44707         getRoot: function () {
44708
44709                 return this._root;
44710
44711         },
44712
44713         // free all resources specific to a particular clip
44714         uncacheClip: function ( clip ) {
44715
44716                 const actions = this._actions,
44717                         clipUuid = clip.uuid,
44718                         actionsByClip = this._actionsByClip,
44719                         actionsForClip = actionsByClip[ clipUuid ];
44720
44721                 if ( actionsForClip !== undefined ) {
44722
44723                         // note: just calling _removeInactiveAction would mess up the
44724                         // iteration state and also require updating the state we can
44725                         // just throw away
44726
44727                         const actionsToRemove = actionsForClip.knownActions;
44728
44729                         for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
44730
44731                                 const action = actionsToRemove[ i ];
44732
44733                                 this._deactivateAction( action );
44734
44735                                 const cacheIndex = action._cacheIndex,
44736                                         lastInactiveAction = actions[ actions.length - 1 ];
44737
44738                                 action._cacheIndex = null;
44739                                 action._byClipCacheIndex = null;
44740
44741                                 lastInactiveAction._cacheIndex = cacheIndex;
44742                                 actions[ cacheIndex ] = lastInactiveAction;
44743                                 actions.pop();
44744
44745                                 this._removeInactiveBindingsForAction( action );
44746
44747                         }
44748
44749                         delete actionsByClip[ clipUuid ];
44750
44751                 }
44752
44753         },
44754
44755         // free all resources specific to a particular root target object
44756         uncacheRoot: function ( root ) {
44757
44758                 const rootUuid = root.uuid,
44759                         actionsByClip = this._actionsByClip;
44760
44761                 for ( const clipUuid in actionsByClip ) {
44762
44763                         const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
44764                                 action = actionByRoot[ rootUuid ];
44765
44766                         if ( action !== undefined ) {
44767
44768                                 this._deactivateAction( action );
44769                                 this._removeInactiveAction( action );
44770
44771                         }
44772
44773                 }
44774
44775                 const bindingsByRoot = this._bindingsByRootAndName,
44776                         bindingByName = bindingsByRoot[ rootUuid ];
44777
44778                 if ( bindingByName !== undefined ) {
44779
44780                         for ( const trackName in bindingByName ) {
44781
44782                                 const binding = bindingByName[ trackName ];
44783                                 binding.restoreOriginalState();
44784                                 this._removeInactiveBinding( binding );
44785
44786                         }
44787
44788                 }
44789
44790         },
44791
44792         // remove a targeted clip from the cache
44793         uncacheAction: function ( clip, optionalRoot ) {
44794
44795                 const action = this.existingAction( clip, optionalRoot );
44796
44797                 if ( action !== null ) {
44798
44799                         this._deactivateAction( action );
44800                         this._removeInactiveAction( action );
44801
44802                 }
44803
44804         }
44805
44806     } );
44807
44808     class Uniform {
44809
44810         constructor( value ) {
44811
44812                 if ( typeof value === 'string' ) {
44813
44814                         console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
44815                         value = arguments[ 1 ];
44816
44817                 }
44818
44819                 this.value = value;
44820
44821         }
44822
44823         clone() {
44824
44825                 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
44826
44827         }
44828
44829     }
44830
44831     function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
44832
44833         InterleavedBuffer.call( this, array, stride );
44834
44835         this.meshPerAttribute = meshPerAttribute || 1;
44836
44837     }
44838
44839     InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
44840
44841         constructor: InstancedInterleavedBuffer,
44842
44843         isInstancedInterleavedBuffer: true,
44844
44845         copy: function ( source ) {
44846
44847                 InterleavedBuffer.prototype.copy.call( this, source );
44848
44849                 this.meshPerAttribute = source.meshPerAttribute;
44850
44851                 return this;
44852
44853         },
44854
44855         clone: function ( data ) {
44856
44857                 const ib = InterleavedBuffer.prototype.clone.call( this, data );
44858
44859                 ib.meshPerAttribute = this.meshPerAttribute;
44860
44861                 return ib;
44862
44863         },
44864
44865         toJSON: function ( data ) {
44866
44867                 const json = InterleavedBuffer.prototype.toJSON.call( this, data );
44868
44869                 json.isInstancedInterleavedBuffer = true;
44870                 json.meshPerAttribute = this.meshPerAttribute;
44871
44872                 return json;
44873
44874         }
44875
44876     } );
44877
44878     function GLBufferAttribute( buffer, type, itemSize, elementSize, count ) {
44879
44880         this.buffer = buffer;
44881         this.type = type;
44882         this.itemSize = itemSize;
44883         this.elementSize = elementSize;
44884         this.count = count;
44885
44886         this.version = 0;
44887
44888     }
44889
44890     Object.defineProperty( GLBufferAttribute.prototype, 'needsUpdate', {
44891
44892         set: function ( value ) {
44893
44894                 if ( value === true ) this.version ++;
44895
44896         }
44897
44898     } );
44899
44900     Object.assign( GLBufferAttribute.prototype, {
44901
44902         isGLBufferAttribute: true,
44903
44904         setBuffer: function ( buffer ) {
44905
44906                 this.buffer = buffer;
44907
44908                 return this;
44909
44910         },
44911
44912         setType: function ( type, elementSize ) {
44913
44914                 this.type = type;
44915                 this.elementSize = elementSize;
44916
44917                 return this;
44918
44919         },
44920
44921         setItemSize: function ( itemSize ) {
44922
44923                 this.itemSize = itemSize;
44924
44925                 return this;
44926
44927         },
44928
44929         setCount: function ( count ) {
44930
44931                 this.count = count;
44932
44933                 return this;
44934
44935         },
44936
44937     } );
44938
44939     function Raycaster( origin, direction, near, far ) {
44940
44941         this.ray = new Ray( origin, direction );
44942         // direction is assumed to be normalized (for accurate distance calculations)
44943
44944         this.near = near || 0;
44945         this.far = far || Infinity;
44946         this.camera = null;
44947         this.layers = new Layers();
44948
44949         this.params = {
44950                 Mesh: {},
44951                 Line: { threshold: 1 },
44952                 LOD: {},
44953                 Points: { threshold: 1 },
44954                 Sprite: {}
44955         };
44956
44957         Object.defineProperties( this.params, {
44958                 PointCloud: {
44959                         get: function () {
44960
44961                                 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
44962                                 return this.Points;
44963
44964                         }
44965                 }
44966         } );
44967
44968     }
44969
44970     function ascSort( a, b ) {
44971
44972         return a.distance - b.distance;
44973
44974     }
44975
44976     function intersectObject( object, raycaster, intersects, recursive ) {
44977
44978         if ( object.layers.test( raycaster.layers ) ) {
44979
44980                 object.raycast( raycaster, intersects );
44981
44982         }
44983
44984         if ( recursive === true ) {
44985
44986                 const children = object.children;
44987
44988                 for ( let i = 0, l = children.length; i < l; i ++ ) {
44989
44990                         intersectObject( children[ i ], raycaster, intersects, true );
44991
44992                 }
44993
44994         }
44995
44996     }
44997
44998     Object.assign( Raycaster.prototype, {
44999
45000         set: function ( origin, direction ) {
45001
45002                 // direction is assumed to be normalized (for accurate distance calculations)
45003
45004                 this.ray.set( origin, direction );
45005
45006         },
45007
45008         setFromCamera: function ( coords, camera ) {
45009
45010                 if ( camera && camera.isPerspectiveCamera ) {
45011
45012                         this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
45013                         this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
45014                         this.camera = camera;
45015
45016                 } else if ( camera && camera.isOrthographicCamera ) {
45017
45018                         this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
45019                         this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
45020                         this.camera = camera;
45021
45022                 } else {
45023
45024                         console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
45025
45026                 }
45027
45028         },
45029
45030         intersectObject: function ( object, recursive, optionalTarget ) {
45031
45032                 const intersects = optionalTarget || [];
45033
45034                 intersectObject( object, this, intersects, recursive );
45035
45036                 intersects.sort( ascSort );
45037
45038                 return intersects;
45039
45040         },
45041
45042         intersectObjects: function ( objects, recursive, optionalTarget ) {
45043
45044                 const intersects = optionalTarget || [];
45045
45046                 if ( Array.isArray( objects ) === false ) {
45047
45048                         console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
45049                         return intersects;
45050
45051                 }
45052
45053                 for ( let i = 0, l = objects.length; i < l; i ++ ) {
45054
45055                         intersectObject( objects[ i ], this, intersects, recursive );
45056
45057                 }
45058
45059                 intersects.sort( ascSort );
45060
45061                 return intersects;
45062
45063         }
45064
45065     } );
45066
45067     const _vector$8 = /*@__PURE__*/ new Vector2();
45068
45069     class Box2 {
45070
45071         constructor( min, max ) {
45072
45073                 Object.defineProperty( this, 'isBox2', { value: true } );
45074
45075                 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
45076                 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
45077
45078         }
45079
45080         set( min, max ) {
45081
45082                 this.min.copy( min );
45083                 this.max.copy( max );
45084
45085                 return this;
45086
45087         }
45088
45089         setFromPoints( points ) {
45090
45091                 this.makeEmpty();
45092
45093                 for ( let i = 0, il = points.length; i < il; i ++ ) {
45094
45095                         this.expandByPoint( points[ i ] );
45096
45097                 }
45098
45099                 return this;
45100
45101         }
45102
45103         setFromCenterAndSize( center, size ) {
45104
45105                 const halfSize = _vector$8.copy( size ).multiplyScalar( 0.5 );
45106                 this.min.copy( center ).sub( halfSize );
45107                 this.max.copy( center ).add( halfSize );
45108
45109                 return this;
45110
45111         }
45112
45113         clone() {
45114
45115                 return new this.constructor().copy( this );
45116
45117         }
45118
45119         copy( box ) {
45120
45121                 this.min.copy( box.min );
45122                 this.max.copy( box.max );
45123
45124                 return this;
45125
45126         }
45127
45128         makeEmpty() {
45129
45130                 this.min.x = this.min.y = + Infinity;
45131                 this.max.x = this.max.y = - Infinity;
45132
45133                 return this;
45134
45135         }
45136
45137         isEmpty() {
45138
45139                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
45140
45141                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
45142
45143         }
45144
45145         getCenter( target ) {
45146
45147                 if ( target === undefined ) {
45148
45149                         console.warn( 'THREE.Box2: .getCenter() target is now required' );
45150                         target = new Vector2();
45151
45152                 }
45153
45154                 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
45155
45156         }
45157
45158         getSize( target ) {
45159
45160                 if ( target === undefined ) {
45161
45162                         console.warn( 'THREE.Box2: .getSize() target is now required' );
45163                         target = new Vector2();
45164
45165                 }
45166
45167                 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
45168
45169         }
45170
45171         expandByPoint( point ) {
45172
45173                 this.min.min( point );
45174                 this.max.max( point );
45175
45176                 return this;
45177
45178         }
45179
45180         expandByVector( vector ) {
45181
45182                 this.min.sub( vector );
45183                 this.max.add( vector );
45184
45185                 return this;
45186
45187         }
45188
45189         expandByScalar( scalar ) {
45190
45191                 this.min.addScalar( - scalar );
45192                 this.max.addScalar( scalar );
45193
45194                 return this;
45195
45196         }
45197
45198         containsPoint( point ) {
45199
45200                 return point.x < this.min.x || point.x > this.max.x ||
45201                         point.y < this.min.y || point.y > this.max.y ? false : true;
45202
45203         }
45204
45205         containsBox( box ) {
45206
45207                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
45208                         this.min.y <= box.min.y && box.max.y <= this.max.y;
45209
45210         }
45211
45212         getParameter( point, target ) {
45213
45214                 // This can potentially have a divide by zero if the box
45215                 // has a size dimension of 0.
45216
45217                 if ( target === undefined ) {
45218
45219                         console.warn( 'THREE.Box2: .getParameter() target is now required' );
45220                         target = new Vector2();
45221
45222                 }
45223
45224                 return target.set(
45225                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
45226                         ( point.y - this.min.y ) / ( this.max.y - this.min.y )
45227                 );
45228
45229         }
45230
45231         intersectsBox( box ) {
45232
45233                 // using 4 splitting planes to rule out intersections
45234
45235                 return box.max.x < this.min.x || box.min.x > this.max.x ||
45236                         box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
45237
45238         }
45239
45240         clampPoint( point, target ) {
45241
45242                 if ( target === undefined ) {
45243
45244                         console.warn( 'THREE.Box2: .clampPoint() target is now required' );
45245                         target = new Vector2();
45246
45247                 }
45248
45249                 return target.copy( point ).clamp( this.min, this.max );
45250
45251         }
45252
45253         distanceToPoint( point ) {
45254
45255                 const clampedPoint = _vector$8.copy( point ).clamp( this.min, this.max );
45256                 return clampedPoint.sub( point ).length();
45257
45258         }
45259
45260         intersect( box ) {
45261
45262                 this.min.max( box.min );
45263                 this.max.min( box.max );
45264
45265                 return this;
45266
45267         }
45268
45269         union( box ) {
45270
45271                 this.min.min( box.min );
45272                 this.max.max( box.max );
45273
45274                 return this;
45275
45276         }
45277
45278         translate( offset ) {
45279
45280                 this.min.add( offset );
45281                 this.max.add( offset );
45282
45283                 return this;
45284
45285         }
45286
45287         equals( box ) {
45288
45289                 return box.min.equals( this.min ) && box.max.equals( this.max );
45290
45291         }
45292
45293     }
45294
45295     function ImmediateRenderObject( material ) {
45296
45297         Object3D.call( this );
45298
45299         this.material = material;
45300         this.render = function ( /* renderCallback */ ) {};
45301
45302         this.hasPositions = false;
45303         this.hasNormals = false;
45304         this.hasColors = false;
45305         this.hasUvs = false;
45306
45307         this.positionArray = null;
45308         this.normalArray = null;
45309         this.colorArray = null;
45310         this.uvArray = null;
45311
45312         this.count = 0;
45313
45314     }
45315
45316     ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
45317     ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
45318
45319     ImmediateRenderObject.prototype.isImmediateRenderObject = true;
45320
45321     const backgroundMaterial = new MeshBasicMaterial( {
45322         side: BackSide,
45323         depthWrite: false,
45324         depthTest: false,
45325     } );
45326     new Mesh( new BoxGeometry(), backgroundMaterial );
45327
45328     //
45329
45330     Curve.create = function ( construct, getPoint ) {
45331
45332         console.log( 'THREE.Curve.create() has been deprecated' );
45333
45334         construct.prototype = Object.create( Curve.prototype );
45335         construct.prototype.constructor = construct;
45336         construct.prototype.getPoint = getPoint;
45337
45338         return construct;
45339
45340     };
45341
45342     //
45343
45344     Object.assign( Path.prototype, {
45345
45346         fromPoints: function ( points ) {
45347
45348                 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
45349                 return this.setFromPoints( points );
45350
45351         }
45352
45353     } );
45354
45355     //
45356
45357     function Spline( points ) {
45358
45359         console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
45360
45361         CatmullRomCurve3.call( this, points );
45362         this.type = 'catmullrom';
45363
45364     }
45365
45366     Spline.prototype = Object.create( CatmullRomCurve3.prototype );
45367
45368     Object.assign( Spline.prototype, {
45369
45370         initFromArray: function ( /* a */ ) {
45371
45372                 console.error( 'THREE.Spline: .initFromArray() has been removed.' );
45373
45374         },
45375         getControlPointsArray: function ( /* optionalTarget */ ) {
45376
45377                 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
45378
45379         },
45380         reparametrizeByArcLength: function ( /* samplingCoef */ ) {
45381
45382                 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
45383
45384         }
45385
45386     } );
45387
45388     //
45389
45390     Object.assign( Loader.prototype, {
45391
45392         extractUrlBase: function ( url ) {
45393
45394                 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
45395                 return LoaderUtils.extractUrlBase( url );
45396
45397         }
45398
45399     } );
45400
45401     Loader.Handlers = {
45402
45403         add: function ( /* regex, loader */ ) {
45404
45405                 console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
45406
45407         },
45408
45409         get: function ( /* file */ ) {
45410
45411                 console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
45412
45413         }
45414
45415     };
45416
45417     //
45418
45419     Object.assign( Box2.prototype, {
45420
45421         center: function ( optionalTarget ) {
45422
45423                 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
45424                 return this.getCenter( optionalTarget );
45425
45426         },
45427         empty: function () {
45428
45429                 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
45430                 return this.isEmpty();
45431
45432         },
45433         isIntersectionBox: function ( box ) {
45434
45435                 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
45436                 return this.intersectsBox( box );
45437
45438         },
45439         size: function ( optionalTarget ) {
45440
45441                 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
45442                 return this.getSize( optionalTarget );
45443
45444         }
45445     } );
45446
45447     Object.assign( Box3.prototype, {
45448
45449         center: function ( optionalTarget ) {
45450
45451                 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
45452                 return this.getCenter( optionalTarget );
45453
45454         },
45455         empty: function () {
45456
45457                 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
45458                 return this.isEmpty();
45459
45460         },
45461         isIntersectionBox: function ( box ) {
45462
45463                 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
45464                 return this.intersectsBox( box );
45465
45466         },
45467         isIntersectionSphere: function ( sphere ) {
45468
45469                 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
45470                 return this.intersectsSphere( sphere );
45471
45472         },
45473         size: function ( optionalTarget ) {
45474
45475                 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
45476                 return this.getSize( optionalTarget );
45477
45478         }
45479     } );
45480
45481     Object.assign( Sphere.prototype, {
45482
45483         empty: function () {
45484
45485                 console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
45486                 return this.isEmpty();
45487
45488         },
45489
45490     } );
45491
45492     Frustum.prototype.setFromMatrix = function ( m ) {
45493
45494         console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
45495         return this.setFromProjectionMatrix( m );
45496
45497     };
45498
45499     Object.assign( MathUtils, {
45500
45501         random16: function () {
45502
45503                 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
45504                 return Math.random();
45505
45506         },
45507
45508         nearestPowerOfTwo: function ( value ) {
45509
45510                 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
45511                 return MathUtils.floorPowerOfTwo( value );
45512
45513         },
45514
45515         nextPowerOfTwo: function ( value ) {
45516
45517                 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
45518                 return MathUtils.ceilPowerOfTwo( value );
45519
45520         }
45521
45522     } );
45523
45524     Object.assign( Matrix3.prototype, {
45525
45526         flattenToArrayOffset: function ( array, offset ) {
45527
45528                 console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
45529                 return this.toArray( array, offset );
45530
45531         },
45532         multiplyVector3: function ( vector ) {
45533
45534                 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
45535                 return vector.applyMatrix3( this );
45536
45537         },
45538         multiplyVector3Array: function ( /* a */ ) {
45539
45540                 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
45541
45542         },
45543         applyToBufferAttribute: function ( attribute ) {
45544
45545                 console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
45546                 return attribute.applyMatrix3( this );
45547
45548         },
45549         applyToVector3Array: function ( /* array, offset, length */ ) {
45550
45551                 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
45552
45553         },
45554         getInverse: function ( matrix ) {
45555
45556                 console.warn( 'THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
45557                 return this.copy( matrix ).invert();
45558
45559         }
45560
45561     } );
45562
45563     Object.assign( Matrix4.prototype, {
45564
45565         extractPosition: function ( m ) {
45566
45567                 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
45568                 return this.copyPosition( m );
45569
45570         },
45571         flattenToArrayOffset: function ( array, offset ) {
45572
45573                 console.warn( 'THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
45574                 return this.toArray( array, offset );
45575
45576         },
45577         getPosition: function () {
45578
45579                 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
45580                 return new Vector3().setFromMatrixColumn( this, 3 );
45581
45582         },
45583         setRotationFromQuaternion: function ( q ) {
45584
45585                 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
45586                 return this.makeRotationFromQuaternion( q );
45587
45588         },
45589         multiplyToArray: function () {
45590
45591                 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
45592
45593         },
45594         multiplyVector3: function ( vector ) {
45595
45596                 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
45597                 return vector.applyMatrix4( this );
45598
45599         },
45600         multiplyVector4: function ( vector ) {
45601
45602                 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
45603                 return vector.applyMatrix4( this );
45604
45605         },
45606         multiplyVector3Array: function ( /* a */ ) {
45607
45608                 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
45609
45610         },
45611         rotateAxis: function ( v ) {
45612
45613                 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
45614                 v.transformDirection( this );
45615
45616         },
45617         crossVector: function ( vector ) {
45618
45619                 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
45620                 return vector.applyMatrix4( this );
45621
45622         },
45623         translate: function () {
45624
45625                 console.error( 'THREE.Matrix4: .translate() has been removed.' );
45626
45627         },
45628         rotateX: function () {
45629
45630                 console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
45631
45632         },
45633         rotateY: function () {
45634
45635                 console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
45636
45637         },
45638         rotateZ: function () {
45639
45640                 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
45641
45642         },
45643         rotateByAxis: function () {
45644
45645                 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
45646
45647         },
45648         applyToBufferAttribute: function ( attribute ) {
45649
45650                 console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
45651                 return attribute.applyMatrix4( this );
45652
45653         },
45654         applyToVector3Array: function ( /* array, offset, length */ ) {
45655
45656                 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
45657
45658         },
45659         makeFrustum: function ( left, right, bottom, top, near, far ) {
45660
45661                 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
45662                 return this.makePerspective( left, right, top, bottom, near, far );
45663
45664         },
45665         getInverse: function ( matrix ) {
45666
45667                 console.warn( 'THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
45668                 return this.copy( matrix ).invert();
45669
45670         }
45671
45672     } );
45673
45674     Plane.prototype.isIntersectionLine = function ( line ) {
45675
45676         console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
45677         return this.intersectsLine( line );
45678
45679     };
45680
45681     Object.assign( Quaternion.prototype, {
45682
45683         multiplyVector3: function ( vector ) {
45684
45685                 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
45686                 return vector.applyQuaternion( this );
45687
45688         },
45689         inverse: function ( ) {
45690
45691                 console.warn( 'THREE.Quaternion: .inverse() has been renamed to invert().' );
45692                 return this.invert();
45693
45694         }
45695
45696     } );
45697
45698     Object.assign( Ray.prototype, {
45699
45700         isIntersectionBox: function ( box ) {
45701
45702                 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
45703                 return this.intersectsBox( box );
45704
45705         },
45706         isIntersectionPlane: function ( plane ) {
45707
45708                 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
45709                 return this.intersectsPlane( plane );
45710
45711         },
45712         isIntersectionSphere: function ( sphere ) {
45713
45714                 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
45715                 return this.intersectsSphere( sphere );
45716
45717         }
45718
45719     } );
45720
45721     Object.assign( Triangle.prototype, {
45722
45723         area: function () {
45724
45725                 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
45726                 return this.getArea();
45727
45728         },
45729         barycoordFromPoint: function ( point, target ) {
45730
45731                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
45732                 return this.getBarycoord( point, target );
45733
45734         },
45735         midpoint: function ( target ) {
45736
45737                 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
45738                 return this.getMidpoint( target );
45739
45740         },
45741         normal: function ( target ) {
45742
45743                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
45744                 return this.getNormal( target );
45745
45746         },
45747         plane: function ( target ) {
45748
45749                 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
45750                 return this.getPlane( target );
45751
45752         }
45753
45754     } );
45755
45756     Object.assign( Triangle, {
45757
45758         barycoordFromPoint: function ( point, a, b, c, target ) {
45759
45760                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
45761                 return Triangle.getBarycoord( point, a, b, c, target );
45762
45763         },
45764         normal: function ( a, b, c, target ) {
45765
45766                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
45767                 return Triangle.getNormal( a, b, c, target );
45768
45769         }
45770
45771     } );
45772
45773     Object.assign( Shape.prototype, {
45774
45775         extractAllPoints: function ( divisions ) {
45776
45777                 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
45778                 return this.extractPoints( divisions );
45779
45780         },
45781         extrude: function ( options ) {
45782
45783                 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
45784                 return new ExtrudeGeometry( this, options );
45785
45786         },
45787         makeGeometry: function ( options ) {
45788
45789                 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
45790                 return new ShapeGeometry( this, options );
45791
45792         }
45793
45794     } );
45795
45796     Object.assign( Vector2.prototype, {
45797
45798         fromAttribute: function ( attribute, index, offset ) {
45799
45800                 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
45801                 return this.fromBufferAttribute( attribute, index, offset );
45802
45803         },
45804         distanceToManhattan: function ( v ) {
45805
45806                 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
45807                 return this.manhattanDistanceTo( v );
45808
45809         },
45810         lengthManhattan: function () {
45811
45812                 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
45813                 return this.manhattanLength();
45814
45815         }
45816
45817     } );
45818
45819     Object.assign( Vector3.prototype, {
45820
45821         setEulerFromRotationMatrix: function () {
45822
45823                 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
45824
45825         },
45826         setEulerFromQuaternion: function () {
45827
45828                 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
45829
45830         },
45831         getPositionFromMatrix: function ( m ) {
45832
45833                 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
45834                 return this.setFromMatrixPosition( m );
45835
45836         },
45837         getScaleFromMatrix: function ( m ) {
45838
45839                 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
45840                 return this.setFromMatrixScale( m );
45841
45842         },
45843         getColumnFromMatrix: function ( index, matrix ) {
45844
45845                 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
45846                 return this.setFromMatrixColumn( matrix, index );
45847
45848         },
45849         applyProjection: function ( m ) {
45850
45851                 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
45852                 return this.applyMatrix4( m );
45853
45854         },
45855         fromAttribute: function ( attribute, index, offset ) {
45856
45857                 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
45858                 return this.fromBufferAttribute( attribute, index, offset );
45859
45860         },
45861         distanceToManhattan: function ( v ) {
45862
45863                 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
45864                 return this.manhattanDistanceTo( v );
45865
45866         },
45867         lengthManhattan: function () {
45868
45869                 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
45870                 return this.manhattanLength();
45871
45872         }
45873
45874     } );
45875
45876     Object.assign( Vector4.prototype, {
45877
45878         fromAttribute: function ( attribute, index, offset ) {
45879
45880                 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
45881                 return this.fromBufferAttribute( attribute, index, offset );
45882
45883         },
45884         lengthManhattan: function () {
45885
45886                 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
45887                 return this.manhattanLength();
45888
45889         }
45890
45891     } );
45892
45893     //
45894
45895     Object.assign( Object3D.prototype, {
45896
45897         getChildByName: function ( name ) {
45898
45899                 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
45900                 return this.getObjectByName( name );
45901
45902         },
45903         renderDepth: function () {
45904
45905                 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
45906
45907         },
45908         translate: function ( distance, axis ) {
45909
45910                 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
45911                 return this.translateOnAxis( axis, distance );
45912
45913         },
45914         getWorldRotation: function () {
45915
45916                 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
45917
45918         },
45919         applyMatrix: function ( matrix ) {
45920
45921                 console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
45922                 return this.applyMatrix4( matrix );
45923
45924         }
45925
45926     } );
45927
45928     Object.defineProperties( Object3D.prototype, {
45929
45930         eulerOrder: {
45931                 get: function () {
45932
45933                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
45934                         return this.rotation.order;
45935
45936                 },
45937                 set: function ( value ) {
45938
45939                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
45940                         this.rotation.order = value;
45941
45942                 }
45943         },
45944         useQuaternion: {
45945                 get: function () {
45946
45947                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
45948
45949                 },
45950                 set: function () {
45951
45952                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
45953
45954                 }
45955         }
45956
45957     } );
45958
45959     Object.assign( Mesh.prototype, {
45960
45961         setDrawMode: function () {
45962
45963                 console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
45964
45965         },
45966
45967     } );
45968
45969     Object.defineProperties( Mesh.prototype, {
45970
45971         drawMode: {
45972                 get: function () {
45973
45974                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
45975                         return TrianglesDrawMode;
45976
45977                 },
45978                 set: function () {
45979
45980                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
45981
45982                 }
45983         }
45984
45985     } );
45986
45987     Object.defineProperties( LOD.prototype, {
45988
45989         objects: {
45990                 get: function () {
45991
45992                         console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
45993                         return this.levels;
45994
45995                 }
45996         }
45997
45998     } );
45999
46000     Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
46001
46002         get: function () {
46003
46004                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
46005
46006         },
46007         set: function () {
46008
46009                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
46010
46011         }
46012
46013     } );
46014
46015     SkinnedMesh.prototype.initBones = function () {
46016
46017         console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
46018
46019     };
46020
46021     Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
46022
46023         get: function () {
46024
46025                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
46026                 return this.arcLengthDivisions;
46027
46028         },
46029         set: function ( value ) {
46030
46031                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
46032                 this.arcLengthDivisions = value;
46033
46034         }
46035
46036     } );
46037
46038     //
46039
46040     PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
46041
46042         console.warn( 'THREE.PerspectiveCamera.setLens is deprecated. ' +
46043                         'Use .setFocalLength and .filmGauge for a photographic setup.' );
46044
46045         if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
46046         this.setFocalLength( focalLength );
46047
46048     };
46049
46050     //
46051
46052     Object.defineProperties( Light.prototype, {
46053         onlyShadow: {
46054                 set: function () {
46055
46056                         console.warn( 'THREE.Light: .onlyShadow has been removed.' );
46057
46058                 }
46059         },
46060         shadowCameraFov: {
46061                 set: function ( value ) {
46062
46063                         console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
46064                         this.shadow.camera.fov = value;
46065
46066                 }
46067         },
46068         shadowCameraLeft: {
46069                 set: function ( value ) {
46070
46071                         console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
46072                         this.shadow.camera.left = value;
46073
46074                 }
46075         },
46076         shadowCameraRight: {
46077                 set: function ( value ) {
46078
46079                         console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
46080                         this.shadow.camera.right = value;
46081
46082                 }
46083         },
46084         shadowCameraTop: {
46085                 set: function ( value ) {
46086
46087                         console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
46088                         this.shadow.camera.top = value;
46089
46090                 }
46091         },
46092         shadowCameraBottom: {
46093                 set: function ( value ) {
46094
46095                         console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
46096                         this.shadow.camera.bottom = value;
46097
46098                 }
46099         },
46100         shadowCameraNear: {
46101                 set: function ( value ) {
46102
46103                         console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
46104                         this.shadow.camera.near = value;
46105
46106                 }
46107         },
46108         shadowCameraFar: {
46109                 set: function ( value ) {
46110
46111                         console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
46112                         this.shadow.camera.far = value;
46113
46114                 }
46115         },
46116         shadowCameraVisible: {
46117                 set: function () {
46118
46119                         console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
46120
46121                 }
46122         },
46123         shadowBias: {
46124                 set: function ( value ) {
46125
46126                         console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
46127                         this.shadow.bias = value;
46128
46129                 }
46130         },
46131         shadowDarkness: {
46132                 set: function () {
46133
46134                         console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
46135
46136                 }
46137         },
46138         shadowMapWidth: {
46139                 set: function ( value ) {
46140
46141                         console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
46142                         this.shadow.mapSize.width = value;
46143
46144                 }
46145         },
46146         shadowMapHeight: {
46147                 set: function ( value ) {
46148
46149                         console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
46150                         this.shadow.mapSize.height = value;
46151
46152                 }
46153         }
46154     } );
46155
46156     //
46157
46158     Object.defineProperties( BufferAttribute.prototype, {
46159
46160         length: {
46161                 get: function () {
46162
46163                         console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
46164                         return this.array.length;
46165
46166                 }
46167         },
46168         dynamic: {
46169                 get: function () {
46170
46171                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
46172                         return this.usage === DynamicDrawUsage;
46173
46174                 },
46175                 set: function ( /* value */ ) {
46176
46177                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
46178                         this.setUsage( DynamicDrawUsage );
46179
46180                 }
46181         }
46182
46183     } );
46184
46185     Object.assign( BufferAttribute.prototype, {
46186         setDynamic: function ( value ) {
46187
46188                 console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
46189                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
46190                 return this;
46191
46192         },
46193         copyIndicesArray: function ( /* indices */ ) {
46194
46195                 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
46196
46197         },
46198         setArray: function ( /* array */ ) {
46199
46200                 console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
46201
46202         }
46203     } );
46204
46205     Object.assign( BufferGeometry.prototype, {
46206
46207         addIndex: function ( index ) {
46208
46209                 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
46210                 this.setIndex( index );
46211
46212         },
46213         addAttribute: function ( name, attribute ) {
46214
46215                 console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
46216
46217                 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
46218
46219                         console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
46220
46221                         return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
46222
46223                 }
46224
46225                 if ( name === 'index' ) {
46226
46227                         console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
46228                         this.setIndex( attribute );
46229
46230                         return this;
46231
46232                 }
46233
46234                 return this.setAttribute( name, attribute );
46235
46236         },
46237         addDrawCall: function ( start, count, indexOffset ) {
46238
46239                 if ( indexOffset !== undefined ) {
46240
46241                         console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
46242
46243                 }
46244
46245                 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
46246                 this.addGroup( start, count );
46247
46248         },
46249         clearDrawCalls: function () {
46250
46251                 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
46252                 this.clearGroups();
46253
46254         },
46255         computeOffsets: function () {
46256
46257                 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
46258
46259         },
46260         removeAttribute: function ( name ) {
46261
46262                 console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
46263
46264                 return this.deleteAttribute( name );
46265
46266         },
46267         applyMatrix: function ( matrix ) {
46268
46269                 console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
46270                 return this.applyMatrix4( matrix );
46271
46272         }
46273
46274     } );
46275
46276     Object.defineProperties( BufferGeometry.prototype, {
46277
46278         drawcalls: {
46279                 get: function () {
46280
46281                         console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
46282                         return this.groups;
46283
46284                 }
46285         },
46286         offsets: {
46287                 get: function () {
46288
46289                         console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
46290                         return this.groups;
46291
46292                 }
46293         }
46294
46295     } );
46296
46297     Object.defineProperties( InstancedBufferGeometry.prototype, {
46298
46299         maxInstancedCount: {
46300                 get: function () {
46301
46302                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
46303                         return this.instanceCount;
46304
46305                 },
46306                 set: function ( value ) {
46307
46308                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
46309                         this.instanceCount = value;
46310
46311                 }
46312         }
46313
46314     } );
46315
46316     Object.defineProperties( Raycaster.prototype, {
46317
46318         linePrecision: {
46319                 get: function () {
46320
46321                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
46322                         return this.params.Line.threshold;
46323
46324                 },
46325                 set: function ( value ) {
46326
46327                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
46328                         this.params.Line.threshold = value;
46329
46330                 }
46331         }
46332
46333     } );
46334
46335     Object.defineProperties( InterleavedBuffer.prototype, {
46336
46337         dynamic: {
46338                 get: function () {
46339
46340                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
46341                         return this.usage === DynamicDrawUsage;
46342
46343                 },
46344                 set: function ( value ) {
46345
46346                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
46347                         this.setUsage( value );
46348
46349                 }
46350         }
46351
46352     } );
46353
46354     Object.assign( InterleavedBuffer.prototype, {
46355         setDynamic: function ( value ) {
46356
46357                 console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
46358                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
46359                 return this;
46360
46361         },
46362         setArray: function ( /* array */ ) {
46363
46364                 console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
46365
46366         }
46367     } );
46368
46369     //
46370
46371     Object.assign( ExtrudeGeometry.prototype, {
46372
46373         getArrays: function () {
46374
46375                 console.error( 'THREE.ExtrudeGeometry: .getArrays() has been removed.' );
46376
46377         },
46378
46379         addShapeList: function () {
46380
46381                 console.error( 'THREE.ExtrudeGeometry: .addShapeList() has been removed.' );
46382
46383         },
46384
46385         addShape: function () {
46386
46387                 console.error( 'THREE.ExtrudeGeometry: .addShape() has been removed.' );
46388
46389         }
46390
46391     } );
46392
46393     //
46394
46395     Object.assign( Scene.prototype, {
46396
46397         dispose: function () {
46398
46399                 console.error( 'THREE.Scene: .dispose() has been removed.' );
46400
46401         }
46402
46403     } );
46404
46405     //
46406
46407     Object.defineProperties( Uniform.prototype, {
46408
46409         dynamic: {
46410                 set: function () {
46411
46412                         console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
46413
46414                 }
46415         },
46416         onUpdate: {
46417                 value: function () {
46418
46419                         console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
46420                         return this;
46421
46422                 }
46423         }
46424
46425     } );
46426
46427     //
46428
46429     Object.defineProperties( Material.prototype, {
46430
46431         wrapAround: {
46432                 get: function () {
46433
46434                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
46435
46436                 },
46437                 set: function () {
46438
46439                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
46440
46441                 }
46442         },
46443
46444         overdraw: {
46445                 get: function () {
46446
46447                         console.warn( 'THREE.Material: .overdraw has been removed.' );
46448
46449                 },
46450                 set: function () {
46451
46452                         console.warn( 'THREE.Material: .overdraw has been removed.' );
46453
46454                 }
46455         },
46456
46457         wrapRGB: {
46458                 get: function () {
46459
46460                         console.warn( 'THREE.Material: .wrapRGB has been removed.' );
46461                         return new Color();
46462
46463                 }
46464         },
46465
46466         shading: {
46467                 get: function () {
46468
46469                         console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
46470
46471                 },
46472                 set: function ( value ) {
46473
46474                         console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
46475                         this.flatShading = ( value === FlatShading );
46476
46477                 }
46478         },
46479
46480         stencilMask: {
46481                 get: function () {
46482
46483                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
46484                         return this.stencilFuncMask;
46485
46486                 },
46487                 set: function ( value ) {
46488
46489                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
46490                         this.stencilFuncMask = value;
46491
46492                 }
46493         }
46494
46495     } );
46496
46497     Object.defineProperties( MeshPhongMaterial.prototype, {
46498
46499         metal: {
46500                 get: function () {
46501
46502                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
46503                         return false;
46504
46505                 },
46506                 set: function () {
46507
46508                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
46509
46510                 }
46511         }
46512
46513     } );
46514
46515     Object.defineProperties( MeshPhysicalMaterial.prototype, {
46516
46517         transparency: {
46518                 get: function () {
46519
46520                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
46521                         return this.transmission;
46522
46523                 },
46524                 set: function ( value ) {
46525
46526                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
46527                         this.transmission = value;
46528
46529                 }
46530         }
46531
46532     } );
46533
46534     Object.defineProperties( ShaderMaterial.prototype, {
46535
46536         derivatives: {
46537                 get: function () {
46538
46539                         console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
46540                         return this.extensions.derivatives;
46541
46542                 },
46543                 set: function ( value ) {
46544
46545                         console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
46546                         this.extensions.derivatives = value;
46547
46548                 }
46549         }
46550
46551     } );
46552
46553     //
46554
46555     Object.assign( WebGLRenderer.prototype, {
46556
46557         clearTarget: function ( renderTarget, color, depth, stencil ) {
46558
46559                 console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
46560                 this.setRenderTarget( renderTarget );
46561                 this.clear( color, depth, stencil );
46562
46563         },
46564         animate: function ( callback ) {
46565
46566                 console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
46567                 this.setAnimationLoop( callback );
46568
46569         },
46570         getCurrentRenderTarget: function () {
46571
46572                 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
46573                 return this.getRenderTarget();
46574
46575         },
46576         getMaxAnisotropy: function () {
46577
46578                 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
46579                 return this.capabilities.getMaxAnisotropy();
46580
46581         },
46582         getPrecision: function () {
46583
46584                 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
46585                 return this.capabilities.precision;
46586
46587         },
46588         resetGLState: function () {
46589
46590                 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
46591                 return this.state.reset();
46592
46593         },
46594         supportsFloatTextures: function () {
46595
46596                 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
46597                 return this.extensions.get( 'OES_texture_float' );
46598
46599         },
46600         supportsHalfFloatTextures: function () {
46601
46602                 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
46603                 return this.extensions.get( 'OES_texture_half_float' );
46604
46605         },
46606         supportsStandardDerivatives: function () {
46607
46608                 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
46609                 return this.extensions.get( 'OES_standard_derivatives' );
46610
46611         },
46612         supportsCompressedTextureS3TC: function () {
46613
46614                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
46615                 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
46616
46617         },
46618         supportsCompressedTexturePVRTC: function () {
46619
46620                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
46621                 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
46622
46623         },
46624         supportsBlendMinMax: function () {
46625
46626                 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
46627                 return this.extensions.get( 'EXT_blend_minmax' );
46628
46629         },
46630         supportsVertexTextures: function () {
46631
46632                 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
46633                 return this.capabilities.vertexTextures;
46634
46635         },
46636         supportsInstancedArrays: function () {
46637
46638                 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
46639                 return this.extensions.get( 'ANGLE_instanced_arrays' );
46640
46641         },
46642         enableScissorTest: function ( boolean ) {
46643
46644                 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
46645                 this.setScissorTest( boolean );
46646
46647         },
46648         initMaterial: function () {
46649
46650                 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
46651
46652         },
46653         addPrePlugin: function () {
46654
46655                 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
46656
46657         },
46658         addPostPlugin: function () {
46659
46660                 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
46661
46662         },
46663         updateShadowMap: function () {
46664
46665                 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
46666
46667         },
46668         setFaceCulling: function () {
46669
46670                 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
46671
46672         },
46673         allocTextureUnit: function () {
46674
46675                 console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
46676
46677         },
46678         setTexture: function () {
46679
46680                 console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
46681
46682         },
46683         setTexture2D: function () {
46684
46685                 console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
46686
46687         },
46688         setTextureCube: function () {
46689
46690                 console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
46691
46692         },
46693         getActiveMipMapLevel: function () {
46694
46695                 console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
46696                 return this.getActiveMipmapLevel();
46697
46698         }
46699
46700     } );
46701
46702     Object.defineProperties( WebGLRenderer.prototype, {
46703
46704         shadowMapEnabled: {
46705                 get: function () {
46706
46707                         return this.shadowMap.enabled;
46708
46709                 },
46710                 set: function ( value ) {
46711
46712                         console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
46713                         this.shadowMap.enabled = value;
46714
46715                 }
46716         },
46717         shadowMapType: {
46718                 get: function () {
46719
46720                         return this.shadowMap.type;
46721
46722                 },
46723                 set: function ( value ) {
46724
46725                         console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
46726                         this.shadowMap.type = value;
46727
46728                 }
46729         },
46730         shadowMapCullFace: {
46731                 get: function () {
46732
46733                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
46734                         return undefined;
46735
46736                 },
46737                 set: function ( /* value */ ) {
46738
46739                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
46740
46741                 }
46742         },
46743         context: {
46744                 get: function () {
46745
46746                         console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
46747                         return this.getContext();
46748
46749                 }
46750         },
46751         vr: {
46752                 get: function () {
46753
46754                         console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
46755                         return this.xr;
46756
46757                 }
46758         },
46759         gammaInput: {
46760                 get: function () {
46761
46762                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
46763                         return false;
46764
46765                 },
46766                 set: function () {
46767
46768                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
46769
46770                 }
46771         },
46772         gammaOutput: {
46773                 get: function () {
46774
46775                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
46776                         return false;
46777
46778                 },
46779                 set: function ( value ) {
46780
46781                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
46782                         this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
46783
46784                 }
46785         },
46786         toneMappingWhitePoint: {
46787                 get: function () {
46788
46789                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
46790                         return 1.0;
46791
46792                 },
46793                 set: function () {
46794
46795                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
46796
46797                 }
46798         },
46799
46800     } );
46801
46802     Object.defineProperties( WebGLShadowMap.prototype, {
46803
46804         cullFace: {
46805                 get: function () {
46806
46807                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
46808                         return undefined;
46809
46810                 },
46811                 set: function ( /* cullFace */ ) {
46812
46813                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
46814
46815                 }
46816         },
46817         renderReverseSided: {
46818                 get: function () {
46819
46820                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
46821                         return undefined;
46822
46823                 },
46824                 set: function () {
46825
46826                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
46827
46828                 }
46829         },
46830         renderSingleSided: {
46831                 get: function () {
46832
46833                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
46834                         return undefined;
46835
46836                 },
46837                 set: function () {
46838
46839                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
46840
46841                 }
46842         }
46843
46844     } );
46845
46846     //
46847
46848     Object.defineProperties( WebGLRenderTarget.prototype, {
46849
46850         wrapS: {
46851                 get: function () {
46852
46853                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
46854                         return this.texture.wrapS;
46855
46856                 },
46857                 set: function ( value ) {
46858
46859                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
46860                         this.texture.wrapS = value;
46861
46862                 }
46863         },
46864         wrapT: {
46865                 get: function () {
46866
46867                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
46868                         return this.texture.wrapT;
46869
46870                 },
46871                 set: function ( value ) {
46872
46873                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
46874                         this.texture.wrapT = value;
46875
46876                 }
46877         },
46878         magFilter: {
46879                 get: function () {
46880
46881                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
46882                         return this.texture.magFilter;
46883
46884                 },
46885                 set: function ( value ) {
46886
46887                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
46888                         this.texture.magFilter = value;
46889
46890                 }
46891         },
46892         minFilter: {
46893                 get: function () {
46894
46895                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
46896                         return this.texture.minFilter;
46897
46898                 },
46899                 set: function ( value ) {
46900
46901                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
46902                         this.texture.minFilter = value;
46903
46904                 }
46905         },
46906         anisotropy: {
46907                 get: function () {
46908
46909                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
46910                         return this.texture.anisotropy;
46911
46912                 },
46913                 set: function ( value ) {
46914
46915                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
46916                         this.texture.anisotropy = value;
46917
46918                 }
46919         },
46920         offset: {
46921                 get: function () {
46922
46923                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
46924                         return this.texture.offset;
46925
46926                 },
46927                 set: function ( value ) {
46928
46929                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
46930                         this.texture.offset = value;
46931
46932                 }
46933         },
46934         repeat: {
46935                 get: function () {
46936
46937                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
46938                         return this.texture.repeat;
46939
46940                 },
46941                 set: function ( value ) {
46942
46943                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
46944                         this.texture.repeat = value;
46945
46946                 }
46947         },
46948         format: {
46949                 get: function () {
46950
46951                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
46952                         return this.texture.format;
46953
46954                 },
46955                 set: function ( value ) {
46956
46957                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
46958                         this.texture.format = value;
46959
46960                 }
46961         },
46962         type: {
46963                 get: function () {
46964
46965                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
46966                         return this.texture.type;
46967
46968                 },
46969                 set: function ( value ) {
46970
46971                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
46972                         this.texture.type = value;
46973
46974                 }
46975         },
46976         generateMipmaps: {
46977                 get: function () {
46978
46979                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
46980                         return this.texture.generateMipmaps;
46981
46982                 },
46983                 set: function ( value ) {
46984
46985                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
46986                         this.texture.generateMipmaps = value;
46987
46988                 }
46989         }
46990
46991     } );
46992
46993     //
46994
46995     Object.defineProperties( Audio.prototype, {
46996
46997         load: {
46998                 value: function ( file ) {
46999
47000                         console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
47001                         const scope = this;
47002                         const audioLoader = new AudioLoader();
47003                         audioLoader.load( file, function ( buffer ) {
47004
47005                                 scope.setBuffer( buffer );
47006
47007                         } );
47008                         return this;
47009
47010                 }
47011         },
47012         startTime: {
47013                 set: function () {
47014
47015                         console.warn( 'THREE.Audio: .startTime is now .play( delay ).' );
47016
47017                 }
47018         }
47019
47020     } );
47021
47022     //
47023
47024     CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
47025
47026         console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
47027         return this.update( renderer, scene );
47028
47029     };
47030
47031     CubeCamera.prototype.clear = function ( renderer, color, depth, stencil ) {
47032
47033         console.warn( 'THREE.CubeCamera: .clear() is now .renderTarget.clear().' );
47034         return this.renderTarget.clear( renderer, color, depth, stencil );
47035
47036     };
47037
47038     ImageUtils.crossOrigin = undefined;
47039
47040     ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
47041
47042         console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
47043
47044         const loader = new TextureLoader();
47045         loader.setCrossOrigin( this.crossOrigin );
47046
47047         const texture = loader.load( url, onLoad, undefined, onError );
47048
47049         if ( mapping ) texture.mapping = mapping;
47050
47051         return texture;
47052
47053     };
47054
47055     ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
47056
47057         console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
47058
47059         const loader = new CubeTextureLoader();
47060         loader.setCrossOrigin( this.crossOrigin );
47061
47062         const texture = loader.load( urls, onLoad, undefined, onError );
47063
47064         if ( mapping ) texture.mapping = mapping;
47065
47066         return texture;
47067
47068     };
47069
47070     ImageUtils.loadCompressedTexture = function () {
47071
47072         console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
47073
47074     };
47075
47076     ImageUtils.loadCompressedTextureCube = function () {
47077
47078         console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
47079
47080     };
47081
47082     if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
47083
47084         /* eslint-disable no-undef */
47085         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
47086                 revision: REVISION,
47087         } } ) );
47088         /* eslint-enable no-undef */
47089
47090     }
47091
47092     if ( typeof window !== 'undefined' ) {
47093
47094         if ( window.__THREE__ ) {
47095
47096                 console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
47097
47098         } else {
47099
47100                 window.__THREE__ = REVISION;
47101
47102         }
47103
47104     }
47105
47106     const DEG2RAD = Math.PI / 180;
47107     const RAD2DEG = 180 / Math.PI;
47108     const WGS84A = 6378137.0;
47109     const WGS84B = 6356752.31424518;
47110     /**
47111      * Convert coordinates from geodetic (WGS84) reference to local topocentric
47112      * (ENU) reference.
47113      *
47114      * @param {number} lng Longitude in degrees.
47115      * @param {number} lat Latitude in degrees.
47116      * @param {number} alt Altitude in meters.
47117      * @param {number} refLng Reference longitude in degrees.
47118      * @param {number} refLat Reference latitude in degrees.
47119      * @param {number} refAlt Reference altitude in meters.
47120      * @returns {Array<number>} The x, y, z local topocentric ENU coordinates.
47121      */
47122     function geodeticToEnu(lng, lat, alt, refLng, refLat, refAlt) {
47123         const ecef = geodeticToEcef(lng, lat, alt);
47124         return ecefToEnu(ecef[0], ecef[1], ecef[2], refLng, refLat, refAlt);
47125     }
47126     /**
47127      * Convert coordinates from local topocentric (ENU) reference to
47128      * geodetic (WGS84) reference.
47129      *
47130      * @param {number} x Topocentric ENU coordinate in East direction.
47131      * @param {number} y Topocentric ENU coordinate in North direction.
47132      * @param {number} z Topocentric ENU coordinate in Up direction.
47133      * @param {number} refLng Reference longitude in degrees.
47134      * @param {number} refLat Reference latitude in degrees.
47135      * @param {number} refAlt Reference altitude in meters.
47136      * @returns {Array<number>} The longitude, latitude in degrees
47137      * and altitude in meters.
47138      */
47139     function enuToGeodetic(x, y, z, refLng, refLat, refAlt) {
47140         const ecef = enuToEcef(x, y, z, refLng, refLat, refAlt);
47141         return ecefToGeodetic(ecef[0], ecef[1], ecef[2]);
47142     }
47143     /**
47144      * Convert coordinates from Earth-Centered, Earth-Fixed (ECEF) reference
47145      * to local topocentric (ENU) reference.
47146      *
47147      * @param {number} X ECEF X-value.
47148      * @param {number} Y ECEF Y-value.
47149      * @param {number} Z ECEF Z-value.
47150      * @param {number} refLng Reference longitude in degrees.
47151      * @param {number} refLat Reference latitude in degrees.
47152      * @param {number} refAlt Reference altitude in meters.
47153      * @returns {Array<number>} The x, y, z topocentric ENU coordinates in East, North
47154      * and Up directions respectively.
47155      */
47156     function ecefToEnu(X, Y, Z, refLng, refLat, refAlt) {
47157         const refEcef = geodeticToEcef(refLng, refLat, refAlt);
47158         const V = [
47159             X - refEcef[0],
47160             Y - refEcef[1],
47161             Z - refEcef[2],
47162         ];
47163         refLng = refLng * DEG2RAD;
47164         refLat = refLat * DEG2RAD;
47165         const cosLng = Math.cos(refLng);
47166         const sinLng = Math.sin(refLng);
47167         const cosLat = Math.cos(refLat);
47168         const sinLat = Math.sin(refLat);
47169         const x = -sinLng * V[0] + cosLng * V[1];
47170         const y = -sinLat * cosLng * V[0] - sinLat * sinLng * V[1] + cosLat * V[2];
47171         const z = cosLat * cosLng * V[0] + cosLat * sinLng * V[1] + sinLat * V[2];
47172         return [x, y, z];
47173     }
47174     /**
47175      * Convert coordinates from local topocentric (ENU) reference
47176      * to Earth-Centered, Earth-Fixed (ECEF) reference.
47177      *
47178      * @param {number} x Topocentric ENU coordinate in East direction.
47179      * @param {number} y Topocentric ENU coordinate in North direction.
47180      * @param {number} z Topocentric ENU coordinate in Up direction.
47181      * @param {number} refLng Reference longitude in degrees.
47182      * @param {number} refLat Reference latitude in degrees.
47183      * @param {number} refAlt Reference altitude in meters.
47184      * @returns {Array<number>} The X, Y, Z ECEF coordinates.
47185      */
47186     function enuToEcef(x, y, z, refLng, refLat, refAlt) {
47187         const refEcef = geodeticToEcef(refLng, refLat, refAlt);
47188         refLng = refLng * DEG2RAD;
47189         refLat = refLat * DEG2RAD;
47190         const cosLng = Math.cos(refLng);
47191         const sinLng = Math.sin(refLng);
47192         const cosLat = Math.cos(refLat);
47193         const sinLat = Math.sin(refLat);
47194         const X = -sinLng * x
47195             - sinLat * cosLng * y
47196             + cosLat * cosLng * z
47197             + refEcef[0];
47198         const Y = cosLng * x
47199             - sinLat * sinLng * y
47200             + cosLat * sinLng * z
47201             + refEcef[1];
47202         const Z = cosLat * y +
47203             sinLat * z +
47204             refEcef[2];
47205         return [X, Y, Z];
47206     }
47207     /**
47208      * Convert coordinates from geodetic reference (WGS84) to Earth-Centered,
47209      * Earth-Fixed (ECEF) reference.
47210      *
47211      * @param {number} lng Longitude in degrees.
47212      * @param {number} lat Latitude in degrees.
47213      * @param {number} alt Altitude in meters.
47214      * @returns {Array<number>} The X, Y, Z ECEF coordinates.
47215      */
47216     function geodeticToEcef(lng, lat, alt) {
47217         const a = WGS84A;
47218         const b = WGS84B;
47219         lng = lng * DEG2RAD;
47220         lat = lat * DEG2RAD;
47221         const cosLng = Math.cos(lng);
47222         const sinLng = Math.sin(lng);
47223         const cosLat = Math.cos(lat);
47224         const sinLat = Math.sin(lat);
47225         const a2 = a * a;
47226         const b2 = b * b;
47227         const L = 1.0 / Math.sqrt(a2 * cosLat * cosLat + b2 * sinLat * sinLat);
47228         const nhcl = (a2 * L + alt) * cosLat;
47229         const X = nhcl * cosLng;
47230         const Y = nhcl * sinLng;
47231         const Z = (b2 * L + alt) * sinLat;
47232         return [X, Y, Z];
47233     }
47234     /**
47235      * Convert coordinates from Earth-Centered, Earth-Fixed (ECEF) reference
47236      * to geodetic reference (WGS84).
47237      *
47238      * @param {number} X ECEF X-value.
47239      * @param {number} Y ECEF Y-value.
47240      * @param {number} Z ECEF Z-value.
47241      * @returns {Array<number>} The longitude, latitude in degrees
47242      * and altitude in meters.
47243      */
47244     function ecefToGeodetic(X, Y, Z) {
47245         const a = WGS84A;
47246         const b = WGS84B;
47247         const a2 = a * a;
47248         const b2 = b * b;
47249         const a2mb2 = a2 - b2;
47250         const ea = Math.sqrt(a2mb2 / a2);
47251         const eb = Math.sqrt(a2mb2 / b2);
47252         const p = Math.sqrt(X * X + Y * Y);
47253         const theta = Math.atan2(Z * a, p * b);
47254         const sinTheta = Math.sin(theta);
47255         const cosTheta = Math.cos(theta);
47256         const lng = Math.atan2(Y, X);
47257         const lat = Math.atan2(Z + eb * eb * b * sinTheta * sinTheta * sinTheta, p - ea * ea * a * cosTheta * cosTheta * cosTheta);
47258         const sinLat = Math.sin(lat);
47259         const cosLat = Math.cos(lat);
47260         const N = a / Math.sqrt(1 - ea * ea * sinLat * sinLat);
47261         const alt = p / cosLat - N;
47262         return [
47263             lng * RAD2DEG,
47264             lat * RAD2DEG,
47265             alt
47266         ];
47267     }
47268
47269     /**
47270      * @class GraphCalculator
47271      *
47272      * @classdesc Represents a calculator for graph entities.
47273      */
47274     class GraphCalculator {
47275         /**
47276          * Get the bounding box corners for a circle with radius of a threshold
47277          * with center in a geodetic position.
47278          *
47279          * @param {LngLat} lngLat - Longitude, latitude to encode.
47280          * @param {number} threshold - Threshold distance from the position in meters.
47281          *
47282          * @returns {Array<LngLat>} The south west and north east corners of the
47283          * bounding box.
47284          */
47285         boundingBoxCorners(lngLat, threshold) {
47286             const sw = enuToGeodetic(-threshold, -threshold, 0, lngLat.lng, lngLat.lat, 0);
47287             const ne = enuToGeodetic(threshold, threshold, 0, lngLat.lng, lngLat.lat, 0);
47288             return [
47289                 { lat: sw[1], lng: sw[0] },
47290                 { lat: ne[1], lng: ne[0] },
47291             ];
47292         }
47293         /**
47294          * Convert a compass angle to an angle axis rotation vector.
47295          *
47296          * @param {number} compassAngle - The compass angle in degrees.
47297          * @param {number} orientation - The orientation of the original image.
47298          *
47299          * @returns {Array<number>} Angle axis rotation vector.
47300          */
47301         rotationFromCompass(compassAngle, orientation) {
47302             let x = 0;
47303             let y = 0;
47304             let z = 0;
47305             switch (orientation) {
47306                 case 1:
47307                     x = Math.PI / 2;
47308                     break;
47309                 case 3:
47310                     x = -Math.PI / 2;
47311                     z = Math.PI;
47312                     break;
47313                 case 6:
47314                     y = -Math.PI / 2;
47315                     z = -Math.PI / 2;
47316                     break;
47317                 case 8:
47318                     y = Math.PI / 2;
47319                     z = Math.PI / 2;
47320                     break;
47321             }
47322             const rz = new Matrix4()
47323                 .makeRotationZ(z);
47324             const euler = new Euler(x, y, compassAngle * Math.PI / 180, "XYZ");
47325             const re = new Matrix4()
47326                 .makeRotationFromEuler(euler);
47327             const rotation = new Vector4()
47328                 .setAxisAngleFromRotationMatrix(re.multiply(rz));
47329             return rotation
47330                 .multiplyScalar(rotation.w)
47331                 .toArray()
47332                 .slice(0, 3);
47333         }
47334     }
47335
47336     /**
47337      * @class Image
47338      *
47339      * @classdesc Represents a image in the navigation graph.
47340      *
47341      * Explanation of position and bearing properties:
47342      *
47343      * When images are uploaded they will have GPS information in the EXIF, this is what
47344      * is called `originalLngLat` {@link Image.originalLngLat}.
47345      *
47346      * When Structure from Motions has been run for a image a `computedLngLat` that
47347      * differs from the `originalLngLat` will be created. It is different because
47348      * GPS positions are not very exact and SfM aligns the camera positions according
47349      * to the 3D reconstruction {@link Image.computedLngLat}.
47350      *
47351      * At last there exist a `lngLat` property which evaluates to
47352      * the `computedLngLat` from SfM if it exists but falls back
47353      * to the `originalLngLat` from the EXIF GPS otherwise {@link Image.lngLat}.
47354      *
47355      * Everything that is done in in the Viewer is based on the SfM positions,
47356      * i.e. `computedLngLat`. That is why the smooth transitions go in the right
47357      * direction (nd not in strange directions because of bad GPS).
47358      *
47359      * E.g. when placing a marker in the Viewer it is relative to the SfM
47360      * position i.e. the `computedLngLat`.
47361      *
47362      * The same concept as above also applies to the compass angle (or bearing) properties
47363      * `originalCa`, `computedCa` and `ca`.
47364      */
47365     class Image$1 {
47366         /**
47367          * Create a new image instance.
47368          *
47369          * @description Images are always created internally by the library.
47370          * Images can not be added to the library through any API method.
47371          *
47372          * @param {CoreImageEnt} core- Raw core image data.
47373          * @ignore
47374          */
47375         constructor(core) {
47376             if (!core) {
47377                 throw new Error(`Incorrect core image data ${core}`);
47378             }
47379             this._cache = null;
47380             this._core = core;
47381             this._spatial = null;
47382         }
47383         /**
47384          * Get assets cached.
47385          *
47386          * @description The assets that need to be cached for this property
47387          * to report true are the following: fill properties, image and mesh.
47388          * The library ensures that the current image will always have the
47389          * assets cached.
47390          *
47391          * @returns {boolean} Value indicating whether all assets have been
47392          * cached.
47393          *
47394          * @ignore
47395          */
47396         get assetsCached() {
47397             return this._core != null &&
47398                 this._spatial != null &&
47399                 this._cache != null &&
47400                 this._cache.image != null &&
47401                 this._cache.mesh != null;
47402         }
47403         /**
47404          * Get cameraParameters.
47405          *
47406          * @description Will be undefined if SfM has
47407          * not been run.
47408          *
47409          * Camera type dependent parameters.
47410          *
47411          * For perspective and fisheye camera types,
47412          * the camera parameters array should be
47413          * constructed according to
47414          *
47415          * `[focal, k1, k2]`
47416          *
47417          * where focal is the camera focal length,
47418          * and k1, k2 are radial distortion parameters.
47419          *
47420          * For spherical camera type the camera
47421          * parameters are unset or emtpy array.
47422          *
47423          * @returns {Array<number>} The parameters
47424          * related to the camera type.
47425          */
47426         get cameraParameters() {
47427             return this._spatial.camera_parameters;
47428         }
47429         /**
47430          * Get cameraType.
47431          *
47432          * @description Will be undefined if SfM has not been run.
47433          *
47434          * @returns {string} The camera type that captured the image.
47435          */
47436         get cameraType() {
47437             return this._spatial.camera_type;
47438         }
47439         /**
47440          * Get capturedAt.
47441          *
47442          * @description Timestamp of the image capture date
47443          * and time represented as a Unix epoch timestamp in milliseconds.
47444          *
47445          * @returns {number} Timestamp when the image was captured.
47446          */
47447         get capturedAt() {
47448             return this._spatial.captured_at;
47449         }
47450         /**
47451          * Get clusterId.
47452          *
47453          * @returns {string} Globally unique id of the SfM cluster to which
47454          * the image belongs.
47455          */
47456         get clusterId() {
47457             return !!this._spatial.cluster ?
47458                 this._spatial.cluster.id :
47459                 null;
47460         }
47461         /**
47462          * Get clusterUrl.
47463          *
47464          * @returns {string} Url to the cluster reconstruction file.
47465          *
47466          * @ignore
47467          */
47468         get clusterUrl() {
47469             return !!this._spatial.cluster ?
47470                 this._spatial.cluster.url :
47471                 null;
47472         }
47473         /**
47474          * Get compassAngle.
47475          *
47476          * @description If the SfM computed compass angle exists it will
47477          * be returned, otherwise the original EXIF compass angle.
47478          *
47479          * @returns {number} Compass angle, measured in degrees
47480          * clockwise with respect to north.
47481          */
47482         get compassAngle() {
47483             return this._spatial.computed_compass_angle != null ?
47484                 this._spatial.computed_compass_angle :
47485                 this._spatial.compass_angle;
47486         }
47487         /**
47488          * Get complete.
47489          *
47490          * @description The library ensures that the current image will
47491          * always be full.
47492          *
47493          * @returns {boolean} Value indicating whether the image has all
47494          * properties filled.
47495          *
47496          * @ignore
47497          */
47498         get complete() {
47499             return this._spatial != null;
47500         }
47501         /**
47502          * Get computedAltitude.
47503          *
47504          * @description If SfM has not been run the computed altitude is
47505          * set to a default value of two meters.
47506          *
47507          * @returns {number} Altitude, in meters.
47508          */
47509         get computedAltitude() {
47510             return this._spatial.computed_altitude;
47511         }
47512         /**
47513          * Get computedCompassAngle.
47514          *
47515          * @description Will not be set if SfM has not been run.
47516          *
47517          * @returns {number} SfM computed compass angle, measured
47518          * in degrees clockwise with respect to north.
47519          */
47520         get computedCompassAngle() {
47521             return this._spatial.computed_compass_angle;
47522         }
47523         /**
47524          * Get computedLngLat.
47525          *
47526          * @description Will not be set if SfM has not been run.
47527          *
47528          * @returns {LngLat} SfM computed longitude, latitude in WGS84 datum,
47529          * measured in degrees.
47530          */
47531         get computedLngLat() {
47532             return this._core.computed_geometry;
47533         }
47534         /**
47535          * Get creatorId.
47536          *
47537          * @description Note that the creator ID will not be set when using
47538          * the Mapillary API.
47539          *
47540          * @returns {string} Globally unique id of the user who uploaded
47541          * the image.
47542          */
47543         get creatorId() {
47544             return this._spatial.creator.id;
47545         }
47546         /**
47547          * Get creatorUsername.
47548          *
47549          * @description Note that the creator username will not be set when
47550          * using the Mapillary API.
47551          *
47552          * @returns {string} Username of the creator who uploaded
47553          * the image.
47554          */
47555         get creatorUsername() {
47556             return this._spatial.creator.username;
47557         }
47558         /**
47559          * Get exifOrientation.
47560          *
47561          * @returns {number} EXIF orientation of original image.
47562          */
47563         get exifOrientation() {
47564             return this._spatial.exif_orientation;
47565         }
47566         /**
47567          * Get height.
47568          *
47569          * @returns {number} Height of original image, not adjusted
47570          * for orientation.
47571          */
47572         get height() {
47573             return this._spatial.height;
47574         }
47575         /**
47576          * Get image.
47577          *
47578          * @description The image will always be set on the current image.
47579          *
47580          * @returns {HTMLImageElement} Cached image element of the image.
47581          */
47582         get image() {
47583             return this._cache.image;
47584         }
47585         /**
47586          * Get image$.
47587          *
47588          * @returns {Observable<HTMLImageElement>} Observable emitting
47589          * the cached image when it is updated.
47590          *
47591          * @ignore
47592          */
47593         get image$() {
47594             return this._cache.image$;
47595         }
47596         /**
47597          * Get id.
47598          *
47599          * @returns {string} Globally unique id of the image.
47600          */
47601         get id() {
47602             return this._core.id;
47603         }
47604         /**
47605          * Get lngLat.
47606          *
47607          * @description If the SfM computed longitude, latitude exist
47608          * it will be returned, otherwise the original EXIF latitude
47609          * longitude.
47610          *
47611          * @returns {LngLat} Longitude, latitude in WGS84 datum,
47612          * measured in degrees.
47613          */
47614         get lngLat() {
47615             return this._core.computed_geometry != null ?
47616                 this._core.computed_geometry :
47617                 this._core.geometry;
47618         }
47619         /**
47620          * Get merged.
47621          *
47622          * @returns {boolean} Value indicating whether SfM has been
47623          * run on the image and the image has been merged into a
47624          * connected component.
47625          */
47626         get merged() {
47627             return this._spatial != null &&
47628                 this._spatial.merge_id != null;
47629         }
47630         /**
47631          * Get mergeId.
47632          *
47633          * @description Will not be set if SfM has not yet been run on
47634          * image.
47635          *
47636          * @returns {stirng} Id of connected component to which image
47637          * belongs after the aligning merge.
47638          */
47639         get mergeId() {
47640             return this._spatial.merge_id;
47641         }
47642         /**
47643          * Get mesh.
47644          *
47645          * @description The mesh will always be set on the current image.
47646          *
47647          * @returns {MeshContract} SfM triangulated mesh of reconstructed
47648          * atomic 3D points.
47649          */
47650         get mesh() {
47651             return this._cache.mesh;
47652         }
47653         /**
47654          * Get originalAltitude.
47655          *
47656          * @returns {number} EXIF altitude, in meters, if available.
47657          */
47658         get originalAltitude() {
47659             return this._spatial.altitude;
47660         }
47661         /**
47662          * Get originalCompassAngle.
47663          *
47664          * @returns {number} Original EXIF compass angle, measured in
47665          * degrees.
47666          */
47667         get originalCompassAngle() {
47668             return this._spatial.compass_angle;
47669         }
47670         /**
47671          * Get originalLngLat.
47672          *
47673          * @returns {LngLat} Original EXIF longitude, latitude in
47674          * WGS84 datum, measured in degrees.
47675          */
47676         get originalLngLat() {
47677             return this._core.geometry;
47678         }
47679         /**
47680          * Get ownerId.
47681          *
47682          * @returns {string} Globally unique id of the owner to which
47683          * the image belongs. If the image does not belong to an
47684          * owner the owner id will be undefined.
47685          */
47686         get ownerId() {
47687             return !!this._spatial.owner ?
47688                 this._spatial.owner.id :
47689                 null;
47690         }
47691         /**
47692          * Get private.
47693          *
47694          * @returns {boolean} Value specifying if image is accessible to
47695          * organization members only or to everyone.
47696          */
47697         get private() {
47698             return this._spatial.private;
47699         }
47700         /**
47701          * Get qualityScore.
47702          *
47703          * @returns {number} A number between zero and one
47704          * determining the quality of the image. Blurriness
47705          * (motion blur / out-of-focus), occlusion (camera
47706          * mount, ego vehicle, water-drops), windshield
47707          * reflections, bad illumination (exposure, glare),
47708          * and bad weather condition (fog, rain, snow)
47709          * affect the quality score.
47710          *
47711          * @description Value should be on the interval [0, 1].
47712          */
47713         get qualityScore() {
47714             return this._spatial.quality_score;
47715         }
47716         /**
47717          * Get rotation.
47718          *
47719          * @description Will not be set if SfM has not been run.
47720          *
47721          * @returns {Array<number>} Rotation vector in angle axis representation.
47722          */
47723         get rotation() {
47724             return this._spatial.computed_rotation;
47725         }
47726         /**
47727          * Get scale.
47728          *
47729          * @description Will not be set if SfM has not been run.
47730          *
47731          * @returns {number} Scale of reconstruction the image
47732          * belongs to.
47733          */
47734         get scale() {
47735             return this._spatial.atomic_scale;
47736         }
47737         /**
47738          * Get sequenceId.
47739          *
47740          * @returns {string} Globally unique id of the sequence
47741          * to which the image belongs.
47742          */
47743         get sequenceId() {
47744             return !!this._core.sequence ?
47745                 this._core.sequence.id :
47746                 null;
47747         }
47748         /**
47749          * Get sequenceEdges.
47750          *
47751          * @returns {NavigationEdgeStatus} Value describing the status of the
47752          * sequence edges.
47753          *
47754          * @ignore
47755          */
47756         get sequenceEdges() {
47757             return this._cache.sequenceEdges;
47758         }
47759         /**
47760          * Get sequenceEdges$.
47761          *
47762          * @description Internal observable, should not be used as an API.
47763          *
47764          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
47765          * values describing the status of the sequence edges.
47766          *
47767          * @ignore
47768          */
47769         get sequenceEdges$() {
47770             return this._cache.sequenceEdges$;
47771         }
47772         /**
47773          * Get spatialEdges.
47774          *
47775          * @returns {NavigationEdgeStatus} Value describing the status of the
47776          * spatial edges.
47777          *
47778          * @ignore
47779          */
47780         get spatialEdges() {
47781             return this._cache.spatialEdges;
47782         }
47783         /**
47784          * Get spatialEdges$.
47785          *
47786          * @description Internal observable, should not be used as an API.
47787          *
47788          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
47789          * values describing the status of the spatial edges.
47790          *
47791          * @ignore
47792          */
47793         get spatialEdges$() {
47794             return this._cache.spatialEdges$;
47795         }
47796         /**
47797          * Get width.
47798          *
47799          * @returns {number} Width of original image, not
47800          * adjusted for orientation.
47801          */
47802         get width() {
47803             return this._spatial.width;
47804         }
47805         /**
47806          * Cache the image and mesh assets.
47807          *
47808          * @description The assets are always cached internally by the
47809          * library prior to setting a image as the current image.
47810          *
47811          * @returns {Observable<Image>} Observable emitting this image whenever the
47812          * load status has changed and when the mesh or image has been fully loaded.
47813          *
47814          * @ignore
47815          */
47816         cacheAssets$() {
47817             return this._cache
47818                 .cacheAssets$(this._spatial, this.merged)
47819                 .pipe(map(() => { return this; }));
47820         }
47821         /**
47822          * Cache the image asset.
47823          *
47824          * @description Use for caching a differently sized image than
47825          * the one currently held by the image.
47826          *
47827          * @returns {Observable<Image>} Observable emitting this image whenever the
47828          * load status has changed and when the mesh or image has been fully loaded.
47829          *
47830          * @ignore
47831          */
47832         cacheImage$() {
47833             return this._cache
47834                 .cacheImage$(this._spatial)
47835                 .pipe(map(() => { return this; }));
47836         }
47837         /**
47838          * Cache the sequence edges.
47839          *
47840          * @description The sequence edges are cached asynchronously
47841          * internally by the library.
47842          *
47843          * @param {Array<NavigationEdge>} edges - Sequence edges to cache.
47844          * @ignore
47845          */
47846         cacheSequenceEdges(edges) {
47847             this._cache.cacheSequenceEdges(edges);
47848         }
47849         /**
47850          * Cache the spatial edges.
47851          *
47852          * @description The spatial edges are cached asynchronously
47853          * internally by the library.
47854          *
47855          * @param {Array<NavigationEdge>} edges - Spatial edges to cache.
47856          * @ignore
47857          */
47858         cacheSpatialEdges(edges) {
47859             this._cache.cacheSpatialEdges(edges);
47860         }
47861         /**
47862          * Dispose the image.
47863          *
47864          * @description Disposes all cached assets.
47865          * @ignore
47866          */
47867         dispose() {
47868             if (this._cache != null) {
47869                 this._cache.dispose();
47870                 this._cache = null;
47871             }
47872             this._core = null;
47873             this._spatial = null;
47874         }
47875         /**
47876          * Initialize the image cache.
47877          *
47878          * @description The image cache is initialized internally by
47879          * the library.
47880          *
47881          * @param {ImageCache} cache - The image cache to set as cache.
47882          * @ignore
47883          */
47884         initializeCache(cache) {
47885             if (this._cache != null) {
47886                 throw new Error(`Image cache already initialized (${this.id}).`);
47887             }
47888             this._cache = cache;
47889         }
47890         /**
47891          * Complete an image with spatial properties.
47892          *
47893          * @description The image is completed internally by
47894          * the library.
47895          *
47896          * @param {SpatialImageEnt} fill - The spatial image struct.
47897          * @ignore
47898          */
47899         makeComplete(fill) {
47900             if (fill == null) {
47901                 throw new Error("Fill can not be null.");
47902             }
47903             this._spatial = fill;
47904         }
47905         /**
47906          * Reset the sequence edges.
47907          *
47908          * @ignore
47909          */
47910         resetSequenceEdges() {
47911             this._cache.resetSequenceEdges();
47912         }
47913         /**
47914          * Reset the spatial edges.
47915          *
47916          * @ignore
47917          */
47918         resetSpatialEdges() {
47919             this._cache.resetSpatialEdges();
47920         }
47921         /**
47922          * Clears the image and mesh assets, aborts
47923          * any outstanding requests and resets edges.
47924          *
47925          * @ignore
47926          */
47927         uncache() {
47928             if (this._cache == null) {
47929                 return;
47930             }
47931             this._cache.dispose();
47932             this._cache = null;
47933         }
47934     }
47935
47936     /**
47937      * @class ImageCache
47938      *
47939      * @classdesc Represents the cached properties of a image.
47940      */
47941     class ImageCache {
47942         /**
47943          * Create a new image cache instance.
47944          */
47945         constructor(provider) {
47946             this._disposed = false;
47947             this._provider = provider;
47948             this._image = null;
47949             this._mesh = null;
47950             this._sequenceEdges = { cached: false, edges: [] };
47951             this._spatialEdges = { cached: false, edges: [] };
47952             this._imageChanged$ = new Subject();
47953             this._image$ = this._imageChanged$.pipe(startWith(null), publishReplay(1), refCount());
47954             this._iamgeSubscription = this._image$.subscribe();
47955             this._sequenceEdgesChanged$ = new Subject();
47956             this._sequenceEdges$ = this._sequenceEdgesChanged$.pipe(startWith(this._sequenceEdges), publishReplay(1), refCount());
47957             this._sequenceEdgesSubscription = this._sequenceEdges$.subscribe(() => { });
47958             this._spatialEdgesChanged$ = new Subject();
47959             this._spatialEdges$ = this._spatialEdgesChanged$.pipe(startWith(this._spatialEdges), publishReplay(1), refCount());
47960             this._spatialEdgesSubscription = this._spatialEdges$.subscribe(() => { });
47961             this._cachingAssets$ = null;
47962         }
47963         /**
47964          * Get image.
47965          *
47966          * @description Will not be set when assets have not been cached
47967          * or when the object has been disposed.
47968          *
47969          * @returns {HTMLImageElement} Cached image element of the image.
47970          */
47971         get image() {
47972             return this._image;
47973         }
47974         /**
47975          * Get image$.
47976          *
47977          * @returns {Observable<HTMLImageElement>} Observable emitting
47978          * the cached image when it is updated.
47979          */
47980         get image$() {
47981             return this._image$;
47982         }
47983         /**
47984          * Get mesh.
47985          *
47986          * @description Will not be set when assets have not been cached
47987          * or when the object has been disposed.
47988          *
47989          * @returns {MeshContract} SfM triangulated mesh of reconstructed
47990          * atomic 3D points.
47991          */
47992         get mesh() {
47993             return this._mesh;
47994         }
47995         /**
47996          * Get sequenceEdges.
47997          *
47998          * @returns {NavigationEdgeStatus} Value describing the status of the
47999          * sequence edges.
48000          */
48001         get sequenceEdges() {
48002             return this._sequenceEdges;
48003         }
48004         /**
48005          * Get sequenceEdges$.
48006          *
48007          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
48008          * values describing the status of the sequence edges.
48009          */
48010         get sequenceEdges$() {
48011             return this._sequenceEdges$;
48012         }
48013         /**
48014          * Get spatialEdges.
48015          *
48016          * @returns {NavigationEdgeStatus} Value describing the status of the
48017          * spatial edges.
48018          */
48019         get spatialEdges() {
48020             return this._spatialEdges;
48021         }
48022         /**
48023          * Get spatialEdges$.
48024          *
48025          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
48026          * values describing the status of the spatial edges.
48027          */
48028         get spatialEdges$() {
48029             return this._spatialEdges$;
48030         }
48031         /**
48032          * Cache the image and mesh assets.
48033          *
48034          * @param {SpatialImageEnt} spatial - Spatial props of the image to cache.
48035          * @param {boolean} spherical - Value indicating whether image is a spherical.
48036          * @param {boolean} merged - Value indicating whether image is merged.
48037          * @returns {Observable<ImageCache>} Observable emitting this image
48038          * cache whenever the load status has changed and when the mesh or image
48039          * has been fully loaded.
48040          */
48041         cacheAssets$(spatial, merged) {
48042             if (this._cachingAssets$ != null) {
48043                 return this._cachingAssets$;
48044             }
48045             this._cachingAssets$ = combineLatest(this._cacheImage$(spatial), this._cacheMesh$(spatial, merged)).pipe(map(([image, mesh]) => {
48046                 this._image = image;
48047                 this._mesh = mesh;
48048                 return this;
48049             }), finalize(() => {
48050                 this._cachingAssets$ = null;
48051             }), publishReplay(1), refCount());
48052             this._cachingAssets$.pipe(first((imageCache) => {
48053                 return !!imageCache._image;
48054             }))
48055                 .subscribe(() => {
48056                 this._imageChanged$.next(this._image);
48057             }, () => { });
48058             return this._cachingAssets$;
48059         }
48060         /**
48061          * Cache an image with a higher resolution than the current one.
48062          *
48063          * @param {SpatialImageEnt} spatial - Spatial props.
48064          * @returns {Observable<ImageCache>} Observable emitting a single item,
48065          * the image cache, when the image has been cached. If supplied image
48066          * size is not larger than the current image size the image cache is
48067          * returned immediately.
48068          */
48069         cacheImage$(spatial) {
48070             if (this._image != null) {
48071                 return of(this);
48072             }
48073             const cacheImage$ = this._cacheImage$(spatial)
48074                 .pipe(first((image) => {
48075                 return !!image;
48076             }), tap((image) => {
48077                 this._disposeImage();
48078                 this._image = image;
48079             }), map(() => {
48080                 return this;
48081             }), publishReplay(1), refCount());
48082             cacheImage$
48083                 .subscribe(() => {
48084                 this._imageChanged$.next(this._image);
48085             }, () => { });
48086             return cacheImage$;
48087         }
48088         /**
48089          * Cache the sequence edges.
48090          *
48091          * @param {Array<NavigationEdge>} edges - Sequence edges to cache.
48092          */
48093         cacheSequenceEdges(edges) {
48094             this._sequenceEdges = { cached: true, edges: edges };
48095             this._sequenceEdgesChanged$.next(this._sequenceEdges);
48096         }
48097         /**
48098          * Cache the spatial edges.
48099          *
48100          * @param {Array<NavigationEdge>} edges - Spatial edges to cache.
48101          */
48102         cacheSpatialEdges(edges) {
48103             this._spatialEdges = { cached: true, edges: edges };
48104             this._spatialEdgesChanged$.next(this._spatialEdges);
48105         }
48106         /**
48107          * Dispose the image cache.
48108          *
48109          * @description Disposes all cached assets and unsubscribes to
48110          * all streams.
48111          */
48112         dispose() {
48113             this._iamgeSubscription.unsubscribe();
48114             this._sequenceEdgesSubscription.unsubscribe();
48115             this._spatialEdgesSubscription.unsubscribe();
48116             this._disposeImage();
48117             this._mesh = null;
48118             this._sequenceEdges = { cached: false, edges: [] };
48119             this._spatialEdges = { cached: false, edges: [] };
48120             this._imageChanged$.next(null);
48121             this._sequenceEdgesChanged$.next(this._sequenceEdges);
48122             this._spatialEdgesChanged$.next(this._spatialEdges);
48123             this._disposed = true;
48124             if (this._imageAborter != null) {
48125                 this._imageAborter();
48126                 this._imageAborter = null;
48127             }
48128             if (this._meshAborter != null) {
48129                 this._meshAborter();
48130                 this._meshAborter = null;
48131             }
48132         }
48133         /**
48134          * Reset the sequence edges.
48135          */
48136         resetSequenceEdges() {
48137             this._sequenceEdges = { cached: false, edges: [] };
48138             this._sequenceEdgesChanged$.next(this._sequenceEdges);
48139         }
48140         /**
48141          * Reset the spatial edges.
48142          */
48143         resetSpatialEdges() {
48144             this._spatialEdges = { cached: false, edges: [] };
48145             this._spatialEdgesChanged$.next(this._spatialEdges);
48146         }
48147         /**
48148          * Cache the image.
48149          *
48150          * @param {SpatialImageEnt} spatial - Spatial image.
48151          * @param {boolean} spherical - Value indicating whether image is a spherical.
48152          * @returns {Observable<ILoadStatusObject<HTMLImageElement>>} Observable
48153          * emitting a load status object every time the load status changes
48154          * and completes when the image is fully loaded.
48155          */
48156         _cacheImage$(spatial) {
48157             return Observable.create((subscriber) => {
48158                 const abort = new Promise((_, reject) => {
48159                     this._imageAborter = reject;
48160                 });
48161                 const url = spatial.thumb.url;
48162                 if (!url) {
48163                     const thumbId = spatial.thumb.id;
48164                     const message = `Incorrect thumb URL for ${spatial.id} ` +
48165                         `(${thumbId}, ${url})`;
48166                     subscriber.error(new Error(message));
48167                     return;
48168                 }
48169                 this._provider.getImageBuffer(url, abort)
48170                     .then((buffer) => {
48171                     this._imageAborter = null;
48172                     const image = new Image();
48173                     image.crossOrigin = "Anonymous";
48174                     image.onload = () => {
48175                         if (this._disposed) {
48176                             window.URL.revokeObjectURL(image.src);
48177                             const message = `Image load was aborted (${url})`;
48178                             subscriber.error(new Error(message));
48179                             return;
48180                         }
48181                         subscriber.next(image);
48182                         subscriber.complete();
48183                     };
48184                     image.onerror = () => {
48185                         this._imageAborter = null;
48186                         subscriber.error(new Error(`Failed to load image (${url})`));
48187                     };
48188                     const blob = new Blob([buffer]);
48189                     image.src = window.URL.createObjectURL(blob);
48190                 }, (error) => {
48191                     this._imageAborter = null;
48192                     subscriber.error(error);
48193                 });
48194             });
48195         }
48196         /**
48197          * Cache the mesh.
48198          *
48199          * @param {SpatialImageEnt} spatial - Spatial props.
48200          * @param {boolean} merged - Value indicating whether image is merged.
48201          * @returns {Observable<ILoadStatusObject<MeshContract>>} Observable emitting
48202          * a load status object every time the load status changes and completes
48203          * when the mesh is fully loaded.
48204          */
48205         _cacheMesh$(spatial, merged) {
48206             return Observable.create((subscriber) => {
48207                 if (!merged) {
48208                     subscriber.next(this._createEmptyMesh());
48209                     subscriber.complete();
48210                     return;
48211                 }
48212                 const url = spatial.mesh.url;
48213                 if (!url) {
48214                     const meshId = spatial.mesh.id;
48215                     const message = `Incorrect mesh URL for ${spatial.id} ` +
48216                         `(${meshId}, ${url})`;
48217                     console.warn(message);
48218                     subscriber.next(this._createEmptyMesh());
48219                     subscriber.complete();
48220                     return;
48221                 }
48222                 const abort = new Promise((_, reject) => {
48223                     this._meshAborter = reject;
48224                 });
48225                 this._provider.getMesh(url, abort)
48226                     .then((mesh) => {
48227                     this._meshAborter = null;
48228                     if (this._disposed) {
48229                         return;
48230                     }
48231                     subscriber.next(mesh);
48232                     subscriber.complete();
48233                 }, (error) => {
48234                     this._meshAborter = null;
48235                     console.error(error);
48236                     subscriber.next(this._createEmptyMesh());
48237                     subscriber.complete();
48238                 });
48239             });
48240         }
48241         /**
48242          * Create a load status object with an empty mesh.
48243          *
48244          * @returns {ILoadStatusObject<MeshContract>} Load status object
48245          * with empty mesh.
48246          */
48247         _createEmptyMesh() {
48248             return { faces: [], vertices: [] };
48249         }
48250         _disposeImage() {
48251             if (this._image != null) {
48252                 window.URL.revokeObjectURL(this._image.src);
48253             }
48254             this._image = null;
48255         }
48256     }
48257
48258     /**
48259      * @class Sequence
48260      *
48261      * @classdesc Represents a sequence of ordered images.
48262      */
48263     class Sequence {
48264         /**
48265          * Create a new sequene instance.
48266          *
48267          * @param {SequenceEnt} sequence - Raw sequence data.
48268          */
48269         constructor(sequence) {
48270             this._id = sequence.id;
48271             this._imageIds = sequence.image_ids;
48272         }
48273         /**
48274          * Get id.
48275          *
48276          * @returns {string} Unique sequence id.
48277          */
48278         get id() {
48279             return this._id;
48280         }
48281         /**
48282          * Get ids.
48283          *
48284          * @returns {Array<string>} Array of ordered image ids in the sequence.
48285          */
48286         get imageIds() {
48287             return this._imageIds;
48288         }
48289         /**
48290          * Dispose the sequence.
48291          *
48292          * @description Disposes all cached assets.
48293          */
48294         dispose() {
48295             this._id = null;
48296             this._imageIds = null;
48297         }
48298         /**
48299          * Find the next image id in the sequence with respect to
48300          * the provided image id.
48301          *
48302          * @param {string} id - Reference image id.
48303          * @returns {string} Next id in sequence if it exists, null otherwise.
48304          */
48305         findNext(id) {
48306             let i = this._imageIds.indexOf(id);
48307             if ((i + 1) >= this._imageIds.length || i === -1) {
48308                 return null;
48309             }
48310             else {
48311                 return this._imageIds[i + 1];
48312             }
48313         }
48314         /**
48315          * Find the previous image id in the sequence with respect to
48316          * the provided image id.
48317          *
48318          * @param {string} id - Reference image id.
48319          * @returns {string} Previous id in sequence if it exists, null otherwise.
48320          */
48321         findPrev(id) {
48322             let i = this._imageIds.indexOf(id);
48323             if (i === 0 || i === -1) {
48324                 return null;
48325             }
48326             else {
48327                 return this._imageIds[i - 1];
48328             }
48329         }
48330     }
48331
48332     class EdgeCalculatorCoefficients {
48333         constructor() {
48334             this.sphericalPreferredDistance = 2;
48335             this.sphericalMotion = 2;
48336             this.sphericalSequencePenalty = 1;
48337             this.sphericalMergeCCPenalty = 4;
48338             this.stepPreferredDistance = 4;
48339             this.stepMotion = 3;
48340             this.stepRotation = 4;
48341             this.stepSequencePenalty = 2;
48342             this.stepMergeCCPenalty = 6;
48343             this.similarDistance = 2;
48344             this.similarRotation = 3;
48345             this.turnDistance = 4;
48346             this.turnMotion = 2;
48347             this.turnSequencePenalty = 1;
48348             this.turnMergeCCPenalty = 4;
48349         }
48350     }
48351
48352     /**
48353      * Enumeration for edge directions
48354      * @enum {number}
48355      * @readonly
48356      * @description Directions for edges in image graph describing
48357      * sequence, spatial and image type relations between nodes.
48358      */
48359     exports.NavigationDirection = void 0;
48360     (function (NavigationDirection) {
48361         /**
48362          * Next image in the sequence.
48363          */
48364         NavigationDirection[NavigationDirection["Next"] = 0] = "Next";
48365         /**
48366          * Previous image in the sequence.
48367          */
48368         NavigationDirection[NavigationDirection["Prev"] = 1] = "Prev";
48369         /**
48370          * Step to the left keeping viewing direction.
48371          */
48372         NavigationDirection[NavigationDirection["StepLeft"] = 2] = "StepLeft";
48373         /**
48374          * Step to the right keeping viewing direction.
48375          */
48376         NavigationDirection[NavigationDirection["StepRight"] = 3] = "StepRight";
48377         /**
48378          * Step forward keeping viewing direction.
48379          */
48380         NavigationDirection[NavigationDirection["StepForward"] = 4] = "StepForward";
48381         /**
48382          * Step backward keeping viewing direction.
48383          */
48384         NavigationDirection[NavigationDirection["StepBackward"] = 5] = "StepBackward";
48385         /**
48386          * Turn 90 degrees counter clockwise.
48387          */
48388         NavigationDirection[NavigationDirection["TurnLeft"] = 6] = "TurnLeft";
48389         /**
48390          * Turn 90 degrees clockwise.
48391          */
48392         NavigationDirection[NavigationDirection["TurnRight"] = 7] = "TurnRight";
48393         /**
48394          * Turn 180 degrees.
48395          */
48396         NavigationDirection[NavigationDirection["TurnU"] = 8] = "TurnU";
48397         /**
48398          * Spherical in general direction.
48399          */
48400         NavigationDirection[NavigationDirection["Spherical"] = 9] = "Spherical";
48401         /**
48402          * Looking in roughly the same direction at rougly the same position.
48403          */
48404         NavigationDirection[NavigationDirection["Similar"] = 10] = "Similar";
48405     })(exports.NavigationDirection || (exports.NavigationDirection = {}));
48406
48407     class EdgeCalculatorDirections {
48408         constructor() {
48409             this.steps = {};
48410             this.turns = {};
48411             this.spherical = {};
48412             this.steps[exports.NavigationDirection.StepForward] = {
48413                 direction: exports.NavigationDirection.StepForward,
48414                 motionChange: 0,
48415                 useFallback: true,
48416             };
48417             this.steps[exports.NavigationDirection.StepBackward] = {
48418                 direction: exports.NavigationDirection.StepBackward,
48419                 motionChange: Math.PI,
48420                 useFallback: true,
48421             };
48422             this.steps[exports.NavigationDirection.StepLeft] = {
48423                 direction: exports.NavigationDirection.StepLeft,
48424                 motionChange: Math.PI / 2,
48425                 useFallback: false,
48426             };
48427             this.steps[exports.NavigationDirection.StepRight] = {
48428                 direction: exports.NavigationDirection.StepRight,
48429                 motionChange: -Math.PI / 2,
48430                 useFallback: false,
48431             };
48432             this.turns[exports.NavigationDirection.TurnLeft] = {
48433                 direction: exports.NavigationDirection.TurnLeft,
48434                 directionChange: Math.PI / 2,
48435                 motionChange: Math.PI / 4,
48436             };
48437             this.turns[exports.NavigationDirection.TurnRight] = {
48438                 direction: exports.NavigationDirection.TurnRight,
48439                 directionChange: -Math.PI / 2,
48440                 motionChange: -Math.PI / 4,
48441             };
48442             this.turns[exports.NavigationDirection.TurnU] = {
48443                 direction: exports.NavigationDirection.TurnU,
48444                 directionChange: Math.PI,
48445                 motionChange: null,
48446             };
48447             this.spherical[exports.NavigationDirection.StepForward] = {
48448                 direction: exports.NavigationDirection.StepForward,
48449                 directionChange: 0,
48450                 next: exports.NavigationDirection.StepLeft,
48451                 prev: exports.NavigationDirection.StepRight,
48452             };
48453             this.spherical[exports.NavigationDirection.StepBackward] = {
48454                 direction: exports.NavigationDirection.StepBackward,
48455                 directionChange: Math.PI,
48456                 next: exports.NavigationDirection.StepRight,
48457                 prev: exports.NavigationDirection.StepLeft,
48458             };
48459             this.spherical[exports.NavigationDirection.StepLeft] = {
48460                 direction: exports.NavigationDirection.StepLeft,
48461                 directionChange: Math.PI / 2,
48462                 next: exports.NavigationDirection.StepBackward,
48463                 prev: exports.NavigationDirection.StepForward,
48464             };
48465             this.spherical[exports.NavigationDirection.StepRight] = {
48466                 direction: exports.NavigationDirection.StepRight,
48467                 directionChange: -Math.PI / 2,
48468                 next: exports.NavigationDirection.StepForward,
48469                 prev: exports.NavigationDirection.StepBackward,
48470             };
48471         }
48472     }
48473
48474     class EdgeCalculatorSettings {
48475         constructor() {
48476             this.sphericalMinDistance = 0.1;
48477             this.sphericalMaxDistance = 20;
48478             this.sphericalPreferredDistance = 5;
48479             this.sphericalMaxItems = 4;
48480             this.sphericalMaxStepTurnChange = Math.PI / 8;
48481             this.rotationMaxDistance = this.turnMaxRigDistance;
48482             this.rotationMaxDirectionChange = Math.PI / 6;
48483             this.rotationMaxVerticalDirectionChange = Math.PI / 8;
48484             this.similarMaxDirectionChange = Math.PI / 8;
48485             this.similarMaxDistance = 12;
48486             this.similarMinTimeDifference = 12 * 3600 * 1000;
48487             this.stepMaxDistance = 20;
48488             this.stepMaxDirectionChange = Math.PI / 6;
48489             this.stepMaxDrift = Math.PI / 6;
48490             this.stepPreferredDistance = 4;
48491             this.turnMaxDistance = 15;
48492             this.turnMaxDirectionChange = 2 * Math.PI / 9;
48493             this.turnMaxRigDistance = 0.65;
48494             this.turnMinRigDirectionChange = Math.PI / 6;
48495         }
48496         get maxDistance() {
48497             return Math.max(this.sphericalMaxDistance, this.similarMaxDistance, this.stepMaxDistance, this.turnMaxDistance);
48498         }
48499     }
48500
48501     /**
48502      * @class MapillaryError
48503      *
48504      * @classdesc Generic Mapillary error.
48505      */
48506     class MapillaryError extends Error {
48507         constructor(message) {
48508             super(message);
48509             Object.setPrototypeOf(this, MapillaryError.prototype);
48510             this.name = "MapillaryError";
48511         }
48512     }
48513
48514     class ArgumentMapillaryError extends MapillaryError {
48515         constructor(message) {
48516             super(message != null ? message : "The argument is not valid.");
48517             Object.setPrototypeOf(this, ArgumentMapillaryError.prototype);
48518             this.name = "ArgumentMapillaryError";
48519         }
48520     }
48521
48522     /**
48523      * @class Spatial
48524      *
48525      * @classdesc Provides methods for scalar, vector and matrix calculations.
48526      */
48527     class Spatial {
48528         constructor() {
48529             this._epsilon = 1e-9;
48530         }
48531         /**
48532          * Converts azimuthal phi rotation (counter-clockwise with origin on X-axis) to
48533          * bearing (clockwise with origin at north or Y-axis).
48534          *
48535          * @param {number} phi - Azimuthal phi angle in radians.
48536          * @returns {number} Bearing in radians.
48537          */
48538         azimuthalToBearing(phi) {
48539             return -phi + Math.PI / 2;
48540         }
48541         /**
48542          * Converts degrees to radians.
48543          *
48544          * @param {number} deg - Degrees.
48545          * @returns {number} Radians.
48546          */
48547         degToRad(deg) {
48548             return Math.PI * deg / 180;
48549         }
48550         /**
48551          * Converts radians to degrees.
48552          *
48553          * @param {number} rad - Radians.
48554          * @returns {number} Degrees.
48555          */
48556         radToDeg(rad) {
48557             return 180 * rad / Math.PI;
48558         }
48559         /**
48560          * Creates a rotation matrix from an angle-axis vector.
48561          *
48562          * @param {Array<number>} angleAxis - Angle-axis representation of a rotation.
48563          * @returns {THREE.Matrix4} Rotation matrix.
48564          */
48565         rotationMatrix(angleAxis) {
48566             let axis = new Vector3(angleAxis[0], angleAxis[1], angleAxis[2]);
48567             let angle = axis.length();
48568             if (angle > 0) {
48569                 axis.normalize();
48570             }
48571             return new Matrix4().makeRotationAxis(axis, angle);
48572         }
48573         /**
48574          * Rotates a vector according to a angle-axis rotation vector.
48575          *
48576          * @param {Array<number>} vector - Vector to rotate.
48577          * @param {Array<number>} angleAxis - Angle-axis representation of a rotation.
48578          * @returns {THREE.Vector3} Rotated vector.
48579          */
48580         rotate(vector, angleAxis) {
48581             let v = new Vector3(vector[0], vector[1], vector[2]);
48582             let rotationMatrix = this.rotationMatrix(angleAxis);
48583             v.applyMatrix4(rotationMatrix);
48584             return v;
48585         }
48586         /**
48587          * Calculates the optical center from a rotation vector
48588          * on the angle-axis representation and a translation vector
48589          * according to C = -R^T t.
48590          *
48591          * @param {Array<number>} rotation - Angle-axis representation of a rotation.
48592          * @param {Array<number>} translation - Translation vector.
48593          * @returns {THREE.Vector3} Optical center.
48594          */
48595         opticalCenter(rotation, translation) {
48596             let angleAxis = [-rotation[0], -rotation[1], -rotation[2]];
48597             let vector = [-translation[0], -translation[1], -translation[2]];
48598             return this.rotate(vector, angleAxis);
48599         }
48600         /**
48601          * Calculates the viewing direction from a rotation vector
48602          * on the angle-axis representation.
48603          *
48604          * @param {number[]} rotation - Angle-axis representation of a rotation.
48605          * @returns {THREE.Vector3} Viewing direction.
48606          */
48607         viewingDirection(rotation) {
48608             let angleAxis = [-rotation[0], -rotation[1], -rotation[2]];
48609             return this.rotate([0, 0, 1], angleAxis);
48610         }
48611         /**
48612          * Wrap a number on the interval [min, max].
48613          *
48614          * @param {number} value - Value to wrap.
48615          * @param {number} min - Lower endpoint of interval.
48616          * @param {number} max - Upper endpoint of interval.
48617          * @returns {number} The wrapped number.
48618          */
48619         wrap(value, min, max) {
48620             if (max < min) {
48621                 throw new Error("Invalid arguments: max must be larger than min.");
48622             }
48623             let interval = (max - min);
48624             while (value > max || value < min) {
48625                 if (value > max) {
48626                     value = value - interval;
48627                 }
48628                 else if (value < min) {
48629                     value = value + interval;
48630                 }
48631             }
48632             return value;
48633         }
48634         /**
48635          * Wrap an angle on the interval [-Pi, Pi].
48636          *
48637          * @param {number} angle - Value to wrap.
48638          * @returns {number} Wrapped angle.
48639          */
48640         wrapAngle(angle) {
48641             return this.wrap(angle, -Math.PI, Math.PI);
48642         }
48643         /**
48644          * Limit the value to the interval [min, max] by changing the value to
48645          * the nearest available one when it is outside the interval.
48646          *
48647          * @param {number} value - Value to clamp.
48648          * @param {number} min - Minimum of the interval.
48649          * @param {number} max - Maximum of the interval.
48650          * @returns {number} Clamped value.
48651          */
48652         clamp(value, min, max) {
48653             if (value < min) {
48654                 return min;
48655             }
48656             if (value > max) {
48657                 return max;
48658             }
48659             return value;
48660         }
48661         /**
48662          * Calculates the counter-clockwise angle from the first
48663          * vector (x1, y1)^T to the second (x2, y2)^T.
48664          *
48665          * @param {number} x1 - X coordinate of first vector.
48666          * @param {number} y1 - Y coordinate of first vector.
48667          * @param {number} x2 - X coordinate of second vector.
48668          * @param {number} y2 - Y coordinate of second vector.
48669          * @returns {number} Counter clockwise angle between the vectors.
48670          */
48671         angleBetweenVector2(x1, y1, x2, y2) {
48672             let angle = Math.atan2(y2, x2) - Math.atan2(y1, x1);
48673             return this.wrapAngle(angle);
48674         }
48675         /**
48676          * Calculates the minimum (absolute) angle change for rotation
48677          * from one angle to another on the [-Pi, Pi] interval.
48678          *
48679          * @param {number} angle1 - Start angle.
48680          * @param {number} angle2 - Destination angle.
48681          * @returns {number} Absolute angle change between angles.
48682          */
48683         angleDifference(angle1, angle2) {
48684             let angle = angle2 - angle1;
48685             return this.wrapAngle(angle);
48686         }
48687         /**
48688          * Calculates the relative rotation angle between two
48689          * angle-axis vectors.
48690          *
48691          * @param {number} rotation1 - First angle-axis vector.
48692          * @param {number} rotation2 - Second angle-axis vector.
48693          * @returns {number} Relative rotation angle.
48694          */
48695         relativeRotationAngle(rotation1, rotation2) {
48696             let R1T = this.rotationMatrix([-rotation1[0], -rotation1[1], -rotation1[2]]);
48697             let R2 = this.rotationMatrix(rotation2);
48698             let R = R1T.multiply(R2);
48699             let elements = R.elements;
48700             // from Tr(R) = 1 + 2 * cos(theta)
48701             let tr = elements[0] + elements[5] + elements[10];
48702             let theta = Math.acos(Math.max(Math.min((tr - 1) / 2, 1), -1));
48703             return theta;
48704         }
48705         /**
48706          * Calculates the angle from a vector to a plane.
48707          *
48708          * @param {Array<number>} vector - The vector.
48709          * @param {Array<number>} planeNormal - Normal of the plane.
48710          * @returns {number} Angle from between plane and vector.
48711          */
48712         angleToPlane(vector, planeNormal) {
48713             let v = new Vector3().fromArray(vector);
48714             let norm = v.length();
48715             if (norm < this._epsilon) {
48716                 return 0;
48717             }
48718             let projection = v.dot(new Vector3().fromArray(planeNormal));
48719             return Math.asin(projection / norm);
48720         }
48721         azimuthal(direction, up) {
48722             const directionVector = new Vector3().fromArray(direction);
48723             const upVector = new Vector3().fromArray(up);
48724             const upProjection = directionVector.clone().dot(upVector);
48725             const planeProjection = directionVector.clone().sub(upVector.clone().multiplyScalar(upProjection));
48726             return Math.atan2(planeProjection.y, planeProjection.x);
48727         }
48728         /**
48729          * Calculates the distance between two coordinates
48730          * (longitude, latitude pairs) in meters according to
48731          * the haversine formula.
48732          *
48733          * @param {number} lat1 - Latitude of the first coordinate in degrees.
48734          * @param {number} lng1 - Longitude of the first coordinate in degrees.
48735          * @param {number} lat2 - Latitude of the second coordinate in degrees.
48736          * @param {number} lng2 - Longitude of the second coordinate in degrees.
48737          * @returns {number} Distance between lat lon positions in meters.
48738          */
48739         distanceFromLngLat(lng1, lat1, lng2, lat2) {
48740             let r = 6371000;
48741             let dLat = this.degToRad(lat2 - lat1);
48742             let dLng = this.degToRad(lng2 - lng1);
48743             let hav = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
48744                 Math.cos(this.degToRad(lat1)) * Math.cos(this.degToRad(lat2)) *
48745                     Math.sin(dLng / 2) * Math.sin(dLng / 2);
48746             let d = 2 * r * Math.atan2(Math.sqrt(hav), Math.sqrt(1 - hav));
48747             return d;
48748         }
48749     }
48750
48751     const spatial = new Spatial();
48752     function isSpherical(cameraType) {
48753         return cameraType === "spherical";
48754     }
48755     function isFisheye(cameraType) {
48756         return cameraType === "fisheye";
48757     }
48758     function computeTranslation(position, rotation, reference) {
48759         const C = geodeticToEnu(position.lng, position.lat, position.alt, reference.lng, reference.lat, reference.alt);
48760         const RC = spatial.rotate(C, rotation);
48761         const translation = [-RC.x, -RC.y, -RC.z];
48762         return translation;
48763     }
48764     function computeProjectedPoints(transform, basicVertices, basicDirections, pointsPerLine, viewportCoords) {
48765         const basicPoints = [];
48766         for (let side = 0; side < basicVertices.length; ++side) {
48767             const v = basicVertices[side];
48768             const d = basicDirections[side];
48769             for (let i = 0; i <= pointsPerLine; ++i) {
48770                 basicPoints.push([v[0] + d[0] * i / pointsPerLine,
48771                     v[1] + d[1] * i / pointsPerLine]);
48772             }
48773         }
48774         const camera = new Camera$1();
48775         camera.up.copy(transform.upVector());
48776         camera.position.copy(new Vector3().fromArray(transform.unprojectSfM([0, 0], 0)));
48777         camera.lookAt(new Vector3().fromArray(transform.unprojectSfM([0, 0], 10)));
48778         camera.updateMatrix();
48779         camera.updateMatrixWorld(true);
48780         const projectedPoints = basicPoints
48781             .map((basicPoint) => {
48782             const worldPoint = transform.unprojectBasic(basicPoint, 10000);
48783             const cameraPoint = viewportCoords.worldToCamera(worldPoint, camera);
48784             return [
48785                 Math.abs(cameraPoint[0] / cameraPoint[2]),
48786                 Math.abs(cameraPoint[1] / cameraPoint[2]),
48787             ];
48788         });
48789         return projectedPoints;
48790     }
48791
48792     /**
48793      * @class EdgeCalculator
48794      *
48795      * @classdesc Represents a class for calculating node edges.
48796      */
48797     class EdgeCalculator {
48798         /**
48799          * Create a new edge calculator instance.
48800          *
48801          * @param {EdgeCalculatorSettings} settings - Settings struct.
48802          * @param {EdgeCalculatorDirections} directions - Directions struct.
48803          * @param {EdgeCalculatorCoefficients} coefficients - Coefficients struct.
48804          */
48805         constructor(settings, directions, coefficients) {
48806             this._spatial = new Spatial();
48807             this._settings = settings != null ? settings : new EdgeCalculatorSettings();
48808             this._directions = directions != null ? directions : new EdgeCalculatorDirections();
48809             this._coefficients = coefficients != null ? coefficients : new EdgeCalculatorCoefficients();
48810         }
48811         /**
48812          * Returns the potential edges to destination nodes for a set
48813          * of nodes with respect to a source node.
48814          *
48815          * @param {Image} node - Source node.
48816          * @param {Array<Image>} nodes - Potential destination nodes.
48817          * @param {Array<string>} fallbackIds - Ids for destination nodes
48818          * that should be returned even if they do not meet the
48819          * criteria for a potential edge.
48820          * @throws {ArgumentMapillaryError} If node is not full.
48821          */
48822         getPotentialEdges(node, potentialImages, fallbackIds) {
48823             if (!node.complete) {
48824                 throw new ArgumentMapillaryError("Image has to be full.");
48825             }
48826             if (!node.merged) {
48827                 return [];
48828             }
48829             let currentDirection = this._spatial.viewingDirection(node.rotation);
48830             let currentVerticalDirection = this._spatial.angleToPlane(currentDirection.toArray(), [0, 0, 1]);
48831             let potentialEdges = [];
48832             for (let potential of potentialImages) {
48833                 if (!potential.merged ||
48834                     potential.id === node.id) {
48835                     continue;
48836                 }
48837                 let enu = geodeticToEnu(potential.lngLat.lng, potential.lngLat.lat, potential.computedAltitude, node.lngLat.lng, node.lngLat.lat, node.computedAltitude);
48838                 let motion = new Vector3(enu[0], enu[1], enu[2]);
48839                 let distance = motion.length();
48840                 if (distance > this._settings.maxDistance &&
48841                     fallbackIds.indexOf(potential.id) < 0) {
48842                     continue;
48843                 }
48844                 let motionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, motion.x, motion.y);
48845                 let verticalMotion = this._spatial.angleToPlane(motion.toArray(), [0, 0, 1]);
48846                 let direction = this._spatial.viewingDirection(potential.rotation);
48847                 let directionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, direction.x, direction.y);
48848                 let verticalDirection = this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
48849                 let verticalDirectionChange = verticalDirection - currentVerticalDirection;
48850                 let rotation = this._spatial.relativeRotationAngle(node.rotation, potential.rotation);
48851                 let worldMotionAzimuth = this._spatial.angleBetweenVector2(1, 0, motion.x, motion.y);
48852                 let sameSequence = potential.sequenceId != null &&
48853                     node.sequenceId != null &&
48854                     potential.sequenceId === node.sequenceId;
48855                 let sameMergeCC = potential.mergeId === node.mergeId;
48856                 let sameUser = potential.creatorId === node.creatorId;
48857                 let potentialEdge = {
48858                     capturedAt: potential.capturedAt,
48859                     directionChange: directionChange,
48860                     distance: distance,
48861                     spherical: isSpherical(potential.cameraType),
48862                     id: potential.id,
48863                     motionChange: motionChange,
48864                     rotation: rotation,
48865                     sameMergeCC: sameMergeCC,
48866                     sameSequence: sameSequence,
48867                     sameUser: sameUser,
48868                     sequenceId: potential.sequenceId,
48869                     verticalDirectionChange: verticalDirectionChange,
48870                     verticalMotion: verticalMotion,
48871                     worldMotionAzimuth: worldMotionAzimuth,
48872                 };
48873                 potentialEdges.push(potentialEdge);
48874             }
48875             return potentialEdges;
48876         }
48877         /**
48878          * Computes the sequence edges for a node.
48879          *
48880          * @param {Image} node - Source node.
48881          * @throws {ArgumentMapillaryError} If node is not full.
48882          */
48883         computeSequenceEdges(node, sequence) {
48884             if (!node.complete) {
48885                 throw new ArgumentMapillaryError("Image has to be full.");
48886             }
48887             if (node.sequenceId !== sequence.id) {
48888                 throw new ArgumentMapillaryError("Image and sequence does not correspond.");
48889             }
48890             let edges = [];
48891             let nextId = sequence.findNext(node.id);
48892             if (nextId != null) {
48893                 edges.push({
48894                     data: {
48895                         direction: exports.NavigationDirection.Next,
48896                         worldMotionAzimuth: Number.NaN,
48897                     },
48898                     source: node.id,
48899                     target: nextId,
48900                 });
48901             }
48902             let prevId = sequence.findPrev(node.id);
48903             if (prevId != null) {
48904                 edges.push({
48905                     data: {
48906                         direction: exports.NavigationDirection.Prev,
48907                         worldMotionAzimuth: Number.NaN,
48908                     },
48909                     source: node.id,
48910                     target: prevId,
48911                 });
48912             }
48913             return edges;
48914         }
48915         /**
48916          * Computes the similar edges for a node.
48917          *
48918          * @description Similar edges for perspective images
48919          * look roughly in the same direction and are positioned closed to the node.
48920          * Similar edges for spherical only target other spherical.
48921          *
48922          * @param {Image} node - Source node.
48923          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
48924          * @throws {ArgumentMapillaryError} If node is not full.
48925          */
48926         computeSimilarEdges(node, potentialEdges) {
48927             if (!node.complete) {
48928                 throw new ArgumentMapillaryError("Image has to be full.");
48929             }
48930             let nodeSpherical = isSpherical(node.cameraType);
48931             let sequenceGroups = {};
48932             for (let potentialEdge of potentialEdges) {
48933                 if (potentialEdge.sequenceId == null) {
48934                     continue;
48935                 }
48936                 if (potentialEdge.sameSequence) {
48937                     continue;
48938                 }
48939                 if (nodeSpherical) {
48940                     if (!potentialEdge.spherical) {
48941                         continue;
48942                     }
48943                 }
48944                 else {
48945                     if (!potentialEdge.spherical &&
48946                         Math.abs(potentialEdge.directionChange) > this._settings.similarMaxDirectionChange) {
48947                         continue;
48948                     }
48949                 }
48950                 if (potentialEdge.distance > this._settings.similarMaxDistance) {
48951                     continue;
48952                 }
48953                 if (potentialEdge.sameUser &&
48954                     Math.abs(potentialEdge.capturedAt - node.capturedAt) <
48955                         this._settings.similarMinTimeDifference) {
48956                     continue;
48957                 }
48958                 if (sequenceGroups[potentialEdge.sequenceId] == null) {
48959                     sequenceGroups[potentialEdge.sequenceId] = [];
48960                 }
48961                 sequenceGroups[potentialEdge.sequenceId].push(potentialEdge);
48962             }
48963             let similarEdges = [];
48964             let calculateScore = isSpherical(node.cameraType) ?
48965                 (potentialEdge) => {
48966                     return potentialEdge.distance;
48967                 } :
48968                 (potentialEdge) => {
48969                     return this._coefficients.similarDistance * potentialEdge.distance +
48970                         this._coefficients.similarRotation * potentialEdge.rotation;
48971                 };
48972             for (let sequenceId in sequenceGroups) {
48973                 if (!sequenceGroups.hasOwnProperty(sequenceId)) {
48974                     continue;
48975                 }
48976                 let lowestScore = Number.MAX_VALUE;
48977                 let similarEdge = null;
48978                 for (let potentialEdge of sequenceGroups[sequenceId]) {
48979                     let score = calculateScore(potentialEdge);
48980                     if (score < lowestScore) {
48981                         lowestScore = score;
48982                         similarEdge = potentialEdge;
48983                     }
48984                 }
48985                 if (similarEdge == null) {
48986                     continue;
48987                 }
48988                 similarEdges.push(similarEdge);
48989             }
48990             return similarEdges
48991                 .map((potentialEdge) => {
48992                 return {
48993                     data: {
48994                         direction: exports.NavigationDirection.Similar,
48995                         worldMotionAzimuth: potentialEdge.worldMotionAzimuth,
48996                     },
48997                     source: node.id,
48998                     target: potentialEdge.id,
48999                 };
49000             });
49001         }
49002         /**
49003          * Computes the step edges for a perspective node.
49004          *
49005          * @description Step edge targets can only be other perspective nodes.
49006          * Returns an empty array for spherical.
49007          *
49008          * @param {Image} node - Source node.
49009          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
49010          * @param {string} prevId - Id of previous node in sequence.
49011          * @param {string} nextId - Id of next node in sequence.
49012          * @throws {ArgumentMapillaryError} If node is not full.
49013          */
49014         computeStepEdges(node, potentialEdges, prevId, nextId) {
49015             if (!node.complete) {
49016                 throw new ArgumentMapillaryError("Image has to be full.");
49017             }
49018             let edges = [];
49019             if (isSpherical(node.cameraType)) {
49020                 return edges;
49021             }
49022             for (let k in this._directions.steps) {
49023                 if (!this._directions.steps.hasOwnProperty(k)) {
49024                     continue;
49025                 }
49026                 let step = this._directions.steps[k];
49027                 let lowestScore = Number.MAX_VALUE;
49028                 let edge = null;
49029                 let fallback = null;
49030                 for (let potential of potentialEdges) {
49031                     if (potential.spherical) {
49032                         continue;
49033                     }
49034                     if (Math.abs(potential.directionChange) > this._settings.stepMaxDirectionChange) {
49035                         continue;
49036                     }
49037                     let motionDifference = this._spatial.angleDifference(step.motionChange, potential.motionChange);
49038                     let directionMotionDifference = this._spatial.angleDifference(potential.directionChange, motionDifference);
49039                     let drift = Math.max(Math.abs(motionDifference), Math.abs(directionMotionDifference));
49040                     if (Math.abs(drift) > this._settings.stepMaxDrift) {
49041                         continue;
49042                     }
49043                     let potentialId = potential.id;
49044                     if (step.useFallback && (potentialId === prevId || potentialId === nextId)) {
49045                         fallback = potential;
49046                     }
49047                     if (potential.distance > this._settings.stepMaxDistance) {
49048                         continue;
49049                     }
49050                     motionDifference = Math.sqrt(motionDifference * motionDifference +
49051                         potential.verticalMotion * potential.verticalMotion);
49052                     let score = this._coefficients.stepPreferredDistance *
49053                         Math.abs(potential.distance - this._settings.stepPreferredDistance) /
49054                         this._settings.stepMaxDistance +
49055                         this._coefficients.stepMotion * motionDifference / this._settings.stepMaxDrift +
49056                         this._coefficients.stepRotation * potential.rotation / this._settings.stepMaxDirectionChange +
49057                         this._coefficients.stepSequencePenalty * (potential.sameSequence ? 0 : 1) +
49058                         this._coefficients.stepMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
49059                     if (score < lowestScore) {
49060                         lowestScore = score;
49061                         edge = potential;
49062                     }
49063                 }
49064                 edge = edge == null ? fallback : edge;
49065                 if (edge != null) {
49066                     edges.push({
49067                         data: {
49068                             direction: step.direction,
49069                             worldMotionAzimuth: edge.worldMotionAzimuth,
49070                         },
49071                         source: node.id,
49072                         target: edge.id,
49073                     });
49074                 }
49075             }
49076             return edges;
49077         }
49078         /**
49079          * Computes the turn edges for a perspective node.
49080          *
49081          * @description Turn edge targets can only be other perspective images.
49082          * Returns an empty array for spherical.
49083          *
49084          * @param {Image} node - Source node.
49085          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
49086          * @throws {ArgumentMapillaryError} If node is not full.
49087          */
49088         computeTurnEdges(node, potentialEdges) {
49089             if (!node.complete) {
49090                 throw new ArgumentMapillaryError("Image has to be full.");
49091             }
49092             let edges = [];
49093             if (isSpherical(node.cameraType)) {
49094                 return edges;
49095             }
49096             for (let k in this._directions.turns) {
49097                 if (!this._directions.turns.hasOwnProperty(k)) {
49098                     continue;
49099                 }
49100                 let turn = this._directions.turns[k];
49101                 let lowestScore = Number.MAX_VALUE;
49102                 let edge = null;
49103                 for (let potential of potentialEdges) {
49104                     if (potential.spherical) {
49105                         continue;
49106                     }
49107                     if (potential.distance > this._settings.turnMaxDistance) {
49108                         continue;
49109                     }
49110                     let rig = turn.direction !== exports.NavigationDirection.TurnU &&
49111                         potential.distance < this._settings.turnMaxRigDistance &&
49112                         Math.abs(potential.directionChange) > this._settings.turnMinRigDirectionChange;
49113                     let directionDifference = this._spatial.angleDifference(turn.directionChange, potential.directionChange);
49114                     let score;
49115                     if (rig &&
49116                         potential.directionChange * turn.directionChange > 0 &&
49117                         Math.abs(potential.directionChange) < Math.abs(turn.directionChange)) {
49118                         score = -Math.PI / 2 + Math.abs(potential.directionChange);
49119                     }
49120                     else {
49121                         if (Math.abs(directionDifference) > this._settings.turnMaxDirectionChange) {
49122                             continue;
49123                         }
49124                         let motionDifference = turn.motionChange ?
49125                             this._spatial.angleDifference(turn.motionChange, potential.motionChange) : 0;
49126                         motionDifference = Math.sqrt(motionDifference * motionDifference +
49127                             potential.verticalMotion * potential.verticalMotion);
49128                         score =
49129                             this._coefficients.turnDistance * potential.distance /
49130                                 this._settings.turnMaxDistance +
49131                                 this._coefficients.turnMotion * motionDifference / Math.PI +
49132                                 this._coefficients.turnSequencePenalty * (potential.sameSequence ? 0 : 1) +
49133                                 this._coefficients.turnMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
49134                     }
49135                     if (score < lowestScore) {
49136                         lowestScore = score;
49137                         edge = potential;
49138                     }
49139                 }
49140                 if (edge != null) {
49141                     edges.push({
49142                         data: {
49143                             direction: turn.direction,
49144                             worldMotionAzimuth: edge.worldMotionAzimuth,
49145                         },
49146                         source: node.id,
49147                         target: edge.id,
49148                     });
49149                 }
49150             }
49151             return edges;
49152         }
49153         /**
49154          * Computes the spherical edges for a perspective node.
49155          *
49156          * @description Perspective to spherical edge targets can only be
49157          * spherical nodes. Returns an empty array for spherical.
49158          *
49159          * @param {Image} node - Source node.
49160          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
49161          * @throws {ArgumentMapillaryError} If node is not full.
49162          */
49163         computePerspectiveToSphericalEdges(node, potentialEdges) {
49164             if (!node.complete) {
49165                 throw new ArgumentMapillaryError("Image has to be full.");
49166             }
49167             if (isSpherical(node.cameraType)) {
49168                 return [];
49169             }
49170             let lowestScore = Number.MAX_VALUE;
49171             let edge = null;
49172             for (let potential of potentialEdges) {
49173                 if (!potential.spherical) {
49174                     continue;
49175                 }
49176                 let score = this._coefficients.sphericalPreferredDistance *
49177                     Math.abs(potential.distance - this._settings.sphericalPreferredDistance) /
49178                     this._settings.sphericalMaxDistance +
49179                     this._coefficients.sphericalMotion * Math.abs(potential.motionChange) / Math.PI +
49180                     this._coefficients.sphericalMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
49181                 if (score < lowestScore) {
49182                     lowestScore = score;
49183                     edge = potential;
49184                 }
49185             }
49186             if (edge == null) {
49187                 return [];
49188             }
49189             return [
49190                 {
49191                     data: {
49192                         direction: exports.NavigationDirection.Spherical,
49193                         worldMotionAzimuth: edge.worldMotionAzimuth,
49194                     },
49195                     source: node.id,
49196                     target: edge.id,
49197                 },
49198             ];
49199         }
49200         /**
49201          * Computes the spherical and step edges for a spherical node.
49202          *
49203          * @description Spherical to spherical edge targets can only be
49204          * spherical nodes. spherical to step edge targets can only be perspective
49205          * nodes.
49206          *
49207          * @param {Image} node - Source node.
49208          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
49209          * @throws {ArgumentMapillaryError} If node is not full.
49210          */
49211         computeSphericalEdges(node, potentialEdges) {
49212             if (!node.complete) {
49213                 throw new ArgumentMapillaryError("Image has to be full.");
49214             }
49215             if (!isSpherical(node.cameraType)) {
49216                 return [];
49217             }
49218             let sphericalEdges = [];
49219             let potentialSpherical = [];
49220             let potentialSteps = [];
49221             for (let potential of potentialEdges) {
49222                 if (potential.distance > this._settings.sphericalMaxDistance) {
49223                     continue;
49224                 }
49225                 if (potential.spherical) {
49226                     if (potential.distance < this._settings.sphericalMinDistance) {
49227                         continue;
49228                     }
49229                     potentialSpherical.push(potential);
49230                 }
49231                 else {
49232                     for (let k in this._directions.spherical) {
49233                         if (!this._directions.spherical.hasOwnProperty(k)) {
49234                             continue;
49235                         }
49236                         let spherical = this._directions.spherical[k];
49237                         let turn = this._spatial.angleDifference(potential.directionChange, potential.motionChange);
49238                         let turnChange = this._spatial.angleDifference(spherical.directionChange, turn);
49239                         if (Math.abs(turnChange) > this._settings.sphericalMaxStepTurnChange) {
49240                             continue;
49241                         }
49242                         potentialSteps.push([spherical.direction, potential]);
49243                         // break if step direction found
49244                         break;
49245                     }
49246                 }
49247             }
49248             let maxRotationDifference = Math.PI / this._settings.sphericalMaxItems;
49249             let occupiedAngles = [];
49250             let stepAngles = [];
49251             for (let index = 0; index < this._settings.sphericalMaxItems; index++) {
49252                 let rotation = index / this._settings.sphericalMaxItems * 2 * Math.PI;
49253                 let lowestScore = Number.MAX_VALUE;
49254                 let edge = null;
49255                 for (let potential of potentialSpherical) {
49256                     let motionDifference = this._spatial.angleDifference(rotation, potential.motionChange);
49257                     if (Math.abs(motionDifference) > maxRotationDifference) {
49258                         continue;
49259                     }
49260                     let occupiedDifference = Number.MAX_VALUE;
49261                     for (let occupiedAngle of occupiedAngles) {
49262                         let difference = Math.abs(this._spatial.angleDifference(occupiedAngle, potential.motionChange));
49263                         if (difference < occupiedDifference) {
49264                             occupiedDifference = difference;
49265                         }
49266                     }
49267                     if (occupiedDifference <= maxRotationDifference) {
49268                         continue;
49269                     }
49270                     let score = this._coefficients.sphericalPreferredDistance *
49271                         Math.abs(potential.distance - this._settings.sphericalPreferredDistance) /
49272                         this._settings.sphericalMaxDistance +
49273                         this._coefficients.sphericalMotion * Math.abs(motionDifference) / maxRotationDifference +
49274                         this._coefficients.sphericalSequencePenalty * (potential.sameSequence ? 0 : 1) +
49275                         this._coefficients.sphericalMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
49276                     if (score < lowestScore) {
49277                         lowestScore = score;
49278                         edge = potential;
49279                     }
49280                 }
49281                 if (edge != null) {
49282                     occupiedAngles.push(edge.motionChange);
49283                     sphericalEdges.push({
49284                         data: {
49285                             direction: exports.NavigationDirection.Spherical,
49286                             worldMotionAzimuth: edge.worldMotionAzimuth,
49287                         },
49288                         source: node.id,
49289                         target: edge.id,
49290                     });
49291                 }
49292                 else {
49293                     stepAngles.push(rotation);
49294                 }
49295             }
49296             let occupiedStepAngles = {};
49297             occupiedStepAngles[exports.NavigationDirection.Spherical] = occupiedAngles;
49298             occupiedStepAngles[exports.NavigationDirection.StepForward] = [];
49299             occupiedStepAngles[exports.NavigationDirection.StepLeft] = [];
49300             occupiedStepAngles[exports.NavigationDirection.StepBackward] = [];
49301             occupiedStepAngles[exports.NavigationDirection.StepRight] = [];
49302             for (let stepAngle of stepAngles) {
49303                 let occupations = [];
49304                 for (let k in this._directions.spherical) {
49305                     if (!this._directions.spherical.hasOwnProperty(k)) {
49306                         continue;
49307                     }
49308                     let spherical = this._directions.spherical[k];
49309                     let allOccupiedAngles = occupiedStepAngles[exports.NavigationDirection.Spherical]
49310                         .concat(occupiedStepAngles[spherical.direction])
49311                         .concat(occupiedStepAngles[spherical.prev])
49312                         .concat(occupiedStepAngles[spherical.next]);
49313                     let lowestScore = Number.MAX_VALUE;
49314                     let edge = null;
49315                     for (let potential of potentialSteps) {
49316                         if (potential[0] !== spherical.direction) {
49317                             continue;
49318                         }
49319                         let motionChange = this._spatial.angleDifference(stepAngle, potential[1].motionChange);
49320                         if (Math.abs(motionChange) > maxRotationDifference) {
49321                             continue;
49322                         }
49323                         let minOccupiedDifference = Number.MAX_VALUE;
49324                         for (let occupiedAngle of allOccupiedAngles) {
49325                             let occupiedDifference = Math.abs(this._spatial.angleDifference(occupiedAngle, potential[1].motionChange));
49326                             if (occupiedDifference < minOccupiedDifference) {
49327                                 minOccupiedDifference = occupiedDifference;
49328                             }
49329                         }
49330                         if (minOccupiedDifference <= maxRotationDifference) {
49331                             continue;
49332                         }
49333                         let score = this._coefficients.sphericalPreferredDistance *
49334                             Math.abs(potential[1].distance - this._settings.sphericalPreferredDistance) /
49335                             this._settings.sphericalMaxDistance +
49336                             this._coefficients.sphericalMotion * Math.abs(motionChange) / maxRotationDifference +
49337                             this._coefficients.sphericalMergeCCPenalty * (potential[1].sameMergeCC ? 0 : 1);
49338                         if (score < lowestScore) {
49339                             lowestScore = score;
49340                             edge = potential;
49341                         }
49342                     }
49343                     if (edge != null) {
49344                         occupations.push(edge);
49345                         sphericalEdges.push({
49346                             data: {
49347                                 direction: edge[0],
49348                                 worldMotionAzimuth: edge[1].worldMotionAzimuth,
49349                             },
49350                             source: node.id,
49351                             target: edge[1].id,
49352                         });
49353                     }
49354                 }
49355                 for (let occupation of occupations) {
49356                     occupiedStepAngles[occupation[0]].push(occupation[1].motionChange);
49357                 }
49358             }
49359             return sphericalEdges;
49360         }
49361     }
49362
49363     class GraphMapillaryError extends MapillaryError {
49364         constructor(message) {
49365             super(message);
49366             Object.setPrototypeOf(this, GraphMapillaryError.prototype);
49367             this.name = "GraphMapillaryError";
49368         }
49369     }
49370
49371     /**
49372      * @class Graph
49373      *
49374      * @classdesc Represents a graph of nodes with edges.
49375      */
49376     class Graph {
49377         /**
49378          * Create a new graph instance.
49379          *
49380          * @param {APIWrapper} [api] - API instance for retrieving data.
49381          * @param {rbush.RBush<NodeIndexItem>} [nodeIndex] - Node index for fast spatial retreival.
49382          * @param {GraphCalculator} [graphCalculator] - Instance for graph calculations.
49383          * @param {EdgeCalculator} [edgeCalculator] - Instance for edge calculations.
49384          * @param {FilterCreator} [filterCreator] - Instance for  filter creation.
49385          * @param {GraphConfiguration} [configuration] - Configuration struct.
49386          */
49387         constructor(api, nodeIndex, graphCalculator, edgeCalculator, filterCreator, configuration) {
49388             this._api = api;
49389             this._cachedNodes = {};
49390             this._cachedNodeTiles = {};
49391             this._cachedSequenceNodes = {};
49392             this._cachedSpatialEdges = {};
49393             this._cachedTiles = {};
49394             this._cachingFill$ = {};
49395             this._cachingFull$ = {};
49396             this._cachingSequenceNodes$ = {};
49397             this._cachingSequences$ = {};
49398             this._cachingSpatialArea$ = {};
49399             this._cachingTiles$ = {};
49400             this._changed$ = new Subject();
49401             this._filterCreator = filterCreator !== null && filterCreator !== void 0 ? filterCreator : new FilterCreator();
49402             this._filter = this._filterCreator.createFilter(undefined);
49403             this._filterSubject$ = new Subject();
49404             this._filter$ =
49405                 concat(of(this._filter), this._filterSubject$).pipe(publishReplay(1), refCount());
49406             this._filterSubscription = this._filter$.subscribe(() => { });
49407             this._defaultAlt = 2;
49408             this._edgeCalculator = edgeCalculator !== null && edgeCalculator !== void 0 ? edgeCalculator : new EdgeCalculator();
49409             this._graphCalculator = graphCalculator !== null && graphCalculator !== void 0 ? graphCalculator : new GraphCalculator();
49410             this._configuration = configuration !== null && configuration !== void 0 ? configuration : {
49411                 maxSequences: 50,
49412                 maxUnusedImages: 100,
49413                 maxUnusedPreStoredImages: 30,
49414                 maxUnusedTiles: 20,
49415             };
49416             this._nodes = {};
49417             this._nodeIndex = nodeIndex !== null && nodeIndex !== void 0 ? nodeIndex : new Graph._spatialIndex(16);
49418             this._nodeIndexTiles = {};
49419             this._nodeToTile = {};
49420             this._preStored = {};
49421             this._requiredNodeTiles = {};
49422             this._requiredSpatialArea = {};
49423             this._sequences = {};
49424             this._tileThreshold = 20;
49425         }
49426         static register(spatialIndex) {
49427             Graph._spatialIndex = spatialIndex;
49428         }
49429         /**
49430          * Get api.
49431          *
49432          * @returns {APIWrapper} The API instance used by
49433          * the graph.
49434          */
49435         get api() {
49436             return this._api;
49437         }
49438         /**
49439          * Get changed$.
49440          *
49441          * @returns {Observable<Graph>} Observable emitting
49442          * the graph every time it has changed.
49443          */
49444         get changed$() {
49445             return this._changed$;
49446         }
49447         /**
49448          * Get filter$.
49449          *
49450          * @returns {Observable<FilterFunction>} Observable emitting
49451          * the filter every time it has changed.
49452          */
49453         get filter$() {
49454             return this._filter$;
49455         }
49456         /**
49457          * Caches the full node data for all images within a bounding
49458          * box.
49459          *
49460          * @description The node assets are not cached.
49461          *
49462          * @param {LngLat} sw - South west corner of bounding box.
49463          * @param {LngLat} ne - North east corner of bounding box.
49464          * @returns {Observable<Array<Image>>} Observable emitting
49465          * the full nodes in the bounding box.
49466          */
49467         cacheBoundingBox$(sw, ne) {
49468             const cacheTiles$ = this._api.data.geometry.bboxToCellIds(sw, ne)
49469                 .filter((h) => {
49470                 return !(h in this._cachedTiles);
49471             })
49472                 .map((h) => {
49473                 return h in this._cachingTiles$ ?
49474                     this._cachingTiles$[h] :
49475                     this._cacheTile$(h);
49476             });
49477             if (cacheTiles$.length === 0) {
49478                 cacheTiles$.push(of(this));
49479             }
49480             return from(cacheTiles$).pipe(mergeAll(), last(), mergeMap(() => {
49481                 const nodes = this._nodeIndex
49482                     .search({
49483                     maxX: ne.lng,
49484                     maxY: ne.lat,
49485                     minX: sw.lng,
49486                     minY: sw.lat,
49487                 })
49488                     .map((item) => {
49489                     return item.node;
49490                 });
49491                 const fullNodes = [];
49492                 const coreNodes = [];
49493                 for (const node of nodes) {
49494                     if (node.complete) {
49495                         fullNodes.push(node);
49496                     }
49497                     else {
49498                         coreNodes.push(node.id);
49499                     }
49500                 }
49501                 const coreNodeBatches = [];
49502                 const batchSize = 200;
49503                 while (coreNodes.length > 0) {
49504                     coreNodeBatches.push(coreNodes.splice(0, batchSize));
49505                 }
49506                 const fullNodes$ = of(fullNodes);
49507                 const fillNodes$ = coreNodeBatches
49508                     .map((batch) => {
49509                     return this._api
49510                         .getSpatialImages$(batch)
49511                         .pipe(map((items) => {
49512                         const result = [];
49513                         for (const item of items) {
49514                             const exists = this
49515                                 .hasNode(item.node_id);
49516                             if (!exists) {
49517                                 continue;
49518                             }
49519                             const node = this
49520                                 .getNode(item.node_id);
49521                             if (!node.complete) {
49522                                 this._makeFull(node, item.node);
49523                             }
49524                             result.push(node);
49525                         }
49526                         return result;
49527                     }));
49528                 });
49529                 return merge(fullNodes$, from(fillNodes$).pipe(mergeAll()));
49530             }), reduce((acc, value) => {
49531                 return acc.concat(value);
49532             }));
49533         }
49534         /**
49535          * Caches the full node data for all images of a cell.
49536          *
49537          * @description The node assets are not cached.
49538          *
49539          * @param {string} cellId - Cell id.
49540          * @returns {Observable<Array<Image>>} Observable
49541          * emitting the full nodes of the cell.
49542          */
49543         cacheCell$(cellId) {
49544             const cacheCell$ = cellId in this._cachedTiles ?
49545                 of(this) :
49546                 cellId in this._cachingTiles$ ?
49547                     this._cachingTiles$[cellId] :
49548                     this._cacheTile$(cellId);
49549             return cacheCell$.pipe(mergeMap(() => {
49550                 const cachedCell = this._cachedTiles[cellId];
49551                 cachedCell.accessed = new Date().getTime();
49552                 const cellNodes = cachedCell.nodes;
49553                 const fullNodes = [];
49554                 const coreNodes = [];
49555                 for (const node of cellNodes) {
49556                     if (node.complete) {
49557                         fullNodes.push(node);
49558                     }
49559                     else {
49560                         coreNodes.push(node.id);
49561                     }
49562                 }
49563                 const coreNodeBatches = [];
49564                 const batchSize = 200;
49565                 while (coreNodes.length > 0) {
49566                     coreNodeBatches.push(coreNodes.splice(0, batchSize));
49567                 }
49568                 const fullNodes$ = of(fullNodes);
49569                 const fillNodes$ = coreNodeBatches
49570                     .map((batch) => {
49571                     return this._api.getSpatialImages$(batch).pipe(map((items) => {
49572                         const filled = [];
49573                         for (const item of items) {
49574                             if (!item.node) {
49575                                 console.warn(`Image is empty (${item.node})`);
49576                                 continue;
49577                             }
49578                             const id = item.node_id;
49579                             if (!this.hasNode(id)) {
49580                                 continue;
49581                             }
49582                             const node = this.getNode(id);
49583                             if (!node.complete) {
49584                                 this._makeFull(node, item.node);
49585                             }
49586                             filled.push(node);
49587                         }
49588                         return filled;
49589                     }));
49590                 });
49591                 return merge(fullNodes$, from(fillNodes$).pipe(mergeAll()));
49592             }), reduce((acc, value) => {
49593                 return acc.concat(value);
49594             }));
49595         }
49596         /**
49597          * Retrieve and cache node fill properties.
49598          *
49599          * @param {string} key - Key of node to fill.
49600          * @returns {Observable<Graph>} Observable emitting the graph
49601          * when the node has been updated.
49602          * @throws {GraphMapillaryError} When the operation is not valid on the
49603          * current graph.
49604          */
49605         cacheFill$(key) {
49606             if (key in this._cachingFull$) {
49607                 throw new GraphMapillaryError(`Cannot fill node while caching full (${key}).`);
49608             }
49609             if (!this.hasNode(key)) {
49610                 throw new GraphMapillaryError(`Cannot fill node that does not exist in graph (${key}).`);
49611             }
49612             if (key in this._cachingFill$) {
49613                 return this._cachingFill$[key];
49614             }
49615             const node = this.getNode(key);
49616             if (node.complete) {
49617                 throw new GraphMapillaryError(`Cannot fill node that is already full (${key}).`);
49618             }
49619             this._cachingFill$[key] = this._api.getSpatialImages$([key]).pipe(tap((items) => {
49620                 for (const item of items) {
49621                     if (!item.node) {
49622                         console.warn(`Image is empty ${item.node_id}`);
49623                     }
49624                     if (!node.complete) {
49625                         this._makeFull(node, item.node);
49626                     }
49627                     delete this._cachingFill$[item.node_id];
49628                 }
49629             }), map(() => { return this; }), finalize(() => {
49630                 if (key in this._cachingFill$) {
49631                     delete this._cachingFill$[key];
49632                 }
49633                 this._changed$.next(this);
49634             }), publish(), refCount());
49635             return this._cachingFill$[key];
49636         }
49637         /**
49638          * Retrieve and cache full node properties.
49639          *
49640          * @param {string} key - Key of node to fill.
49641          * @returns {Observable<Graph>} Observable emitting the graph
49642          * when the node has been updated.
49643          * @throws {GraphMapillaryError} When the operation is not valid on the
49644          * current graph.
49645          */
49646         cacheFull$(key) {
49647             if (key in this._cachingFull$) {
49648                 return this._cachingFull$[key];
49649             }
49650             if (this.hasNode(key)) {
49651                 throw new GraphMapillaryError(`Cannot cache full node that already exist in graph (${key}).`);
49652             }
49653             this._cachingFull$[key] = this._api.getImages$([key]).pipe(tap((items) => {
49654                 for (const item of items) {
49655                     if (!item.node) {
49656                         throw new GraphMapillaryError(`Image does not exist (${key}, ${item.node}).`);
49657                     }
49658                     const id = item.node_id;
49659                     if (this.hasNode(id)) {
49660                         const node = this.getNode(key);
49661                         if (!node.complete) {
49662                             this._makeFull(node, item.node);
49663                         }
49664                     }
49665                     else {
49666                         if (item.node.sequence.id == null) {
49667                             throw new GraphMapillaryError(`Image has no sequence key (${key}).`);
49668                         }
49669                         const node = new Image$1(item.node);
49670                         this._makeFull(node, item.node);
49671                         const cellId = this._api.data.geometry
49672                             .lngLatToCellId(node.originalLngLat);
49673                         this._preStore(cellId, node);
49674                         this._setNode(node);
49675                         delete this._cachingFull$[id];
49676                     }
49677                 }
49678             }), map(() => this), finalize(() => {
49679                 if (key in this._cachingFull$) {
49680                     delete this._cachingFull$[key];
49681                 }
49682                 this._changed$.next(this);
49683             }), publish(), refCount());
49684             return this._cachingFull$[key];
49685         }
49686         /**
49687          * Retrieve and cache a node sequence.
49688          *
49689          * @param {string} key - Key of node for which to retrieve sequence.
49690          * @returns {Observable<Graph>} Observable emitting the graph
49691          * when the sequence has been retrieved.
49692          * @throws {GraphMapillaryError} When the operation is not valid on the
49693          * current graph.
49694          */
49695         cacheNodeSequence$(key) {
49696             if (!this.hasNode(key)) {
49697                 throw new GraphMapillaryError(`Cannot cache sequence edges of node that does not exist in graph (${key}).`);
49698             }
49699             let node = this.getNode(key);
49700             if (node.sequenceId in this._sequences) {
49701                 throw new GraphMapillaryError(`Sequence already cached (${key}), (${node.sequenceId}).`);
49702             }
49703             return this._cacheSequence$(node.sequenceId);
49704         }
49705         /**
49706          * Retrieve and cache a sequence.
49707          *
49708          * @param {string} sequenceKey - Key of sequence to cache.
49709          * @returns {Observable<Graph>} Observable emitting the graph
49710          * when the sequence has been retrieved.
49711          * @throws {GraphMapillaryError} When the operation is not valid on the
49712          * current graph.
49713          */
49714         cacheSequence$(sequenceKey) {
49715             if (sequenceKey in this._sequences) {
49716                 throw new GraphMapillaryError(`Sequence already cached (${sequenceKey})`);
49717             }
49718             return this._cacheSequence$(sequenceKey);
49719         }
49720         /**
49721          * Cache sequence edges for a node.
49722          *
49723          * @param {string} key - Key of node.
49724          * @throws {GraphMapillaryError} When the operation is not valid on the
49725          * current graph.
49726          */
49727         cacheSequenceEdges(key) {
49728             let node = this.getNode(key);
49729             if (!(node.sequenceId in this._sequences)) {
49730                 throw new GraphMapillaryError(`Sequence is not cached (${key}), (${node.sequenceId})`);
49731             }
49732             let sequence = this._sequences[node.sequenceId].sequence;
49733             let edges = this._edgeCalculator.computeSequenceEdges(node, sequence);
49734             node.cacheSequenceEdges(edges);
49735         }
49736         /**
49737          * Retrieve and cache full nodes for all keys in a sequence.
49738          *
49739          * @param {string} sequenceKey - Key of sequence.
49740          * @param {string} referenceNodeKey - Key of node to use as reference
49741          * for optimized caching.
49742          * @returns {Observable<Graph>} Observable emitting the graph
49743          * when the nodes of the sequence has been cached.
49744          */
49745         cacheSequenceNodes$(sequenceKey, referenceNodeKey) {
49746             if (!this.hasSequence(sequenceKey)) {
49747                 throw new GraphMapillaryError(`Cannot cache sequence nodes of sequence that does not exist in graph (${sequenceKey}).`);
49748             }
49749             if (this.hasSequenceNodes(sequenceKey)) {
49750                 throw new GraphMapillaryError(`Sequence nodes already cached (${sequenceKey}).`);
49751             }
49752             const sequence = this.getSequence(sequenceKey);
49753             if (sequence.id in this._cachingSequenceNodes$) {
49754                 return this._cachingSequenceNodes$[sequence.id];
49755             }
49756             const batches = [];
49757             const keys = sequence.imageIds.slice();
49758             const referenceBatchSize = 50;
49759             if (!!referenceNodeKey && keys.length > referenceBatchSize) {
49760                 const referenceIndex = keys.indexOf(referenceNodeKey);
49761                 const startIndex = Math.max(0, Math.min(referenceIndex - referenceBatchSize / 2, keys.length - referenceBatchSize));
49762                 batches.push(keys.splice(startIndex, referenceBatchSize));
49763             }
49764             const batchSize = 200;
49765             while (keys.length > 0) {
49766                 batches.push(keys.splice(0, batchSize));
49767             }
49768             let batchesToCache = batches.length;
49769             const sequenceNodes$ = from(batches).pipe(mergeMap((batch) => {
49770                 return this._api.getImages$(batch).pipe(tap((items) => {
49771                     for (const item of items) {
49772                         if (!item.node) {
49773                             console.warn(`Image empty (${item.node_id})`);
49774                             continue;
49775                         }
49776                         const id = item.node_id;
49777                         if (this.hasNode(id)) {
49778                             const node = this.getNode(id);
49779                             if (!node.complete) {
49780                                 this._makeFull(node, item.node);
49781                             }
49782                         }
49783                         else {
49784                             if (item.node.sequence.id == null) {
49785                                 console.warn(`Sequence missing, discarding node (${item.node_id})`);
49786                             }
49787                             const node = new Image$1(item.node);
49788                             this._makeFull(node, item.node);
49789                             const cellId = this._api.data.geometry
49790                                 .lngLatToCellId(node.originalLngLat);
49791                             this._preStore(cellId, node);
49792                             this._setNode(node);
49793                         }
49794                     }
49795                     batchesToCache--;
49796                 }), map(() => this));
49797             }, 6), last(), finalize(() => {
49798                 delete this._cachingSequenceNodes$[sequence.id];
49799                 if (batchesToCache === 0) {
49800                     this._cachedSequenceNodes[sequence.id] = true;
49801                 }
49802             }), publish(), refCount());
49803             this._cachingSequenceNodes$[sequence.id] = sequenceNodes$;
49804             return sequenceNodes$;
49805         }
49806         /**
49807          * Retrieve and cache full nodes for a node spatial area.
49808          *
49809          * @param {string} key - Key of node for which to retrieve sequence.
49810          * @returns {Observable<Graph>} Observable emitting the graph
49811          * when the nodes in the spatial area has been made full.
49812          * @throws {GraphMapillaryError} When the operation is not valid on the
49813          * current graph.
49814          */
49815         cacheSpatialArea$(key) {
49816             if (!this.hasNode(key)) {
49817                 throw new GraphMapillaryError(`Cannot cache spatial area of node that does not exist in graph (${key}).`);
49818             }
49819             if (key in this._cachedSpatialEdges) {
49820                 throw new GraphMapillaryError(`Image already spatially cached (${key}).`);
49821             }
49822             if (!(key in this._requiredSpatialArea)) {
49823                 throw new GraphMapillaryError(`Spatial area not determined (${key}).`);
49824             }
49825             let spatialArea = this._requiredSpatialArea[key];
49826             if (Object.keys(spatialArea.cacheNodes).length === 0) {
49827                 throw new GraphMapillaryError(`Spatial nodes already cached (${key}).`);
49828             }
49829             if (key in this._cachingSpatialArea$) {
49830                 return this._cachingSpatialArea$[key];
49831             }
49832             let batches = [];
49833             while (spatialArea.cacheKeys.length > 0) {
49834                 batches.push(spatialArea.cacheKeys.splice(0, 200));
49835             }
49836             let batchesToCache = batches.length;
49837             let spatialNodes$ = [];
49838             for (let batch of batches) {
49839                 let spatialNodeBatch$ = this._api.getSpatialImages$(batch).pipe(tap((items) => {
49840                     for (const item of items) {
49841                         if (!item.node) {
49842                             console.warn(`Image is empty (${item.node_id})`);
49843                             continue;
49844                         }
49845                         const id = item.node_id;
49846                         const spatialNode = spatialArea.cacheNodes[id];
49847                         if (spatialNode.complete) {
49848                             delete spatialArea.cacheNodes[id];
49849                             continue;
49850                         }
49851                         this._makeFull(spatialNode, item.node);
49852                         delete spatialArea.cacheNodes[id];
49853                     }
49854                     if (--batchesToCache === 0) {
49855                         delete this._cachingSpatialArea$[key];
49856                     }
49857                 }), map(() => { return this; }), catchError((error) => {
49858                     for (let batchKey of batch) {
49859                         if (batchKey in spatialArea.all) {
49860                             delete spatialArea.all[batchKey];
49861                         }
49862                         if (batchKey in spatialArea.cacheNodes) {
49863                             delete spatialArea.cacheNodes[batchKey];
49864                         }
49865                     }
49866                     if (--batchesToCache === 0) {
49867                         delete this._cachingSpatialArea$[key];
49868                     }
49869                     throw error;
49870                 }), finalize(() => {
49871                     if (Object.keys(spatialArea.cacheNodes).length === 0) {
49872                         this._changed$.next(this);
49873                     }
49874                 }), publish(), refCount());
49875                 spatialNodes$.push(spatialNodeBatch$);
49876             }
49877             this._cachingSpatialArea$[key] = spatialNodes$;
49878             return spatialNodes$;
49879         }
49880         /**
49881          * Cache spatial edges for a node.
49882          *
49883          * @param {string} key - Key of node.
49884          * @throws {GraphMapillaryError} When the operation is not valid on the
49885          * current graph.
49886          */
49887         cacheSpatialEdges(key) {
49888             if (key in this._cachedSpatialEdges) {
49889                 throw new GraphMapillaryError(`Spatial edges already cached (${key}).`);
49890             }
49891             let node = this.getNode(key);
49892             let sequence = this._sequences[node.sequenceId].sequence;
49893             let fallbackKeys = [];
49894             let prevKey = sequence.findPrev(node.id);
49895             if (prevKey != null) {
49896                 fallbackKeys.push(prevKey);
49897             }
49898             let nextKey = sequence.findNext(node.id);
49899             if (nextKey != null) {
49900                 fallbackKeys.push(nextKey);
49901             }
49902             let allSpatialNodes = this._requiredSpatialArea[key].all;
49903             let potentialNodes = [];
49904             let filter = this._filter;
49905             for (let spatialNodeKey in allSpatialNodes) {
49906                 if (!allSpatialNodes.hasOwnProperty(spatialNodeKey)) {
49907                     continue;
49908                 }
49909                 let spatialNode = allSpatialNodes[spatialNodeKey];
49910                 if (filter(spatialNode)) {
49911                     potentialNodes.push(spatialNode);
49912                 }
49913             }
49914             let potentialEdges = this._edgeCalculator.getPotentialEdges(node, potentialNodes, fallbackKeys);
49915             let edges = this._edgeCalculator.computeStepEdges(node, potentialEdges, prevKey, nextKey);
49916             edges = edges.concat(this._edgeCalculator.computeTurnEdges(node, potentialEdges));
49917             edges = edges.concat(this._edgeCalculator.computeSphericalEdges(node, potentialEdges));
49918             edges = edges.concat(this._edgeCalculator.computePerspectiveToSphericalEdges(node, potentialEdges));
49919             edges = edges.concat(this._edgeCalculator.computeSimilarEdges(node, potentialEdges));
49920             node.cacheSpatialEdges(edges);
49921             this._cachedSpatialEdges[key] = node;
49922             delete this._requiredSpatialArea[key];
49923             delete this._cachedNodeTiles[key];
49924         }
49925         /**
49926          * Retrieve and cache tiles for a node.
49927          *
49928          * @param {string} key - Key of node for which to retrieve tiles.
49929          * @returns {Array<Observable<Graph>>} Array of observables emitting
49930          * the graph for each tile required for the node has been cached.
49931          * @throws {GraphMapillaryError} When the operation is not valid on the
49932          * current graph.
49933          */
49934         cacheTiles$(key) {
49935             if (key in this._cachedNodeTiles) {
49936                 throw new GraphMapillaryError(`Tiles already cached (${key}).`);
49937             }
49938             if (key in this._cachedSpatialEdges) {
49939                 throw new GraphMapillaryError(`Spatial edges already cached so tiles considered cached (${key}).`);
49940             }
49941             if (!(key in this._requiredNodeTiles)) {
49942                 throw new GraphMapillaryError(`Tiles have not been determined (${key}).`);
49943             }
49944             let nodeTiles = this._requiredNodeTiles[key];
49945             if (nodeTiles.cache.length === 0 &&
49946                 nodeTiles.caching.length === 0) {
49947                 throw new GraphMapillaryError(`Tiles already cached (${key}).`);
49948             }
49949             if (!this.hasNode(key)) {
49950                 throw new GraphMapillaryError(`Cannot cache tiles of node that does not exist in graph (${key}).`);
49951             }
49952             let hs = nodeTiles.cache.slice();
49953             nodeTiles.caching = this._requiredNodeTiles[key].caching.concat(hs);
49954             nodeTiles.cache = [];
49955             let cacheTiles$ = [];
49956             for (let h of nodeTiles.caching) {
49957                 const cacheTile$ = h in this._cachingTiles$ ?
49958                     this._cachingTiles$[h] :
49959                     this._cacheTile$(h);
49960                 cacheTiles$.push(cacheTile$.pipe(tap((graph) => {
49961                     let index = nodeTiles.caching.indexOf(h);
49962                     if (index > -1) {
49963                         nodeTiles.caching.splice(index, 1);
49964                     }
49965                     if (nodeTiles.caching.length === 0 &&
49966                         nodeTiles.cache.length === 0) {
49967                         delete this._requiredNodeTiles[key];
49968                         this._cachedNodeTiles[key] = true;
49969                     }
49970                 }), catchError((error) => {
49971                     let index = nodeTiles.caching.indexOf(h);
49972                     if (index > -1) {
49973                         nodeTiles.caching.splice(index, 1);
49974                     }
49975                     if (nodeTiles.caching.length === 0 &&
49976                         nodeTiles.cache.length === 0) {
49977                         delete this._requiredNodeTiles[key];
49978                         this._cachedNodeTiles[key] = true;
49979                     }
49980                     throw error;
49981                 }), finalize(() => {
49982                     this._changed$.next(this);
49983                 }), publish(), refCount()));
49984             }
49985             return cacheTiles$;
49986         }
49987         /**
49988          * Initialize the cache for a node.
49989          *
49990          * @param {string} key - Key of node.
49991          * @throws {GraphMapillaryError} When the operation is not valid on the
49992          * current graph.
49993          */
49994         initializeCache(key) {
49995             if (key in this._cachedNodes) {
49996                 throw new GraphMapillaryError(`Image already in cache (${key}).`);
49997             }
49998             const node = this.getNode(key);
49999             const provider = this._api.data;
50000             node.initializeCache(new ImageCache(provider));
50001             const accessed = new Date().getTime();
50002             this._cachedNodes[key] = { accessed: accessed, node: node };
50003             this._updateCachedTileAccess(key, accessed);
50004         }
50005         /**
50006          * Get a value indicating if the graph is fill caching a node.
50007          *
50008          * @param {string} key - Key of node.
50009          * @returns {boolean} Value indicating if the node is being fill cached.
50010          */
50011         isCachingFill(key) {
50012             return key in this._cachingFill$;
50013         }
50014         /**
50015          * Get a value indicating if the graph is fully caching a node.
50016          *
50017          * @param {string} key - Key of node.
50018          * @returns {boolean} Value indicating if the node is being fully cached.
50019          */
50020         isCachingFull(key) {
50021             return key in this._cachingFull$;
50022         }
50023         /**
50024          * Get a value indicating if the graph is caching a sequence of a node.
50025          *
50026          * @param {string} key - Key of node.
50027          * @returns {boolean} Value indicating if the sequence of a node is
50028          * being cached.
50029          */
50030         isCachingNodeSequence(key) {
50031             let node = this.getNode(key);
50032             return node.sequenceId in this._cachingSequences$;
50033         }
50034         /**
50035          * Get a value indicating if the graph is caching a sequence.
50036          *
50037          * @param {string} sequenceKey - Key of sequence.
50038          * @returns {boolean} Value indicating if the sequence is
50039          * being cached.
50040          */
50041         isCachingSequence(sequenceKey) {
50042             return sequenceKey in this._cachingSequences$;
50043         }
50044         /**
50045          * Get a value indicating if the graph is caching sequence nodes.
50046          *
50047          * @param {string} sequenceKey - Key of sequence.
50048          * @returns {boolean} Value indicating if the sequence nodes are
50049          * being cached.
50050          */
50051         isCachingSequenceNodes(sequenceKey) {
50052             return sequenceKey in this._cachingSequenceNodes$;
50053         }
50054         /**
50055          * Get a value indicating if the graph is caching the tiles
50056          * required for calculating spatial edges of a node.
50057          *
50058          * @param {string} key - Key of node.
50059          * @returns {boolean} Value indicating if the tiles of
50060          * a node are being cached.
50061          */
50062         isCachingTiles(key) {
50063             return key in this._requiredNodeTiles &&
50064                 this._requiredNodeTiles[key].cache.length === 0 &&
50065                 this._requiredNodeTiles[key].caching.length > 0;
50066         }
50067         /**
50068          * Get a value indicating if the cache has been initialized
50069          * for a node.
50070          *
50071          * @param {string} key - Key of node.
50072          * @returns {boolean} Value indicating if the cache has been
50073          * initialized for a node.
50074          */
50075         hasInitializedCache(key) {
50076             return key in this._cachedNodes;
50077         }
50078         /**
50079          * Get a value indicating if a node exist in the graph.
50080          *
50081          * @param {string} key - Key of node.
50082          * @returns {boolean} Value indicating if a node exist in the graph.
50083          */
50084         hasNode(key) {
50085             let accessed = new Date().getTime();
50086             this._updateCachedNodeAccess(key, accessed);
50087             this._updateCachedTileAccess(key, accessed);
50088             return key in this._nodes;
50089         }
50090         /**
50091          * Get a value indicating if a node sequence exist in the graph.
50092          *
50093          * @param {string} key - Key of node.
50094          * @returns {boolean} Value indicating if a node sequence exist
50095          * in the graph.
50096          */
50097         hasNodeSequence(key) {
50098             let node = this.getNode(key);
50099             let sequenceKey = node.sequenceId;
50100             let hasNodeSequence = sequenceKey in this._sequences;
50101             if (hasNodeSequence) {
50102                 this._sequences[sequenceKey].accessed = new Date().getTime();
50103             }
50104             return hasNodeSequence;
50105         }
50106         /**
50107          * Get a value indicating if a sequence exist in the graph.
50108          *
50109          * @param {string} sequenceKey - Key of sequence.
50110          * @returns {boolean} Value indicating if a sequence exist
50111          * in the graph.
50112          */
50113         hasSequence(sequenceKey) {
50114             let hasSequence = sequenceKey in this._sequences;
50115             if (hasSequence) {
50116                 this._sequences[sequenceKey].accessed = new Date().getTime();
50117             }
50118             return hasSequence;
50119         }
50120         /**
50121          * Get a value indicating if sequence nodes has been cached in the graph.
50122          *
50123          * @param {string} sequenceKey - Key of sequence.
50124          * @returns {boolean} Value indicating if a sequence nodes has been
50125          * cached in the graph.
50126          */
50127         hasSequenceNodes(sequenceKey) {
50128             return sequenceKey in this._cachedSequenceNodes;
50129         }
50130         /**
50131          * Get a value indicating if the graph has fully cached
50132          * all nodes in the spatial area of a node.
50133          *
50134          * @param {string} key - Key of node.
50135          * @returns {boolean} Value indicating if the spatial area
50136          * of a node has been cached.
50137          */
50138         hasSpatialArea(key) {
50139             if (!this.hasNode(key)) {
50140                 throw new GraphMapillaryError(`Spatial area nodes cannot be determined if node not in graph (${key}).`);
50141             }
50142             if (key in this._cachedSpatialEdges) {
50143                 return true;
50144             }
50145             if (key in this._requiredSpatialArea) {
50146                 return Object
50147                     .keys(this._requiredSpatialArea[key].cacheNodes)
50148                     .length === 0;
50149             }
50150             let node = this.getNode(key);
50151             let bbox = this._graphCalculator
50152                 .boundingBoxCorners(node.lngLat, this._tileThreshold);
50153             let spatialItems = this._nodeIndex
50154                 .search({
50155                 maxX: bbox[1].lng,
50156                 maxY: bbox[1].lat,
50157                 minX: bbox[0].lng,
50158                 minY: bbox[0].lat,
50159             });
50160             let spatialNodes = {
50161                 all: {},
50162                 cacheKeys: [],
50163                 cacheNodes: {},
50164             };
50165             for (let spatialItem of spatialItems) {
50166                 spatialNodes.all[spatialItem.node.id] = spatialItem.node;
50167                 if (!spatialItem.node.complete) {
50168                     spatialNodes.cacheKeys.push(spatialItem.node.id);
50169                     spatialNodes.cacheNodes[spatialItem.node.id] = spatialItem.node;
50170                 }
50171             }
50172             this._requiredSpatialArea[key] = spatialNodes;
50173             return spatialNodes.cacheKeys.length === 0;
50174         }
50175         /**
50176          * Get a value indicating if the graph has a tiles required
50177          * for a node.
50178          *
50179          * @param {string} key - Key of node.
50180          * @returns {boolean} Value indicating if the the tiles required
50181          * by a node has been cached.
50182          */
50183         hasTiles(key) {
50184             if (key in this._cachedNodeTiles) {
50185                 return true;
50186             }
50187             if (key in this._cachedSpatialEdges) {
50188                 return true;
50189             }
50190             if (!this.hasNode(key)) {
50191                 throw new GraphMapillaryError(`Image does not exist in graph (${key}).`);
50192             }
50193             let nodeTiles = { cache: [], caching: [] };
50194             if (!(key in this._requiredNodeTiles)) {
50195                 const node = this.getNode(key);
50196                 const [sw, ne] = this._graphCalculator
50197                     .boundingBoxCorners(node.lngLat, this._tileThreshold);
50198                 nodeTiles.cache = this._api.data.geometry
50199                     .bboxToCellIds(sw, ne)
50200                     .filter((h) => {
50201                     return !(h in this._cachedTiles);
50202                 });
50203                 if (nodeTiles.cache.length > 0) {
50204                     this._requiredNodeTiles[key] = nodeTiles;
50205                 }
50206             }
50207             else {
50208                 nodeTiles = this._requiredNodeTiles[key];
50209             }
50210             return nodeTiles.cache.length === 0 && nodeTiles.caching.length === 0;
50211         }
50212         /**
50213          * Get a node.
50214          *
50215          * @param {string} key - Key of node.
50216          * @returns {Image} Retrieved node.
50217          */
50218         getNode(key) {
50219             let accessed = new Date().getTime();
50220             this._updateCachedNodeAccess(key, accessed);
50221             this._updateCachedTileAccess(key, accessed);
50222             return this._nodes[key];
50223         }
50224         /**
50225          * Get a sequence.
50226          *
50227          * @param {string} sequenceKey - Key of sequence.
50228          * @returns {Image} Retrieved sequence.
50229          */
50230         getSequence(sequenceKey) {
50231             let sequenceAccess = this._sequences[sequenceKey];
50232             sequenceAccess.accessed = new Date().getTime();
50233             return sequenceAccess.sequence;
50234         }
50235         /**
50236          * Reset all spatial edges of the graph nodes.
50237          */
50238         resetSpatialEdges() {
50239             let cachedKeys = Object.keys(this._cachedSpatialEdges);
50240             for (let cachedKey of cachedKeys) {
50241                 let node = this._cachedSpatialEdges[cachedKey];
50242                 node.resetSpatialEdges();
50243                 delete this._cachedSpatialEdges[cachedKey];
50244             }
50245         }
50246         /**
50247          * Reset the complete graph but keep the nodes corresponding
50248          * to the supplied keys. All other nodes will be disposed.
50249          *
50250          * @param {Array<string>} keepKeys - Keys for nodes to keep
50251          * in graph after reset.
50252          */
50253         reset(keepKeys) {
50254             const nodes = [];
50255             for (const key of keepKeys) {
50256                 if (!this.hasNode(key)) {
50257                     throw new Error(`Image does not exist ${key}`);
50258                 }
50259                 const node = this.getNode(key);
50260                 node.resetSequenceEdges();
50261                 node.resetSpatialEdges();
50262                 nodes.push(node);
50263             }
50264             for (let cachedKey of Object.keys(this._cachedNodes)) {
50265                 if (keepKeys.indexOf(cachedKey) !== -1) {
50266                     continue;
50267                 }
50268                 this._cachedNodes[cachedKey].node.dispose();
50269                 delete this._cachedNodes[cachedKey];
50270             }
50271             this._cachedNodeTiles = {};
50272             this._cachedSpatialEdges = {};
50273             this._cachedTiles = {};
50274             this._cachingFill$ = {};
50275             this._cachingFull$ = {};
50276             this._cachingSequences$ = {};
50277             this._cachingSpatialArea$ = {};
50278             this._cachingTiles$ = {};
50279             this._nodes = {};
50280             this._nodeToTile = {};
50281             this._preStored = {};
50282             for (const node of nodes) {
50283                 this._nodes[node.id] = node;
50284                 const h = this._api.data.geometry.lngLatToCellId(node.originalLngLat);
50285                 this._preStore(h, node);
50286             }
50287             this._requiredNodeTiles = {};
50288             this._requiredSpatialArea = {};
50289             this._sequences = {};
50290             this._nodeIndexTiles = {};
50291             this._nodeIndex.clear();
50292         }
50293         /**
50294          * Set the spatial node filter.
50295          *
50296          * @emits FilterFunction The filter function to the {@link Graph.filter$}
50297          * observable.
50298          *
50299          * @param {FilterExpression} filter - Filter expression to be applied
50300          * when calculating spatial edges.
50301          */
50302         setFilter(filter) {
50303             this._filter = this._filterCreator.createFilter(filter);
50304             this._filterSubject$.next(this._filter);
50305         }
50306         /**
50307          * Uncache the graph according to the graph configuration.
50308          *
50309          * @description Uncaches unused tiles, unused nodes and
50310          * sequences according to the numbers specified in the
50311          * graph configuration. Sequences does not have a direct
50312          * reference to either tiles or nodes and may be uncached
50313          * even if they are related to the nodes that should be kept.
50314          *
50315          * @param {Array<string>} keepIds - Ids of nodes to keep in
50316          * graph unrelated to last access. Tiles related to those keys
50317          * will also be kept in graph.
50318          * @param {Array<string>} keepCellIds - Ids of cells to keep in
50319          * graph unrelated to last access. The nodes of the cells may
50320          * still be uncached if not specified in the keep ids param
50321          * but are guaranteed to not be disposed.
50322          * @param {string} keepSequenceId - Optional id of sequence
50323          * for which the belonging nodes should not be disposed or
50324          * removed from the graph. These nodes may still be uncached if
50325          * not specified in keep ids param but are guaranteed to not
50326          * be disposed.
50327          */
50328         uncache(keepIds, keepCellIds, keepSequenceId) {
50329             const idsInUse = {};
50330             this._addNewKeys(idsInUse, this._cachingFull$);
50331             this._addNewKeys(idsInUse, this._cachingFill$);
50332             this._addNewKeys(idsInUse, this._cachingSpatialArea$);
50333             this._addNewKeys(idsInUse, this._requiredNodeTiles);
50334             this._addNewKeys(idsInUse, this._requiredSpatialArea);
50335             for (const key of keepIds) {
50336                 if (key in idsInUse) {
50337                     continue;
50338                 }
50339                 idsInUse[key] = true;
50340             }
50341             const tileThreshold = this._tileThreshold;
50342             const calculator = this._graphCalculator;
50343             const geometry = this._api.data.geometry;
50344             const keepCells = new Set(keepCellIds);
50345             for (let id in idsInUse) {
50346                 if (!idsInUse.hasOwnProperty(id)) {
50347                     continue;
50348                 }
50349                 const node = this._nodes[id];
50350                 const [sw, ne] = calculator
50351                     .boundingBoxCorners(node.lngLat, tileThreshold);
50352                 const nodeCellIds = geometry.bboxToCellIds(sw, ne);
50353                 for (const nodeCellId of nodeCellIds) {
50354                     if (!keepCells.has(nodeCellId)) {
50355                         keepCells.add(nodeCellId);
50356                     }
50357                 }
50358             }
50359             const potentialCells = [];
50360             for (let cellId in this._cachedTiles) {
50361                 if (!this._cachedTiles.hasOwnProperty(cellId) ||
50362                     keepCells.has(cellId)) {
50363                     continue;
50364                 }
50365                 potentialCells.push([cellId, this._cachedTiles[cellId]]);
50366             }
50367             const uncacheCells = potentialCells
50368                 .sort((h1, h2) => {
50369                 return h2[1].accessed - h1[1].accessed;
50370             })
50371                 .slice(this._configuration.maxUnusedTiles)
50372                 .map((h) => {
50373                 return h[0];
50374             });
50375             for (let uncacheCell of uncacheCells) {
50376                 this._uncacheTile(uncacheCell, keepSequenceId);
50377             }
50378             const potentialPreStored = [];
50379             const nonCachedPreStored = [];
50380             for (let cellId in this._preStored) {
50381                 if (!this._preStored.hasOwnProperty(cellId) ||
50382                     cellId in this._cachingTiles$) {
50383                     continue;
50384                 }
50385                 const prestoredNodes = this._preStored[cellId];
50386                 for (let id in prestoredNodes) {
50387                     if (!prestoredNodes.hasOwnProperty(id) || id in idsInUse) {
50388                         continue;
50389                     }
50390                     if (prestoredNodes[id].sequenceId === keepSequenceId) {
50391                         continue;
50392                     }
50393                     if (id in this._cachedNodes) {
50394                         potentialPreStored.push([this._cachedNodes[id], cellId]);
50395                     }
50396                     else {
50397                         nonCachedPreStored.push([id, cellId]);
50398                     }
50399                 }
50400             }
50401             const uncachePreStored = potentialPreStored
50402                 .sort(([na1], [na2]) => {
50403                 return na2.accessed - na1.accessed;
50404             })
50405                 .slice(this._configuration.maxUnusedPreStoredImages)
50406                 .map(([na, h]) => {
50407                 return [na.node.id, h];
50408             });
50409             this._uncachePreStored(nonCachedPreStored);
50410             this._uncachePreStored(uncachePreStored);
50411             const potentialNodes = [];
50412             for (let id in this._cachedNodes) {
50413                 if (!this._cachedNodes.hasOwnProperty(id) || id in idsInUse) {
50414                     continue;
50415                 }
50416                 potentialNodes.push(this._cachedNodes[id]);
50417             }
50418             const uncacheNodes = potentialNodes
50419                 .sort((n1, n2) => {
50420                 return n2.accessed - n1.accessed;
50421             })
50422                 .slice(this._configuration.maxUnusedImages);
50423             for (const nodeAccess of uncacheNodes) {
50424                 nodeAccess.node.uncache();
50425                 const id = nodeAccess.node.id;
50426                 delete this._cachedNodes[id];
50427                 if (id in this._cachedNodeTiles) {
50428                     delete this._cachedNodeTiles[id];
50429                 }
50430                 if (id in this._cachedSpatialEdges) {
50431                     delete this._cachedSpatialEdges[id];
50432                 }
50433             }
50434             const potentialSequences = [];
50435             for (let sequenceId in this._sequences) {
50436                 if (!this._sequences.hasOwnProperty(sequenceId) ||
50437                     sequenceId in this._cachingSequences$ ||
50438                     sequenceId === keepSequenceId) {
50439                     continue;
50440                 }
50441                 potentialSequences.push(this._sequences[sequenceId]);
50442             }
50443             const uncacheSequences = potentialSequences
50444                 .sort((s1, s2) => {
50445                 return s2.accessed - s1.accessed;
50446             })
50447                 .slice(this._configuration.maxSequences);
50448             for (const sequenceAccess of uncacheSequences) {
50449                 const sequenceId = sequenceAccess.sequence.id;
50450                 delete this._sequences[sequenceId];
50451                 if (sequenceId in this._cachedSequenceNodes) {
50452                     delete this._cachedSequenceNodes[sequenceId];
50453                 }
50454                 sequenceAccess.sequence.dispose();
50455             }
50456         }
50457         /**
50458          * Updates existing cells with new core nodes.
50459          *
50460          * @description Non-existing cells are discarded
50461          * and not requested at all.
50462          *
50463          * Existing nodes are not changed.
50464          *
50465          * New nodes are not made full or getting assets
50466          * cached.
50467          *
50468          * @param {Array<string>} cellIds - Cell ids.
50469          * @returns {Observable<Array<Image>>} Observable
50470          * emitting the updated cells.
50471          */
50472         updateCells$(cellIds) {
50473             const cachedCells = this._cachedTiles;
50474             const cachingCells = this._cachingTiles$;
50475             return from(cellIds)
50476                 .pipe(mergeMap((cellId) => {
50477                 if (cellId in cachedCells) {
50478                     return this._updateCell$(cellId);
50479                 }
50480                 if (cellId in cachingCells) {
50481                     return cachingCells[cellId]
50482                         .pipe(catchError(() => {
50483                         return of(this);
50484                     }), mergeMap(() => this._updateCell$(cellId)));
50485                 }
50486                 return empty();
50487             }));
50488         }
50489         /**
50490          * Unsubscribes all subscriptions.
50491          *
50492          * @description Afterwards, you must not call any other methods
50493          * on the graph instance.
50494          */
50495         unsubscribe() {
50496             this._filterSubscription.unsubscribe();
50497         }
50498         _addNewKeys(keys, dict) {
50499             for (let key in dict) {
50500                 if (!dict.hasOwnProperty(key) || !this.hasNode(key)) {
50501                     continue;
50502                 }
50503                 if (!(key in keys)) {
50504                     keys[key] = true;
50505                 }
50506             }
50507         }
50508         _cacheSequence$(sequenceId) {
50509             if (sequenceId in this._cachingSequences$) {
50510                 return this._cachingSequences$[sequenceId];
50511             }
50512             this._cachingSequences$[sequenceId] = this._api
50513                 .getSequence$(sequenceId)
50514                 .pipe(tap((sequence) => {
50515                 if (!sequence) {
50516                     console.warn(`Sequence does not exist ` +
50517                         `(${sequenceId})`);
50518                 }
50519                 else {
50520                     if (!(sequence.id in this._sequences)) {
50521                         this._sequences[sequence.id] = {
50522                             accessed: new Date().getTime(),
50523                             sequence: new Sequence(sequence),
50524                         };
50525                     }
50526                     delete this._cachingSequences$[sequenceId];
50527                 }
50528             }), map(() => { return this; }), finalize(() => {
50529                 if (sequenceId in this._cachingSequences$) {
50530                     delete this._cachingSequences$[sequenceId];
50531                 }
50532                 this._changed$.next(this);
50533             }), publish(), refCount());
50534             return this._cachingSequences$[sequenceId];
50535         }
50536         _cacheTile$(cellId) {
50537             this._cachingTiles$[cellId] = this._api
50538                 .getCoreImages$(cellId)
50539                 .pipe(tap((contract) => {
50540                 if (cellId in this._cachedTiles) {
50541                     return;
50542                 }
50543                 const cores = contract.images;
50544                 this._nodeIndexTiles[cellId] = [];
50545                 this._cachedTiles[cellId] = {
50546                     accessed: new Date().getTime(),
50547                     nodes: [],
50548                 };
50549                 const hCache = this._cachedTiles[cellId].nodes;
50550                 const preStored = this._removeFromPreStore(cellId);
50551                 for (const core of cores) {
50552                     if (!core) {
50553                         break;
50554                     }
50555                     if (core.sequence.id == null) {
50556                         console.warn(`Sequence missing, discarding ` +
50557                             `node (${core.id})`);
50558                         continue;
50559                     }
50560                     if (preStored != null && core.id in preStored) {
50561                         const preStoredNode = preStored[core.id];
50562                         delete preStored[core.id];
50563                         hCache.push(preStoredNode);
50564                         const preStoredNodeIndexItem = {
50565                             lat: preStoredNode.lngLat.lat,
50566                             lng: preStoredNode.lngLat.lng,
50567                             node: preStoredNode,
50568                         };
50569                         this._nodeIndex.insert(preStoredNodeIndexItem);
50570                         this._nodeIndexTiles[cellId]
50571                             .push(preStoredNodeIndexItem);
50572                         this._nodeToTile[preStoredNode.id] = cellId;
50573                         continue;
50574                     }
50575                     const node = new Image$1(core);
50576                     hCache.push(node);
50577                     const nodeIndexItem = {
50578                         lat: node.lngLat.lat,
50579                         lng: node.lngLat.lng,
50580                         node: node,
50581                     };
50582                     this._nodeIndex.insert(nodeIndexItem);
50583                     this._nodeIndexTiles[cellId].push(nodeIndexItem);
50584                     this._nodeToTile[node.id] = cellId;
50585                     this._setNode(node);
50586                 }
50587                 delete this._cachingTiles$[cellId];
50588             }), map(() => this), catchError((error) => {
50589                 delete this._cachingTiles$[cellId];
50590                 throw error;
50591             }), publish(), refCount());
50592             return this._cachingTiles$[cellId];
50593         }
50594         _makeFull(node, fillNode) {
50595             if (fillNode.computed_altitude == null) {
50596                 fillNode.computed_altitude = this._defaultAlt;
50597             }
50598             if (fillNode.computed_rotation == null) {
50599                 fillNode.computed_rotation = this._graphCalculator.rotationFromCompass(fillNode.compass_angle, fillNode.exif_orientation);
50600             }
50601             node.makeComplete(fillNode);
50602         }
50603         _preStore(h, node) {
50604             if (!(h in this._preStored)) {
50605                 this._preStored[h] = {};
50606             }
50607             this._preStored[h][node.id] = node;
50608         }
50609         _removeFromPreStore(h) {
50610             let preStored = null;
50611             if (h in this._preStored) {
50612                 preStored = this._preStored[h];
50613                 delete this._preStored[h];
50614             }
50615             return preStored;
50616         }
50617         _setNode(node) {
50618             let key = node.id;
50619             if (this.hasNode(key)) {
50620                 throw new GraphMapillaryError(`Image already exist (${key}).`);
50621             }
50622             this._nodes[key] = node;
50623         }
50624         _uncacheTile(h, keepSequenceKey) {
50625             for (let node of this._cachedTiles[h].nodes) {
50626                 let key = node.id;
50627                 delete this._nodeToTile[key];
50628                 if (key in this._cachedNodes) {
50629                     delete this._cachedNodes[key];
50630                 }
50631                 if (key in this._cachedNodeTiles) {
50632                     delete this._cachedNodeTiles[key];
50633                 }
50634                 if (key in this._cachedSpatialEdges) {
50635                     delete this._cachedSpatialEdges[key];
50636                 }
50637                 if (node.sequenceId === keepSequenceKey) {
50638                     this._preStore(h, node);
50639                     node.uncache();
50640                 }
50641                 else {
50642                     delete this._nodes[key];
50643                     if (node.sequenceId in this._cachedSequenceNodes) {
50644                         delete this._cachedSequenceNodes[node.sequenceId];
50645                     }
50646                     node.dispose();
50647                 }
50648             }
50649             for (let nodeIndexItem of this._nodeIndexTiles[h]) {
50650                 this._nodeIndex.remove(nodeIndexItem);
50651             }
50652             delete this._nodeIndexTiles[h];
50653             delete this._cachedTiles[h];
50654         }
50655         _uncachePreStored(preStored) {
50656             let hs = {};
50657             for (let [key, h] of preStored) {
50658                 if (key in this._nodes) {
50659                     delete this._nodes[key];
50660                 }
50661                 if (key in this._cachedNodes) {
50662                     delete this._cachedNodes[key];
50663                 }
50664                 let node = this._preStored[h][key];
50665                 if (node.sequenceId in this._cachedSequenceNodes) {
50666                     delete this._cachedSequenceNodes[node.sequenceId];
50667                 }
50668                 delete this._preStored[h][key];
50669                 node.dispose();
50670                 hs[h] = true;
50671             }
50672             for (let h in hs) {
50673                 if (!hs.hasOwnProperty(h)) {
50674                     continue;
50675                 }
50676                 if (Object.keys(this._preStored[h]).length === 0) {
50677                     delete this._preStored[h];
50678                 }
50679             }
50680         }
50681         _updateCachedTileAccess(key, accessed) {
50682             if (key in this._nodeToTile) {
50683                 this._cachedTiles[this._nodeToTile[key]].accessed = accessed;
50684             }
50685         }
50686         _updateCachedNodeAccess(key, accessed) {
50687             if (key in this._cachedNodes) {
50688                 this._cachedNodes[key].accessed = accessed;
50689             }
50690         }
50691         _updateCell$(cellId) {
50692             return this._api.getCoreImages$(cellId).pipe(mergeMap((contract) => {
50693                 if (!(cellId in this._cachedTiles)) {
50694                     return empty();
50695                 }
50696                 const nodeIndex = this._nodeIndex;
50697                 const nodeIndexCell = this._nodeIndexTiles[cellId];
50698                 const nodeToCell = this._nodeToTile;
50699                 const cell = this._cachedTiles[cellId];
50700                 cell.accessed = new Date().getTime();
50701                 const cellNodes = cell.nodes;
50702                 const cores = contract.images;
50703                 for (const core of cores) {
50704                     if (core == null) {
50705                         break;
50706                     }
50707                     if (this.hasNode(core.id)) {
50708                         continue;
50709                     }
50710                     if (core.sequence.id == null) {
50711                         console.warn(`Sequence missing, discarding ` +
50712                             `node (${core.id})`);
50713                         continue;
50714                     }
50715                     const node = new Image$1(core);
50716                     cellNodes.push(node);
50717                     const nodeIndexItem = {
50718                         lat: node.lngLat.lat,
50719                         lng: node.lngLat.lng,
50720                         node: node,
50721                     };
50722                     nodeIndex.insert(nodeIndexItem);
50723                     nodeIndexCell.push(nodeIndexItem);
50724                     nodeToCell[node.id] = cellId;
50725                     this._setNode(node);
50726                 }
50727                 return of(cellId);
50728             }), catchError((error) => {
50729                 console.error(error);
50730                 return empty();
50731             }));
50732         }
50733     }
50734
50735     class MarkerSet {
50736         constructor() {
50737             this._hash = {};
50738             this._index = new MarkerSet._spatialIndex(16);
50739             this._indexChanged$ = new Subject();
50740             this._updated$ = new Subject();
50741         }
50742         static register(spatialIndex) {
50743             MarkerSet._spatialIndex = spatialIndex;
50744         }
50745         get changed$() {
50746             return this._indexChanged$;
50747         }
50748         get updated$() {
50749             return this._updated$;
50750         }
50751         add(markers) {
50752             const updated = [];
50753             const hash = this._hash;
50754             const index = this._index;
50755             for (const marker of markers) {
50756                 const id = marker.id;
50757                 if (id in hash) {
50758                     index.remove(hash[id]);
50759                     updated.push(marker);
50760                 }
50761                 const item = {
50762                     lat: marker.lngLat.lat,
50763                     lng: marker.lngLat.lng,
50764                     marker: marker,
50765                 };
50766                 hash[id] = item;
50767                 index.insert(item);
50768             }
50769             if (updated.length > 0) {
50770                 this._updated$.next(updated);
50771             }
50772             if (markers.length > updated.length) {
50773                 this._indexChanged$.next(this);
50774             }
50775         }
50776         has(id) {
50777             return id in this._hash;
50778         }
50779         get(id) {
50780             return this.has(id) ? this._hash[id].marker : undefined;
50781         }
50782         getAll() {
50783             return this._index
50784                 .all()
50785                 .map((indexItem) => {
50786                 return indexItem.marker;
50787             });
50788         }
50789         remove(ids) {
50790             const hash = this._hash;
50791             const index = this._index;
50792             let changed = false;
50793             for (const id of ids) {
50794                 if (!(id in hash)) {
50795                     continue;
50796                 }
50797                 const item = hash[id];
50798                 index.remove(item);
50799                 delete hash[id];
50800                 changed = true;
50801             }
50802             if (changed) {
50803                 this._indexChanged$.next(this);
50804             }
50805         }
50806         removeAll() {
50807             this._hash = {};
50808             this._index.clear();
50809             this._indexChanged$.next(this);
50810         }
50811         search([sw, ne]) {
50812             return this._index
50813                 .search({
50814                 maxX: ne.lng,
50815                 maxY: ne.lat,
50816                 minX: sw.lng,
50817                 minY: sw.lat,
50818             })
50819                 .map((indexItem) => {
50820                 return indexItem.marker;
50821             });
50822         }
50823         update(marker) {
50824             const hash = this._hash;
50825             const index = this._index;
50826             const id = marker.id;
50827             if (!(id in hash)) {
50828                 return;
50829             }
50830             index.remove(hash[id]);
50831             const item = {
50832                 lat: marker.lngLat.lat,
50833                 lng: marker.lngLat.lng,
50834                 marker: marker,
50835             };
50836             hash[id] = item;
50837             index.insert(item);
50838         }
50839     }
50840
50841     function quickselect(arr, k, left, right, compare) {
50842         quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare$2);
50843     }
50844
50845     function quickselectStep(arr, k, left, right, compare) {
50846
50847         while (right > left) {
50848             if (right - left > 600) {
50849                 var n = right - left + 1;
50850                 var m = k - left + 1;
50851                 var z = Math.log(n);
50852                 var s = 0.5 * Math.exp(2 * z / 3);
50853                 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
50854                 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
50855                 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
50856                 quickselectStep(arr, k, newLeft, newRight, compare);
50857             }
50858
50859             var t = arr[k];
50860             var i = left;
50861             var j = right;
50862
50863             swap(arr, left, k);
50864             if (compare(arr[right], t) > 0) swap(arr, left, right);
50865
50866             while (i < j) {
50867                 swap(arr, i, j);
50868                 i++;
50869                 j--;
50870                 while (compare(arr[i], t) < 0) i++;
50871                 while (compare(arr[j], t) > 0) j--;
50872             }
50873
50874             if (compare(arr[left], t) === 0) swap(arr, left, j);
50875             else {
50876                 j++;
50877                 swap(arr, j, right);
50878             }
50879
50880             if (j <= k) left = j + 1;
50881             if (k <= j) right = j - 1;
50882         }
50883     }
50884
50885     function swap(arr, i, j) {
50886         var tmp = arr[i];
50887         arr[i] = arr[j];
50888         arr[j] = tmp;
50889     }
50890
50891     function defaultCompare$2(a, b) {
50892         return a < b ? -1 : a > b ? 1 : 0;
50893     }
50894
50895     class RBush {
50896         constructor(maxEntries = 9) {
50897             // max entries in a node is 9 by default; min node fill is 40% for best performance
50898             this._maxEntries = Math.max(4, maxEntries);
50899             this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
50900             this.clear();
50901         }
50902
50903         all() {
50904             return this._all(this.data, []);
50905         }
50906
50907         search(bbox) {
50908             let node = this.data;
50909             const result = [];
50910
50911             if (!intersects$1(bbox, node)) return result;
50912
50913             const toBBox = this.toBBox;
50914             const nodesToSearch = [];
50915
50916             while (node) {
50917                 for (let i = 0; i < node.children.length; i++) {
50918                     const child = node.children[i];
50919                     const childBBox = node.leaf ? toBBox(child) : child;
50920
50921                     if (intersects$1(bbox, childBBox)) {
50922                         if (node.leaf) result.push(child);
50923                         else if (contains(bbox, childBBox)) this._all(child, result);
50924                         else nodesToSearch.push(child);
50925                     }
50926                 }
50927                 node = nodesToSearch.pop();
50928             }
50929
50930             return result;
50931         }
50932
50933         collides(bbox) {
50934             let node = this.data;
50935
50936             if (!intersects$1(bbox, node)) return false;
50937
50938             const nodesToSearch = [];
50939             while (node) {
50940                 for (let i = 0; i < node.children.length; i++) {
50941                     const child = node.children[i];
50942                     const childBBox = node.leaf ? this.toBBox(child) : child;
50943
50944                     if (intersects$1(bbox, childBBox)) {
50945                         if (node.leaf || contains(bbox, childBBox)) return true;
50946                         nodesToSearch.push(child);
50947                     }
50948                 }
50949                 node = nodesToSearch.pop();
50950             }
50951
50952             return false;
50953         }
50954
50955         load(data) {
50956             if (!(data && data.length)) return this;
50957
50958             if (data.length < this._minEntries) {
50959                 for (let i = 0; i < data.length; i++) {
50960                     this.insert(data[i]);
50961                 }
50962                 return this;
50963             }
50964
50965             // recursively build the tree with the given data from scratch using OMT algorithm
50966             let node = this._build(data.slice(), 0, data.length - 1, 0);
50967
50968             if (!this.data.children.length) {
50969                 // save as is if tree is empty
50970                 this.data = node;
50971
50972             } else if (this.data.height === node.height) {
50973                 // split root if trees have the same height
50974                 this._splitRoot(this.data, node);
50975
50976             } else {
50977                 if (this.data.height < node.height) {
50978                     // swap trees if inserted one is bigger
50979                     const tmpNode = this.data;
50980                     this.data = node;
50981                     node = tmpNode;
50982                 }
50983
50984                 // insert the small tree into the large tree at appropriate level
50985                 this._insert(node, this.data.height - node.height - 1, true);
50986             }
50987
50988             return this;
50989         }
50990
50991         insert(item) {
50992             if (item) this._insert(item, this.data.height - 1);
50993             return this;
50994         }
50995
50996         clear() {
50997             this.data = createNode([]);
50998             return this;
50999         }
51000
51001         remove(item, equalsFn) {
51002             if (!item) return this;
51003
51004             let node = this.data;
51005             const bbox = this.toBBox(item);
51006             const path = [];
51007             const indexes = [];
51008             let i, parent, goingUp;
51009
51010             // depth-first iterative tree traversal
51011             while (node || path.length) {
51012
51013                 if (!node) { // go up
51014                     node = path.pop();
51015                     parent = path[path.length - 1];
51016                     i = indexes.pop();
51017                     goingUp = true;
51018                 }
51019
51020                 if (node.leaf) { // check current node
51021                     const index = findItem(item, node.children, equalsFn);
51022
51023                     if (index !== -1) {
51024                         // item found, remove the item and condense tree upwards
51025                         node.children.splice(index, 1);
51026                         path.push(node);
51027                         this._condense(path);
51028                         return this;
51029                     }
51030                 }
51031
51032                 if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
51033                     path.push(node);
51034                     indexes.push(i);
51035                     i = 0;
51036                     parent = node;
51037                     node = node.children[0];
51038
51039                 } else if (parent) { // go right
51040                     i++;
51041                     node = parent.children[i];
51042                     goingUp = false;
51043
51044                 } else node = null; // nothing found
51045             }
51046
51047             return this;
51048         }
51049
51050         toBBox(item) { return item; }
51051
51052         compareMinX(a, b) { return a.minX - b.minX; }
51053         compareMinY(a, b) { return a.minY - b.minY; }
51054
51055         toJSON() { return this.data; }
51056
51057         fromJSON(data) {
51058             this.data = data;
51059             return this;
51060         }
51061
51062         _all(node, result) {
51063             const nodesToSearch = [];
51064             while (node) {
51065                 if (node.leaf) result.push(...node.children);
51066                 else nodesToSearch.push(...node.children);
51067
51068                 node = nodesToSearch.pop();
51069             }
51070             return result;
51071         }
51072
51073         _build(items, left, right, height) {
51074
51075             const N = right - left + 1;
51076             let M = this._maxEntries;
51077             let node;
51078
51079             if (N <= M) {
51080                 // reached leaf level; return leaf
51081                 node = createNode(items.slice(left, right + 1));
51082                 calcBBox(node, this.toBBox);
51083                 return node;
51084             }
51085
51086             if (!height) {
51087                 // target height of the bulk-loaded tree
51088                 height = Math.ceil(Math.log(N) / Math.log(M));
51089
51090                 // target number of root entries to maximize storage utilization
51091                 M = Math.ceil(N / Math.pow(M, height - 1));
51092             }
51093
51094             node = createNode([]);
51095             node.leaf = false;
51096             node.height = height;
51097
51098             // split the items into M mostly square tiles
51099
51100             const N2 = Math.ceil(N / M);
51101             const N1 = N2 * Math.ceil(Math.sqrt(M));
51102
51103             multiSelect(items, left, right, N1, this.compareMinX);
51104
51105             for (let i = left; i <= right; i += N1) {
51106
51107                 const right2 = Math.min(i + N1 - 1, right);
51108
51109                 multiSelect(items, i, right2, N2, this.compareMinY);
51110
51111                 for (let j = i; j <= right2; j += N2) {
51112
51113                     const right3 = Math.min(j + N2 - 1, right2);
51114
51115                     // pack each entry recursively
51116                     node.children.push(this._build(items, j, right3, height - 1));
51117                 }
51118             }
51119
51120             calcBBox(node, this.toBBox);
51121
51122             return node;
51123         }
51124
51125         _chooseSubtree(bbox, node, level, path) {
51126             while (true) {
51127                 path.push(node);
51128
51129                 if (node.leaf || path.length - 1 === level) break;
51130
51131                 let minArea = Infinity;
51132                 let minEnlargement = Infinity;
51133                 let targetNode;
51134
51135                 for (let i = 0; i < node.children.length; i++) {
51136                     const child = node.children[i];
51137                     const area = bboxArea(child);
51138                     const enlargement = enlargedArea(bbox, child) - area;
51139
51140                     // choose entry with the least area enlargement
51141                     if (enlargement < minEnlargement) {
51142                         minEnlargement = enlargement;
51143                         minArea = area < minArea ? area : minArea;
51144                         targetNode = child;
51145
51146                     } else if (enlargement === minEnlargement) {
51147                         // otherwise choose one with the smallest area
51148                         if (area < minArea) {
51149                             minArea = area;
51150                             targetNode = child;
51151                         }
51152                     }
51153                 }
51154
51155                 node = targetNode || node.children[0];
51156             }
51157
51158             return node;
51159         }
51160
51161         _insert(item, level, isNode) {
51162             const bbox = isNode ? item : this.toBBox(item);
51163             const insertPath = [];
51164
51165             // find the best node for accommodating the item, saving all nodes along the path too
51166             const node = this._chooseSubtree(bbox, this.data, level, insertPath);
51167
51168             // put the item into the node
51169             node.children.push(item);
51170             extend(node, bbox);
51171
51172             // split on node overflow; propagate upwards if necessary
51173             while (level >= 0) {
51174                 if (insertPath[level].children.length > this._maxEntries) {
51175                     this._split(insertPath, level);
51176                     level--;
51177                 } else break;
51178             }
51179
51180             // adjust bboxes along the insertion path
51181             this._adjustParentBBoxes(bbox, insertPath, level);
51182         }
51183
51184         // split overflowed node into two
51185         _split(insertPath, level) {
51186             const node = insertPath[level];
51187             const M = node.children.length;
51188             const m = this._minEntries;
51189
51190             this._chooseSplitAxis(node, m, M);
51191
51192             const splitIndex = this._chooseSplitIndex(node, m, M);
51193
51194             const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
51195             newNode.height = node.height;
51196             newNode.leaf = node.leaf;
51197
51198             calcBBox(node, this.toBBox);
51199             calcBBox(newNode, this.toBBox);
51200
51201             if (level) insertPath[level - 1].children.push(newNode);
51202             else this._splitRoot(node, newNode);
51203         }
51204
51205         _splitRoot(node, newNode) {
51206             // split root node
51207             this.data = createNode([node, newNode]);
51208             this.data.height = node.height + 1;
51209             this.data.leaf = false;
51210             calcBBox(this.data, this.toBBox);
51211         }
51212
51213         _chooseSplitIndex(node, m, M) {
51214             let index;
51215             let minOverlap = Infinity;
51216             let minArea = Infinity;
51217
51218             for (let i = m; i <= M - m; i++) {
51219                 const bbox1 = distBBox(node, 0, i, this.toBBox);
51220                 const bbox2 = distBBox(node, i, M, this.toBBox);
51221
51222                 const overlap = intersectionArea(bbox1, bbox2);
51223                 const area = bboxArea(bbox1) + bboxArea(bbox2);
51224
51225                 // choose distribution with minimum overlap
51226                 if (overlap < minOverlap) {
51227                     minOverlap = overlap;
51228                     index = i;
51229
51230                     minArea = area < minArea ? area : minArea;
51231
51232                 } else if (overlap === minOverlap) {
51233                     // otherwise choose distribution with minimum area
51234                     if (area < minArea) {
51235                         minArea = area;
51236                         index = i;
51237                     }
51238                 }
51239             }
51240
51241             return index || M - m;
51242         }
51243
51244         // sorts node children by the best axis for split
51245         _chooseSplitAxis(node, m, M) {
51246             const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
51247             const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
51248             const xMargin = this._allDistMargin(node, m, M, compareMinX);
51249             const yMargin = this._allDistMargin(node, m, M, compareMinY);
51250
51251             // if total distributions margin value is minimal for x, sort by minX,
51252             // otherwise it's already sorted by minY
51253             if (xMargin < yMargin) node.children.sort(compareMinX);
51254         }
51255
51256         // total margin of all possible split distributions where each node is at least m full
51257         _allDistMargin(node, m, M, compare) {
51258             node.children.sort(compare);
51259
51260             const toBBox = this.toBBox;
51261             const leftBBox = distBBox(node, 0, m, toBBox);
51262             const rightBBox = distBBox(node, M - m, M, toBBox);
51263             let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
51264
51265             for (let i = m; i < M - m; i++) {
51266                 const child = node.children[i];
51267                 extend(leftBBox, node.leaf ? toBBox(child) : child);
51268                 margin += bboxMargin(leftBBox);
51269             }
51270
51271             for (let i = M - m - 1; i >= m; i--) {
51272                 const child = node.children[i];
51273                 extend(rightBBox, node.leaf ? toBBox(child) : child);
51274                 margin += bboxMargin(rightBBox);
51275             }
51276
51277             return margin;
51278         }
51279
51280         _adjustParentBBoxes(bbox, path, level) {
51281             // adjust bboxes along the given tree path
51282             for (let i = level; i >= 0; i--) {
51283                 extend(path[i], bbox);
51284             }
51285         }
51286
51287         _condense(path) {
51288             // go through the path, removing empty nodes and updating bboxes
51289             for (let i = path.length - 1, siblings; i >= 0; i--) {
51290                 if (path[i].children.length === 0) {
51291                     if (i > 0) {
51292                         siblings = path[i - 1].children;
51293                         siblings.splice(siblings.indexOf(path[i]), 1);
51294
51295                     } else this.clear();
51296
51297                 } else calcBBox(path[i], this.toBBox);
51298             }
51299         }
51300     }
51301
51302     function findItem(item, items, equalsFn) {
51303         if (!equalsFn) return items.indexOf(item);
51304
51305         for (let i = 0; i < items.length; i++) {
51306             if (equalsFn(item, items[i])) return i;
51307         }
51308         return -1;
51309     }
51310
51311     // calculate node's bbox from bboxes of its children
51312     function calcBBox(node, toBBox) {
51313         distBBox(node, 0, node.children.length, toBBox, node);
51314     }
51315
51316     // min bounding rectangle of node children from k to p-1
51317     function distBBox(node, k, p, toBBox, destNode) {
51318         if (!destNode) destNode = createNode(null);
51319         destNode.minX = Infinity;
51320         destNode.minY = Infinity;
51321         destNode.maxX = -Infinity;
51322         destNode.maxY = -Infinity;
51323
51324         for (let i = k; i < p; i++) {
51325             const child = node.children[i];
51326             extend(destNode, node.leaf ? toBBox(child) : child);
51327         }
51328
51329         return destNode;
51330     }
51331
51332     function extend(a, b) {
51333         a.minX = Math.min(a.minX, b.minX);
51334         a.minY = Math.min(a.minY, b.minY);
51335         a.maxX = Math.max(a.maxX, b.maxX);
51336         a.maxY = Math.max(a.maxY, b.maxY);
51337         return a;
51338     }
51339
51340     function compareNodeMinX(a, b) { return a.minX - b.minX; }
51341     function compareNodeMinY(a, b) { return a.minY - b.minY; }
51342
51343     function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
51344     function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
51345
51346     function enlargedArea(a, b) {
51347         return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
51348                (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
51349     }
51350
51351     function intersectionArea(a, b) {
51352         const minX = Math.max(a.minX, b.minX);
51353         const minY = Math.max(a.minY, b.minY);
51354         const maxX = Math.min(a.maxX, b.maxX);
51355         const maxY = Math.min(a.maxY, b.maxY);
51356
51357         return Math.max(0, maxX - minX) *
51358                Math.max(0, maxY - minY);
51359     }
51360
51361     function contains(a, b) {
51362         return a.minX <= b.minX &&
51363                a.minY <= b.minY &&
51364                b.maxX <= a.maxX &&
51365                b.maxY <= a.maxY;
51366     }
51367
51368     function intersects$1(a, b) {
51369         return b.minX <= a.maxX &&
51370                b.minY <= a.maxY &&
51371                b.maxX >= a.minX &&
51372                b.maxY >= a.minY;
51373     }
51374
51375     function createNode(children) {
51376         return {
51377             children,
51378             height: 1,
51379             leaf: true,
51380             minX: Infinity,
51381             minY: Infinity,
51382             maxX: -Infinity,
51383             maxY: -Infinity
51384         };
51385     }
51386
51387     // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
51388     // combines selection algorithm with binary divide & conquer approach
51389
51390     function multiSelect(arr, left, right, n, compare) {
51391         const stack = [left, right];
51392
51393         while (stack.length) {
51394             right = stack.pop();
51395             left = stack.pop();
51396
51397             if (right - left <= n) continue;
51398
51399             const mid = left + Math.ceil((right - left) / n / 2) * n;
51400             quickselect(arr, mid, left, right, compare);
51401
51402             stack.push(left, mid, mid, right);
51403         }
51404     }
51405
51406     class GeoRBush extends RBush {
51407         compareMinX(a, b) {
51408             return a.lng - b.lng;
51409         }
51410         compareMinY(a, b) {
51411             return a.lat - b.lat;
51412         }
51413         toBBox(item) {
51414             return {
51415                 minX: item.lng,
51416                 minY: item.lat,
51417                 maxX: item.lng,
51418                 maxY: item.lat,
51419             };
51420         }
51421     }
51422
51423     /*
51424      * Copyright (C) 2008 Apple Inc. All Rights Reserved.
51425      *
51426      * Redistribution and use in source and binary forms, with or without
51427      * modification, are permitted provided that the following conditions
51428      * are met:
51429      * 1. Redistributions of source code must retain the above copyright
51430      *    notice, this list of conditions and the following disclaimer.
51431      * 2. Redistributions in binary form must reproduce the above copyright
51432      *    notice, this list of conditions and the following disclaimer in the
51433      *    documentation and/or other materials provided with the distribution.
51434      *
51435      * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
51436      * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51437      * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51438      * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
51439      * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
51440      * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51441      * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51442      * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
51443      * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51444      * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51445      * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51446      *
51447      * Ported from Webkit
51448      * http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h
51449      */
51450     var unitbezier = UnitBezier;
51451
51452     function UnitBezier(p1x, p1y, p2x, p2y) {
51453         // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
51454         this.cx = 3.0 * p1x;
51455         this.bx = 3.0 * (p2x - p1x) - this.cx;
51456         this.ax = 1.0 - this.cx - this.bx;
51457
51458         this.cy = 3.0 * p1y;
51459         this.by = 3.0 * (p2y - p1y) - this.cy;
51460         this.ay = 1.0 - this.cy - this.by;
51461
51462         this.p1x = p1x;
51463         this.p1y = p2y;
51464         this.p2x = p2x;
51465         this.p2y = p2y;
51466     }
51467
51468     UnitBezier.prototype.sampleCurveX = function(t) {
51469         // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
51470         return ((this.ax * t + this.bx) * t + this.cx) * t;
51471     };
51472
51473     UnitBezier.prototype.sampleCurveY = function(t) {
51474         return ((this.ay * t + this.by) * t + this.cy) * t;
51475     };
51476
51477     UnitBezier.prototype.sampleCurveDerivativeX = function(t) {
51478         return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
51479     };
51480
51481     UnitBezier.prototype.solveCurveX = function(x, epsilon) {
51482         if (typeof epsilon === 'undefined') epsilon = 1e-6;
51483
51484         var t0, t1, t2, x2, i;
51485
51486         // First try a few iterations of Newton's method -- normally very fast.
51487         for (t2 = x, i = 0; i < 8; i++) {
51488
51489             x2 = this.sampleCurveX(t2) - x;
51490             if (Math.abs(x2) < epsilon) return t2;
51491
51492             var d2 = this.sampleCurveDerivativeX(t2);
51493             if (Math.abs(d2) < 1e-6) break;
51494
51495             t2 = t2 - x2 / d2;
51496         }
51497
51498         // Fall back to the bisection method for reliability.
51499         t0 = 0.0;
51500         t1 = 1.0;
51501         t2 = x;
51502
51503         if (t2 < t0) return t0;
51504         if (t2 > t1) return t1;
51505
51506         while (t0 < t1) {
51507
51508             x2 = this.sampleCurveX(t2);
51509             if (Math.abs(x2 - x) < epsilon) return t2;
51510
51511             if (x > x2) {
51512                 t0 = t2;
51513             } else {
51514                 t1 = t2;
51515             }
51516
51517             t2 = (t1 - t0) * 0.5 + t0;
51518         }
51519
51520         // Failure.
51521         return t2;
51522     };
51523
51524     UnitBezier.prototype.solve = function(x, epsilon) {
51525         return this.sampleCurveY(this.solveCurveX(x, epsilon));
51526     };
51527
51528     /**
51529      * Enumeration for transition mode
51530      * @enum {number}
51531      * @readonly
51532      * @description Modes for specifying how transitions
51533      * between images are performed.
51534      */
51535     exports.TransitionMode = void 0;
51536     (function (TransitionMode) {
51537         /**
51538          * Default transitions.
51539          *
51540          * @description The viewer dynamically determines
51541          * whether transitions should be performed with or
51542          * without motion and blending for each transition
51543          * based on the underlying data.
51544          */
51545         TransitionMode[TransitionMode["Default"] = 0] = "Default";
51546         /**
51547          * Instantaneous transitions.
51548          *
51549          * @description All transitions are performed
51550          * without motion or blending.
51551          */
51552         TransitionMode[TransitionMode["Instantaneous"] = 1] = "Instantaneous";
51553     })(exports.TransitionMode || (exports.TransitionMode = {}));
51554
51555     /**
51556      * @class Camera
51557      *
51558      * @classdesc Holds information about a camera.
51559      */
51560     class Camera {
51561         /**
51562          * Create a new camera instance.
51563          * @param {Transform} [transform] - Optional transform instance.
51564          */
51565         constructor(transform) {
51566             if (transform != null) {
51567                 this._position = new Vector3().fromArray(transform.unprojectSfM([0, 0], 0));
51568                 this._lookat = new Vector3().fromArray(transform.unprojectSfM([0, 0], 10));
51569                 this._up = transform.upVector();
51570                 this._focal = this._getFocal(transform);
51571             }
51572             else {
51573                 this._position = new Vector3(0, 0, 0);
51574                 this._lookat = new Vector3(1, 0, 0);
51575                 this._up = new Vector3(0, 0, 1);
51576                 this._focal = 1;
51577             }
51578         }
51579         /**
51580          * Get position.
51581          * @returns {THREE.Vector3} The position vector.
51582          */
51583         get position() {
51584             return this._position;
51585         }
51586         /**
51587          * Get lookat.
51588          * @returns {THREE.Vector3} The lookat vector.
51589          */
51590         get lookat() {
51591             return this._lookat;
51592         }
51593         /**
51594          * Get up.
51595          * @returns {THREE.Vector3} The up vector.
51596          */
51597         get up() {
51598             return this._up;
51599         }
51600         /**
51601          * Get focal.
51602          * @returns {number} The focal length.
51603          */
51604         get focal() {
51605             return this._focal;
51606         }
51607         /**
51608          * Set focal.
51609          */
51610         set focal(value) {
51611             this._focal = value;
51612         }
51613         /**
51614          * Update this camera to the linearly interpolated value of two other cameras.
51615          *
51616          * @param {Camera} a - First camera.
51617          * @param {Camera} b - Second camera.
51618          * @param {number} alpha - Interpolation value on the interval [0, 1].
51619          */
51620         lerpCameras(a, b, alpha) {
51621             this._position.subVectors(b.position, a.position).multiplyScalar(alpha).add(a.position);
51622             this._lookat.subVectors(b.lookat, a.lookat).multiplyScalar(alpha).add(a.lookat);
51623             this._up.subVectors(b.up, a.up).multiplyScalar(alpha).add(a.up);
51624             this._focal = (1 - alpha) * a.focal + alpha * b.focal;
51625         }
51626         /**
51627          * Copy the properties of another camera to this camera.
51628          *
51629          * @param {Camera} other - Another camera.
51630          */
51631         copy(other) {
51632             this._position.copy(other.position);
51633             this._lookat.copy(other.lookat);
51634             this._up.copy(other.up);
51635             this._focal = other.focal;
51636         }
51637         /**
51638          * Clone this camera.
51639          *
51640          * @returns {Camera} A camera with cloned properties equal to this camera.
51641          */
51642         clone() {
51643             let camera = new Camera();
51644             camera.position.copy(this._position);
51645             camera.lookat.copy(this._lookat);
51646             camera.up.copy(this._up);
51647             camera.focal = this._focal;
51648             return camera;
51649         }
51650         /**
51651          * Determine the distance between this camera and another camera.
51652          *
51653          * @param {Camera} other - Another camera.
51654          * @returns {number} The distance between the cameras.
51655          */
51656         diff(other) {
51657             let pd = this._position.distanceToSquared(other.position);
51658             let ld = this._lookat.distanceToSquared(other.lookat);
51659             let ud = this._up.distanceToSquared(other.up);
51660             let fd = 100 * Math.abs(this._focal - other.focal);
51661             return Math.max(pd, ld, ud, fd);
51662         }
51663         /**
51664          * Get the focal length based on the transform.
51665          *
51666          * @description Returns the focal length corresponding
51667          * to a 90 degree field of view for spherical
51668          * transforms.
51669          *
51670          * Returns the transform focal length for other
51671          * projection types.
51672          *
51673          * @returns {number} Focal length.
51674          */
51675         _getFocal(transform) {
51676             if (!isSpherical(transform.cameraType)) {
51677                 return transform.focal;
51678             }
51679             return 0.5 / Math.tan(Math.PI / 2);
51680         }
51681     }
51682
51683     const EPSILON = 1e-8;
51684     /**
51685      * @class Transform
51686      *
51687      * @classdesc Class used for calculating coordinate transformations
51688      * and projections.
51689      */
51690     class Transform {
51691         /**
51692          * Create a new transform instance.
51693          * @param {number} orientation - Image orientation.
51694          * @param {number} width - Image height.
51695          * @param {number} height - Image width.
51696          * @param {number} focal - Focal length.
51697          * @param {number} scale - Atomic scale.
51698          * @param {Array<number>} rotation - Rotation vector in three dimensions.
51699          * @param {Array<number>} translation - Translation vector in three dimensions.
51700          * @param {HTMLImageElement} image - Image for fallback size calculations.
51701          */
51702         constructor(orientation, width, height, scale, rotation, translation, image, textureScale, cameraParameters, cameraType) {
51703             this._orientation = this._getValue(orientation, 1);
51704             let imageWidth = image != null ? image.width : 4;
51705             let imageHeight = image != null ? image.height : 3;
51706             let keepOrientation = this._orientation < 5;
51707             this._width = this._getValue(width, keepOrientation ? imageWidth : imageHeight);
51708             this._height = this._getValue(height, keepOrientation ? imageHeight : imageWidth);
51709             this._basicAspect = keepOrientation ?
51710                 this._width / this._height :
51711                 this._height / this._width;
51712             this._basicWidth = keepOrientation ? width : height;
51713             this._basicHeight = keepOrientation ? height : width;
51714             const parameters = this._getCameraParameters(cameraParameters, cameraType);
51715             const focal = parameters[0];
51716             const ck1 = parameters[1];
51717             const ck2 = parameters[2];
51718             this._focal = this._getValue(focal, 1);
51719             this._scale = this._getValue(scale, 0);
51720             this._worldToCamera = this.createWorldToCamera(rotation, translation);
51721             this._worldToCameraInverse = new Matrix4()
51722                 .copy(this._worldToCamera)
51723                 .invert();
51724             this._scaledWorldToCamera =
51725                 this._createScaledWorldToCamera(this._worldToCamera, this._scale);
51726             this._scaledWorldToCameraInverse = new Matrix4()
51727                 .copy(this._scaledWorldToCamera)
51728                 .invert();
51729             this._basicWorldToCamera = this._createBasicWorldToCamera(this._worldToCamera, orientation);
51730             this._textureScale = !!textureScale ? textureScale : [1, 1];
51731             this._ck1 = !!ck1 ? ck1 : 0;
51732             this._ck2 = !!ck2 ? ck2 : 0;
51733             this._cameraType = !!cameraType ?
51734                 cameraType :
51735                 "perspective";
51736             this._radialPeak = this._getRadialPeak(this._ck1, this._ck2);
51737         }
51738         get ck1() {
51739             return this._ck1;
51740         }
51741         get ck2() {
51742             return this._ck2;
51743         }
51744         get cameraType() {
51745             return this._cameraType;
51746         }
51747         /**
51748          * Get basic aspect.
51749          * @returns {number} The orientation adjusted aspect ratio.
51750          */
51751         get basicAspect() {
51752             return this._basicAspect;
51753         }
51754         /**
51755          * Get basic height.
51756          *
51757          * @description Does not fall back to image image height but
51758          * uses original value from API so can be faulty.
51759          *
51760          * @returns {number} The height of the basic version image
51761          * (adjusted for orientation).
51762          */
51763         get basicHeight() {
51764             return this._basicHeight;
51765         }
51766         get basicRt() {
51767             return this._basicWorldToCamera;
51768         }
51769         /**
51770          * Get basic width.
51771          *
51772          * @description Does not fall back to image image width but
51773          * uses original value from API so can be faulty.
51774          *
51775          * @returns {number} The width of the basic version image
51776          * (adjusted for orientation).
51777          */
51778         get basicWidth() {
51779             return this._basicWidth;
51780         }
51781         /**
51782          * Get focal.
51783          * @returns {number} The image focal length.
51784          */
51785         get focal() {
51786             return this._focal;
51787         }
51788         /**
51789          * Get height.
51790          *
51791          * @description Falls back to the image image height if
51792          * the API data is faulty.
51793          *
51794          * @returns {number} The orientation adjusted image height.
51795          */
51796         get height() {
51797             return this._height;
51798         }
51799         /**
51800          * Get orientation.
51801          * @returns {number} The image orientation.
51802          */
51803         get orientation() {
51804             return this._orientation;
51805         }
51806         /**
51807          * Get rt.
51808          * @returns {THREE.Matrix4} The extrinsic camera matrix.
51809          */
51810         get rt() {
51811             return this._worldToCamera;
51812         }
51813         /**
51814          * Get srt.
51815          * @returns {THREE.Matrix4} The scaled extrinsic camera matrix.
51816          */
51817         get srt() {
51818             return this._scaledWorldToCamera;
51819         }
51820         /**
51821          * Get srtInverse.
51822          * @returns {THREE.Matrix4} The scaled extrinsic camera matrix.
51823          */
51824         get srtInverse() {
51825             return this._scaledWorldToCameraInverse;
51826         }
51827         /**
51828          * Get scale.
51829          * @returns {number} The image atomic reconstruction scale.
51830          */
51831         get scale() {
51832             return this._scale;
51833         }
51834         /**
51835          * Get has valid scale.
51836          * @returns {boolean} Value indicating if the scale of the transform is valid.
51837          */
51838         get hasValidScale() {
51839             return this._scale > 1e-2 && this._scale < 50;
51840         }
51841         /**
51842          * Get radial peak.
51843          * @returns {number} Value indicating the radius where the radial
51844          * undistortion function peaks.
51845          */
51846         get radialPeak() {
51847             return this._radialPeak;
51848         }
51849         /**
51850          * Get width.
51851          *
51852          * @description Falls back to the image image width if
51853          * the API data is faulty.
51854          *
51855          * @returns {number} The orientation adjusted image width.
51856          */
51857         get width() {
51858             return this._width;
51859         }
51860         /**
51861          * Calculate the up vector for the image transform.
51862          *
51863          * @returns {THREE.Vector3} Normalized and orientation adjusted up vector.
51864          */
51865         upVector() {
51866             let rte = this._worldToCamera.elements;
51867             switch (this._orientation) {
51868                 case 1:
51869                     return new Vector3(-rte[1], -rte[5], -rte[9]);
51870                 case 3:
51871                     return new Vector3(rte[1], rte[5], rte[9]);
51872                 case 6:
51873                     return new Vector3(-rte[0], -rte[4], -rte[8]);
51874                 case 8:
51875                     return new Vector3(rte[0], rte[4], rte[8]);
51876                 default:
51877                     return new Vector3(-rte[1], -rte[5], -rte[9]);
51878             }
51879         }
51880         /**
51881          * Calculate projector matrix for projecting 3D points to texture map
51882          * coordinates (u and v).
51883          *
51884          * @returns {THREE.Matrix4} Projection matrix for 3D point to texture
51885          * map coordinate calculations.
51886          */
51887         projectorMatrix() {
51888             let projector = this._normalizedToTextureMatrix();
51889             let f = this._focal;
51890             let projection = new Matrix4().set(f, 0, 0, 0, 0, f, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
51891             projector.multiply(projection);
51892             projector.multiply(this._worldToCamera);
51893             return projector;
51894         }
51895         /**
51896          * Project 3D world coordinates to basic coordinates.
51897          *
51898          * @param {Array<number>} point3d - 3D world coordinates.
51899          * @return {Array<number>} 2D basic coordinates.
51900          */
51901         projectBasic(point3d) {
51902             let sfm = this.projectSfM(point3d);
51903             return this._sfmToBasic(sfm);
51904         }
51905         /**
51906          * Unproject basic coordinates to 3D world coordinates.
51907          *
51908          * @param {Array<number>} basic - 2D basic coordinates.
51909          * @param {Array<number>} distance - Distance to unproject from camera center.
51910          * @param {boolean} [depth] - Treat the distance value as depth from camera center.
51911          *                            Only applicable for perspective images. Will be
51912          *                            ignored for spherical.
51913          * @returns {Array<number>} Unprojected 3D world coordinates.
51914          */
51915         unprojectBasic(basic, distance, depth) {
51916             let sfm = this._basicToSfm(basic);
51917             return this.unprojectSfM(sfm, distance, depth);
51918         }
51919         /**
51920          * Project 3D world coordinates to SfM coordinates.
51921          *
51922          * @param {Array<number>} point3d - 3D world coordinates.
51923          * @return {Array<number>} 2D SfM coordinates.
51924          */
51925         projectSfM(point3d) {
51926             let v = new Vector4(point3d[0], point3d[1], point3d[2], 1);
51927             v.applyMatrix4(this._worldToCamera);
51928             return this._bearingToSfm([v.x, v.y, v.z]);
51929         }
51930         /**
51931          * Unproject SfM coordinates to a 3D world coordinates.
51932          *
51933          * @param {Array<number>} sfm - 2D SfM coordinates.
51934          * @param {Array<number>} distance - Distance to unproject
51935          * from camera center.
51936          * @param {boolean} [depth] - Treat the distance value as
51937          * depth from camera center. Only applicable for perspective
51938          * images. Will be ignored for spherical.
51939          * @returns {Array<number>} Unprojected 3D world coordinates.
51940          */
51941         unprojectSfM(sfm, distance, depth) {
51942             const bearing = this._sfmToBearing(sfm);
51943             const unprojectedCamera = depth && !isSpherical(this._cameraType) ?
51944                 new Vector4(distance * bearing[0] / bearing[2], distance * bearing[1] / bearing[2], distance, 1) :
51945                 new Vector4(distance * bearing[0], distance * bearing[1], distance * bearing[2], 1);
51946             const unprojectedWorld = unprojectedCamera
51947                 .applyMatrix4(this._worldToCameraInverse);
51948             return [
51949                 unprojectedWorld.x / unprojectedWorld.w,
51950                 unprojectedWorld.y / unprojectedWorld.w,
51951                 unprojectedWorld.z / unprojectedWorld.w,
51952             ];
51953         }
51954         /**
51955          * Transform SfM coordinates to bearing vector (3D cartesian
51956          * coordinates on the unit sphere).
51957          *
51958          * @param {Array<number>} sfm - 2D SfM coordinates.
51959          * @returns {Array<number>} Bearing vector (3D cartesian coordinates
51960          * on the unit sphere).
51961          */
51962         _sfmToBearing(sfm) {
51963             if (isSpherical(this._cameraType)) {
51964                 let lng = sfm[0] * 2 * Math.PI;
51965                 let lat = -sfm[1] * 2 * Math.PI;
51966                 let x = Math.cos(lat) * Math.sin(lng);
51967                 let y = -Math.sin(lat);
51968                 let z = Math.cos(lat) * Math.cos(lng);
51969                 return [x, y, z];
51970             }
51971             else if (isFisheye(this._cameraType)) {
51972                 let [dxn, dyn] = [sfm[0] / this._focal, sfm[1] / this._focal];
51973                 const dTheta = Math.sqrt(dxn * dxn + dyn * dyn);
51974                 let d = this._distortionFromDistortedRadius(dTheta, this._ck1, this._ck2, this._radialPeak);
51975                 let theta = dTheta / d;
51976                 let z = Math.cos(theta);
51977                 let r = Math.sin(theta);
51978                 const denomTheta = dTheta > EPSILON ? 1 / dTheta : 1;
51979                 let x = r * dxn * denomTheta;
51980                 let y = r * dyn * denomTheta;
51981                 return [x, y, z];
51982             }
51983             else {
51984                 let [dxn, dyn] = [sfm[0] / this._focal, sfm[1] / this._focal];
51985                 const dr = Math.sqrt(dxn * dxn + dyn * dyn);
51986                 let d = this._distortionFromDistortedRadius(dr, this._ck1, this._ck2, this._radialPeak);
51987                 const xn = dxn / d;
51988                 const yn = dyn / d;
51989                 let v = new Vector3(xn, yn, 1);
51990                 v.normalize();
51991                 return [v.x, v.y, v.z];
51992             }
51993         }
51994         /** Compute distortion given the distorted radius.
51995          *
51996          *  Solves for d in the equation
51997          *    y = d(x, k1, k2) * x
51998          * given the distorted radius, y.
51999          */
52000         _distortionFromDistortedRadius(distortedRadius, k1, k2, radialPeak) {
52001             let d = 1.0;
52002             for (let i = 0; i < 10; i++) {
52003                 let radius = distortedRadius / d;
52004                 if (radius > radialPeak) {
52005                     radius = radialPeak;
52006                 }
52007                 d = 1 + k1 * Math.pow(radius, 2) + k2 * Math.pow(radius, 4);
52008             }
52009             return d;
52010         }
52011         /**
52012          * Transform bearing vector (3D cartesian coordiantes on the unit sphere) to
52013          * SfM coordinates.
52014          *
52015          * @param {Array<number>} bearing - Bearing vector (3D cartesian coordinates on the
52016          * unit sphere).
52017          * @returns {Array<number>} 2D SfM coordinates.
52018          */
52019         _bearingToSfm(bearing) {
52020             if (isSpherical(this._cameraType)) {
52021                 let x = bearing[0];
52022                 let y = bearing[1];
52023                 let z = bearing[2];
52024                 let lng = Math.atan2(x, z);
52025                 let lat = Math.atan2(-y, Math.sqrt(x * x + z * z));
52026                 return [lng / (2 * Math.PI), -lat / (2 * Math.PI)];
52027             }
52028             else if (isFisheye(this._cameraType)) {
52029                 if (bearing[2] > 0) {
52030                     const [x, y, z] = bearing;
52031                     const r = Math.sqrt(x * x + y * y);
52032                     let theta = Math.atan2(r, z);
52033                     if (theta > this._radialPeak) {
52034                         theta = this._radialPeak;
52035                     }
52036                     const distortion = 1.0 + Math.pow(theta, 2) * (this._ck1 + Math.pow(theta, 2) * this._ck2);
52037                     const s = this._focal * distortion * theta / r;
52038                     return [s * x, s * y];
52039                 }
52040                 else {
52041                     return [
52042                         bearing[0] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
52043                         bearing[1] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
52044                     ];
52045                 }
52046             }
52047             else {
52048                 if (bearing[2] > 0) {
52049                     let [xn, yn] = [bearing[0] / bearing[2], bearing[1] / bearing[2]];
52050                     let r2 = xn * xn + yn * yn;
52051                     const rp2 = Math.pow(this._radialPeak, 2);
52052                     if (r2 > rp2) {
52053                         r2 = rp2;
52054                     }
52055                     const d = 1 + this._ck1 * r2 + this._ck2 * Math.pow(r2, 2);
52056                     return [
52057                         this._focal * d * xn,
52058                         this._focal * d * yn,
52059                     ];
52060                 }
52061                 else {
52062                     return [
52063                         bearing[0] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
52064                         bearing[1] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
52065                     ];
52066                 }
52067             }
52068         }
52069         /**
52070          * Convert basic coordinates to SfM coordinates.
52071          *
52072          * @param {Array<number>} basic - 2D basic coordinates.
52073          * @returns {Array<number>} 2D SfM coordinates.
52074          */
52075         _basicToSfm(basic) {
52076             let rotatedX;
52077             let rotatedY;
52078             switch (this._orientation) {
52079                 case 1:
52080                     rotatedX = basic[0];
52081                     rotatedY = basic[1];
52082                     break;
52083                 case 3:
52084                     rotatedX = 1 - basic[0];
52085                     rotatedY = 1 - basic[1];
52086                     break;
52087                 case 6:
52088                     rotatedX = basic[1];
52089                     rotatedY = 1 - basic[0];
52090                     break;
52091                 case 8:
52092                     rotatedX = 1 - basic[1];
52093                     rotatedY = basic[0];
52094                     break;
52095                 default:
52096                     rotatedX = basic[0];
52097                     rotatedY = basic[1];
52098                     break;
52099             }
52100             let w = this._width;
52101             let h = this._height;
52102             let s = Math.max(w, h);
52103             let sfmX = rotatedX * w / s - w / s / 2;
52104             let sfmY = rotatedY * h / s - h / s / 2;
52105             return [sfmX, sfmY];
52106         }
52107         /**
52108          * Convert SfM coordinates to basic coordinates.
52109          *
52110          * @param {Array<number>} sfm - 2D SfM coordinates.
52111          * @returns {Array<number>} 2D basic coordinates.
52112          */
52113         _sfmToBasic(sfm) {
52114             let w = this._width;
52115             let h = this._height;
52116             let s = Math.max(w, h);
52117             let rotatedX = (sfm[0] + w / s / 2) / w * s;
52118             let rotatedY = (sfm[1] + h / s / 2) / h * s;
52119             let basicX;
52120             let basicY;
52121             switch (this._orientation) {
52122                 case 1:
52123                     basicX = rotatedX;
52124                     basicY = rotatedY;
52125                     break;
52126                 case 3:
52127                     basicX = 1 - rotatedX;
52128                     basicY = 1 - rotatedY;
52129                     break;
52130                 case 6:
52131                     basicX = 1 - rotatedY;
52132                     basicY = rotatedX;
52133                     break;
52134                 case 8:
52135                     basicX = rotatedY;
52136                     basicY = 1 - rotatedX;
52137                     break;
52138                 default:
52139                     basicX = rotatedX;
52140                     basicY = rotatedY;
52141                     break;
52142             }
52143             return [basicX, basicY];
52144         }
52145         /**
52146          * Checks a value and returns it if it exists and is larger than 0.
52147          * Fallbacks if it is null.
52148          *
52149          * @param {number} value - Value to check.
52150          * @param {number} fallback - Value to fall back to.
52151          * @returns {number} The value or its fallback value if it is not defined or negative.
52152          */
52153         _getValue(value, fallback) {
52154             return value != null && value > 0 ? value : fallback;
52155         }
52156         _getCameraParameters(value, cameraType) {
52157             if (isSpherical(cameraType)) {
52158                 return [];
52159             }
52160             if (!value || value.length === 0) {
52161                 return [1, 0, 0];
52162             }
52163             const padding = 3 - value.length;
52164             if (padding <= 0) {
52165                 return value;
52166             }
52167             return value
52168                 .concat(new Array(padding)
52169                 .fill(0));
52170         }
52171         /**
52172          * Creates the extrinsic camera matrix [ R | t ].
52173          *
52174          * @param {Array<number>} rotation - Rotation vector in angle axis representation.
52175          * @param {Array<number>} translation - Translation vector.
52176          * @returns {THREE.Matrix4} Extrisic camera matrix.
52177          */
52178         createWorldToCamera(rotation, translation) {
52179             const axis = new Vector3(rotation[0], rotation[1], rotation[2]);
52180             const angle = axis.length();
52181             if (angle > 0) {
52182                 axis.normalize();
52183             }
52184             const worldToCamera = new Matrix4();
52185             worldToCamera.makeRotationAxis(axis, angle);
52186             worldToCamera.setPosition(new Vector3(translation[0], translation[1], translation[2]));
52187             return worldToCamera;
52188         }
52189         /**
52190          * Calculates the scaled extrinsic camera matrix scale * [ R | t ].
52191          *
52192          * @param {THREE.Matrix4} worldToCamera - Extrisic camera matrix.
52193          * @param {number} scale - Scale factor.
52194          * @returns {THREE.Matrix4} Scaled extrisic camera matrix.
52195          */
52196         _createScaledWorldToCamera(worldToCamera, scale) {
52197             const scaledWorldToCamera = worldToCamera.clone();
52198             const elements = scaledWorldToCamera.elements;
52199             elements[12] = scale * elements[12];
52200             elements[13] = scale * elements[13];
52201             elements[14] = scale * elements[14];
52202             scaledWorldToCamera.scale(new Vector3(scale, scale, scale));
52203             return scaledWorldToCamera;
52204         }
52205         _createBasicWorldToCamera(rt, orientation) {
52206             const axis = new Vector3(0, 0, 1);
52207             let angle = 0;
52208             switch (orientation) {
52209                 case 3:
52210                     angle = Math.PI;
52211                     break;
52212                 case 6:
52213                     angle = Math.PI / 2;
52214                     break;
52215                 case 8:
52216                     angle = 3 * Math.PI / 2;
52217                     break;
52218             }
52219             return new Matrix4()
52220                 .makeRotationAxis(axis, angle)
52221                 .multiply(rt);
52222         }
52223         _getRadialPeak(k1, k2) {
52224             const a = 5 * k2;
52225             const b = 3 * k1;
52226             const c = 1;
52227             const d = Math.pow(b, 2) - 4 * a * c;
52228             if (d < 0) {
52229                 return undefined;
52230             }
52231             const root1 = (-b - Math.sqrt(d)) / 2 / a;
52232             const root2 = (-b + Math.sqrt(d)) / 2 / a;
52233             const minRoot = Math.min(root1, root2);
52234             const maxRoot = Math.max(root1, root2);
52235             return minRoot > 0 ?
52236                 Math.sqrt(minRoot) :
52237                 maxRoot > 0 ?
52238                     Math.sqrt(maxRoot) :
52239                     undefined;
52240         }
52241         /**
52242          * Calculate a transformation matrix from normalized coordinates for
52243          * texture map coordinates.
52244          *
52245          * @returns {THREE.Matrix4} Normalized coordinates to texture map
52246          * coordinates transformation matrix.
52247          */
52248         _normalizedToTextureMatrix() {
52249             const size = Math.max(this._width, this._height);
52250             const scaleX = this._orientation < 5 ? this._textureScale[0] : this._textureScale[1];
52251             const scaleY = this._orientation < 5 ? this._textureScale[1] : this._textureScale[0];
52252             const w = size / this._width * scaleX;
52253             const h = size / this._height * scaleY;
52254             switch (this._orientation) {
52255                 case 1:
52256                     return new Matrix4().set(w, 0, 0, 0.5, 0, -h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
52257                 case 3:
52258                     return new Matrix4().set(-w, 0, 0, 0.5, 0, h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
52259                 case 6:
52260                     return new Matrix4().set(0, -h, 0, 0.5, -w, 0, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
52261                 case 8:
52262                     return new Matrix4().set(0, h, 0, 0.5, w, 0, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
52263                 default:
52264                     return new Matrix4().set(w, 0, 0, 0.5, 0, -h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
52265             }
52266         }
52267     }
52268
52269     class StateBase {
52270         constructor(state) {
52271             this._spatial = new Spatial();
52272             this._referenceThreshold = 0.01;
52273             this._transitionMode = state.transitionMode;
52274             this._reference = state.reference;
52275             this._alpha = state.alpha;
52276             this._camera = state.camera.clone();
52277             this._zoom = state.zoom;
52278             this._currentIndex = state.currentIndex;
52279             this._trajectory = state.trajectory.slice();
52280             this._trajectoryTransforms = [];
52281             this._trajectoryCameras = [];
52282             for (let image of this._trajectory) {
52283                 let translation = this._imageToTranslation(image, this._reference);
52284                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
52285                 this._trajectoryTransforms.push(transform);
52286                 this._trajectoryCameras.push(new Camera(transform));
52287             }
52288             this._currentImage = this._trajectory.length > 0 ?
52289                 this._trajectory[this._currentIndex] :
52290                 null;
52291             this._previousImage = this._trajectory.length > 1 && this.currentIndex > 0 ?
52292                 this._trajectory[this._currentIndex - 1] :
52293                 null;
52294             this._currentCamera = this._trajectoryCameras.length > 0 ?
52295                 this._trajectoryCameras[this._currentIndex].clone() :
52296                 new Camera();
52297             this._previousCamera = this._trajectoryCameras.length > 1 && this.currentIndex > 0 ?
52298                 this._trajectoryCameras[this._currentIndex - 1].clone() :
52299                 this._currentCamera.clone();
52300         }
52301         get reference() {
52302             return this._reference;
52303         }
52304         get alpha() {
52305             return this._getAlpha();
52306         }
52307         get camera() {
52308             return this._camera;
52309         }
52310         get zoom() {
52311             return this._zoom;
52312         }
52313         get trajectory() {
52314             return this._trajectory;
52315         }
52316         get currentIndex() {
52317             return this._currentIndex;
52318         }
52319         get currentImage() {
52320             return this._currentImage;
52321         }
52322         get previousImage() {
52323             return this._previousImage;
52324         }
52325         get currentCamera() {
52326             return this._currentCamera;
52327         }
52328         get currentTransform() {
52329             return this._trajectoryTransforms.length > 0 ?
52330                 this._trajectoryTransforms[this.currentIndex] : null;
52331         }
52332         get previousTransform() {
52333             return this._trajectoryTransforms.length > 1 && this.currentIndex > 0 ?
52334                 this._trajectoryTransforms[this.currentIndex - 1] : null;
52335         }
52336         get motionless() {
52337             return this._motionless;
52338         }
52339         get transitionMode() {
52340             return this._transitionMode;
52341         }
52342         move(delta) { }
52343         moveTo(position) { }
52344         rotate(delta) { }
52345         rotateUnbounded(delta) { }
52346         rotateWithoutInertia(delta) { }
52347         rotateBasic(basicRotation) { }
52348         rotateBasicUnbounded(basicRotation) { }
52349         rotateBasicWithoutInertia(basicRotation) { }
52350         rotateToBasic(basic) { }
52351         setSpeed(speed) { }
52352         zoomIn(delta, reference) { }
52353         update(fps) { }
52354         setCenter(center) { }
52355         setZoom(zoom) { }
52356         dolly(delta) { }
52357         orbit(rotation) { }
52358         setViewMatrix(matrix) { }
52359         truck(direction) { }
52360         append(images) {
52361             if (images.length < 1) {
52362                 throw Error("Trajectory can not be empty");
52363             }
52364             if (this._currentIndex < 0) {
52365                 this.set(images);
52366             }
52367             else {
52368                 this._trajectory = this._trajectory.concat(images);
52369                 this._appendToTrajectories(images);
52370             }
52371         }
52372         prepend(images) {
52373             if (images.length < 1) {
52374                 throw Error("Trajectory can not be empty");
52375             }
52376             this._trajectory = images.slice().concat(this._trajectory);
52377             this._currentIndex += images.length;
52378             this._setCurrentImage();
52379             let referenceReset = this._setReference(this._currentImage);
52380             if (referenceReset) {
52381                 this._setTrajectories();
52382             }
52383             else {
52384                 this._prependToTrajectories(images);
52385             }
52386             this._setCurrentCamera();
52387         }
52388         remove(n) {
52389             if (n < 0) {
52390                 throw Error("n must be a positive integer");
52391             }
52392             if (this._currentIndex - 1 < n) {
52393                 throw Error("Current and previous images can not be removed");
52394             }
52395             for (let i = 0; i < n; i++) {
52396                 this._trajectory.shift();
52397                 this._trajectoryTransforms.shift();
52398                 this._trajectoryCameras.shift();
52399                 this._currentIndex--;
52400             }
52401             this._setCurrentImage();
52402         }
52403         clearPrior() {
52404             if (this._currentIndex > 0) {
52405                 this.remove(this._currentIndex - 1);
52406             }
52407         }
52408         clear() {
52409             this.cut();
52410             if (this._currentIndex > 0) {
52411                 this.remove(this._currentIndex - 1);
52412             }
52413         }
52414         cut() {
52415             while (this._trajectory.length - 1 > this._currentIndex) {
52416                 this._trajectory.pop();
52417                 this._trajectoryTransforms.pop();
52418                 this._trajectoryCameras.pop();
52419             }
52420         }
52421         set(images) {
52422             this._setTrajectory(images);
52423             this._setCurrentImage();
52424             this._setReference(this._currentImage);
52425             this._setTrajectories();
52426             this._setCurrentCamera();
52427         }
52428         getCenter() {
52429             return this._currentImage != null ?
52430                 this.currentTransform.projectBasic(this._camera.lookat.toArray()) :
52431                 [0.5, 0.5];
52432         }
52433         setTransitionMode(mode) {
52434             this._transitionMode = mode;
52435         }
52436         _getAlpha() { return 1; }
52437         _setCurrent() {
52438             this._setCurrentImage();
52439             let referenceReset = this._setReference(this._currentImage);
52440             if (referenceReset) {
52441                 this._setTrajectories();
52442             }
52443             this._setCurrentCamera();
52444         }
52445         _setCurrentCamera() {
52446             this._currentCamera = this._trajectoryCameras[this._currentIndex].clone();
52447             this._previousCamera = this._currentIndex > 0 ?
52448                 this._trajectoryCameras[this._currentIndex - 1].clone() :
52449                 this._currentCamera.clone();
52450         }
52451         _motionlessTransition() {
52452             let imagesSet = this._currentImage != null && this._previousImage != null;
52453             return imagesSet && (this._transitionMode === exports.TransitionMode.Instantaneous || !(this._currentImage.merged &&
52454                 this._previousImage.merged &&
52455                 this._withinOriginalDistance() &&
52456                 this._sameConnectedComponent()));
52457         }
52458         _setReference(image) {
52459             // do not reset reference if image is within threshold distance
52460             if (Math.abs(image.lngLat.lat - this.reference.lat) < this._referenceThreshold &&
52461                 Math.abs(image.lngLat.lng - this.reference.lng) < this._referenceThreshold) {
52462                 return false;
52463             }
52464             // do not reset reference if previous image exist and transition is with motion
52465             if (this._previousImage != null && !this._motionlessTransition()) {
52466                 return false;
52467             }
52468             this._reference.lat = image.lngLat.lat;
52469             this._reference.lng = image.lngLat.lng;
52470             this._reference.alt = image.computedAltitude;
52471             return true;
52472         }
52473         _setCurrentImage() {
52474             this._currentImage = this._trajectory.length > 0 ?
52475                 this._trajectory[this._currentIndex] :
52476                 null;
52477             this._previousImage = this._currentIndex > 0 ?
52478                 this._trajectory[this._currentIndex - 1] :
52479                 null;
52480         }
52481         _setTrajectory(images) {
52482             if (images.length < 1) {
52483                 throw new ArgumentMapillaryError("Trajectory can not be empty");
52484             }
52485             if (this._currentImage != null) {
52486                 this._trajectory = [this._currentImage].concat(images);
52487                 this._currentIndex = 1;
52488             }
52489             else {
52490                 this._trajectory = images.slice();
52491                 this._currentIndex = 0;
52492             }
52493         }
52494         _setTrajectories() {
52495             this._trajectoryTransforms.length = 0;
52496             this._trajectoryCameras.length = 0;
52497             this._appendToTrajectories(this._trajectory);
52498         }
52499         _appendToTrajectories(images) {
52500             for (let image of images) {
52501                 if (!image.assetsCached) {
52502                     throw new ArgumentMapillaryError("Assets must be cached when image is added to trajectory");
52503                 }
52504                 let translation = this._imageToTranslation(image, this.reference);
52505                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
52506                 this._trajectoryTransforms.push(transform);
52507                 this._trajectoryCameras.push(new Camera(transform));
52508             }
52509         }
52510         _prependToTrajectories(images) {
52511             for (let image of images.reverse()) {
52512                 if (!image.assetsCached) {
52513                     throw new ArgumentMapillaryError("Assets must be cached when added to trajectory");
52514                 }
52515                 let translation = this._imageToTranslation(image, this.reference);
52516                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
52517                 this._trajectoryTransforms.unshift(transform);
52518                 this._trajectoryCameras.unshift(new Camera(transform));
52519             }
52520         }
52521         _imageToTranslation(image, reference) {
52522             return computeTranslation({ alt: image.computedAltitude, lat: image.lngLat.lat, lng: image.lngLat.lng }, image.rotation, reference);
52523         }
52524         _sameConnectedComponent() {
52525             let current = this._currentImage;
52526             let previous = this._previousImage;
52527             return !!current && !!previous &&
52528                 current.mergeId === previous.mergeId;
52529         }
52530         _withinOriginalDistance() {
52531             let current = this._currentImage;
52532             let previous = this._previousImage;
52533             if (!current || !previous) {
52534                 return true;
52535             }
52536             // 50 km/h moves 28m in 2s
52537             let distance = this._spatial.distanceFromLngLat(current.originalLngLat.lng, current.originalLngLat.lat, previous.originalLngLat.lng, previous.originalLngLat.lat);
52538             return distance < 25;
52539         }
52540     }
52541
52542     class EulerRotationDelta {
52543         constructor(phi, theta) {
52544             this._phi = phi;
52545             this._theta = theta;
52546         }
52547         get phi() {
52548             return this._phi;
52549         }
52550         set phi(value) {
52551             this._phi = value;
52552         }
52553         get theta() {
52554             return this._theta;
52555         }
52556         set theta(value) {
52557             this._theta = value;
52558         }
52559         get isZero() {
52560             return this._phi === 0 && this._theta === 0;
52561         }
52562         copy(delta) {
52563             this._phi = delta.phi;
52564             this._theta = delta.theta;
52565         }
52566         lerp(other, alpha) {
52567             this._phi = (1 - alpha) * this._phi + alpha * other.phi;
52568             this._theta = (1 - alpha) * this._theta + alpha * other.theta;
52569         }
52570         multiply(value) {
52571             this._phi *= value;
52572             this._theta *= value;
52573         }
52574         threshold(value) {
52575             this._phi = Math.abs(this._phi) > value ? this._phi : 0;
52576             this._theta = Math.abs(this._theta) > value ? this._theta : 0;
52577         }
52578         lengthSquared() {
52579             return this._phi * this._phi + this._theta * this._theta;
52580         }
52581         reset() {
52582             this._phi = 0;
52583             this._theta = 0;
52584         }
52585     }
52586
52587     class InteractiveStateBase extends StateBase {
52588         constructor(state) {
52589             super(state);
52590             this._animationSpeed = 1 / 40;
52591             this._rotationDelta = new EulerRotationDelta(0, 0);
52592             this._requestedRotationDelta = null;
52593             this._basicRotation = [0, 0];
52594             this._requestedBasicRotation = null;
52595             this._requestedBasicRotationUnbounded = null;
52596             this._rotationAcceleration = 0.86;
52597             this._rotationIncreaseAlpha = 0.97;
52598             this._rotationDecreaseAlpha = 0.9;
52599             this._rotationThreshold = 1e-3;
52600             this._unboundedRotationAlpha = 0.8;
52601             this._desiredZoom = state.zoom;
52602             this._minZoom = 0;
52603             this._maxZoom = 3;
52604             this._lookatDepth = 10;
52605             this._desiredLookat = null;
52606             this._desiredCenter = null;
52607         }
52608         rotate(rotationDelta) {
52609             if (this._currentImage == null) {
52610                 return;
52611             }
52612             if (rotationDelta.phi === 0 && rotationDelta.theta === 0) {
52613                 return;
52614             }
52615             this._desiredZoom = this._zoom;
52616             this._desiredLookat = null;
52617             this._requestedBasicRotation = null;
52618             if (this._requestedRotationDelta != null) {
52619                 this._requestedRotationDelta.phi = this._requestedRotationDelta.phi + rotationDelta.phi;
52620                 this._requestedRotationDelta.theta = this._requestedRotationDelta.theta + rotationDelta.theta;
52621             }
52622             else {
52623                 this._requestedRotationDelta = new EulerRotationDelta(rotationDelta.phi, rotationDelta.theta);
52624             }
52625         }
52626         rotateUnbounded(delta) {
52627             if (this._currentImage == null) {
52628                 return;
52629             }
52630             this._requestedBasicRotation = null;
52631             this._requestedRotationDelta = null;
52632             this._applyRotation(delta, this._currentCamera);
52633             this._applyRotation(delta, this._previousCamera);
52634             if (!this._desiredLookat) {
52635                 return;
52636             }
52637             const q = new Quaternion().setFromUnitVectors(this._currentCamera.up, new Vector3(0, 0, 1));
52638             const qInverse = q.clone().invert();
52639             const offset = new Vector3()
52640                 .copy(this._desiredLookat)
52641                 .sub(this._camera.position)
52642                 .applyQuaternion(q);
52643             const length = offset.length();
52644             let phi = Math.atan2(offset.y, offset.x);
52645             phi += delta.phi;
52646             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
52647             theta += delta.theta;
52648             theta = Math.max(0.1, Math.min(Math.PI - 0.1, theta));
52649             offset.x = Math.sin(theta) * Math.cos(phi);
52650             offset.y = Math.sin(theta) * Math.sin(phi);
52651             offset.z = Math.cos(theta);
52652             offset.applyQuaternion(qInverse);
52653             this._desiredLookat
52654                 .copy(this._camera.position)
52655                 .add(offset.multiplyScalar(length));
52656         }
52657         rotateWithoutInertia(rotationDelta) {
52658             if (this._currentImage == null) {
52659                 return;
52660             }
52661             this._desiredZoom = this._zoom;
52662             this._desiredLookat = null;
52663             this._requestedBasicRotation = null;
52664             this._requestedRotationDelta = null;
52665             const threshold = Math.PI / (10 * Math.pow(2, this._zoom));
52666             const delta = {
52667                 phi: this._spatial.clamp(rotationDelta.phi, -threshold, threshold),
52668                 theta: this._spatial.clamp(rotationDelta.theta, -threshold, threshold),
52669             };
52670             this._applyRotation(delta, this._currentCamera);
52671             this._applyRotation(delta, this._previousCamera);
52672         }
52673         rotateBasic(basicRotation) {
52674             if (this._currentImage == null) {
52675                 return;
52676             }
52677             this._desiredZoom = this._zoom;
52678             this._desiredLookat = null;
52679             this._requestedRotationDelta = null;
52680             if (this._requestedBasicRotation != null) {
52681                 this._requestedBasicRotation[0] += basicRotation[0];
52682                 this._requestedBasicRotation[1] += basicRotation[1];
52683                 let threshold = 0.05 / Math.pow(2, this._zoom);
52684                 this._requestedBasicRotation[0] =
52685                     this._spatial.clamp(this._requestedBasicRotation[0], -threshold, threshold);
52686                 this._requestedBasicRotation[1] =
52687                     this._spatial.clamp(this._requestedBasicRotation[1], -threshold, threshold);
52688             }
52689             else {
52690                 this._requestedBasicRotation = basicRotation.slice();
52691             }
52692         }
52693         rotateBasicUnbounded(basicRotation) {
52694             if (this._currentImage == null) {
52695                 return;
52696             }
52697             if (this._requestedBasicRotationUnbounded != null) {
52698                 this._requestedBasicRotationUnbounded[0] += basicRotation[0];
52699                 this._requestedBasicRotationUnbounded[1] += basicRotation[1];
52700             }
52701             else {
52702                 this._requestedBasicRotationUnbounded = basicRotation.slice();
52703             }
52704         }
52705         rotateBasicWithoutInertia(basic) {
52706             if (this._currentImage == null) {
52707                 return;
52708             }
52709             this._desiredZoom = this._zoom;
52710             this._desiredLookat = null;
52711             this._requestedRotationDelta = null;
52712             this._requestedBasicRotation = null;
52713             const threshold = 0.05 / Math.pow(2, this._zoom);
52714             const basicRotation = basic.slice();
52715             basicRotation[0] = this._spatial.clamp(basicRotation[0], -threshold, threshold);
52716             basicRotation[1] = this._spatial.clamp(basicRotation[1], -threshold, threshold);
52717             this._applyRotationBasic(basicRotation);
52718         }
52719         rotateToBasic(basic) {
52720             if (this._currentImage == null) {
52721                 return;
52722             }
52723             this._desiredZoom = this._zoom;
52724             this._desiredLookat = null;
52725             basic[0] = this._spatial.clamp(basic[0], 0, 1);
52726             basic[1] = this._spatial.clamp(basic[1], 0, 1);
52727             let lookat = this.currentTransform.unprojectBasic(basic, this._lookatDepth);
52728             this._currentCamera.lookat.fromArray(lookat);
52729         }
52730         zoomIn(delta, reference) {
52731             if (this._currentImage == null) {
52732                 return;
52733             }
52734             this._desiredZoom = Math.max(this._minZoom, Math.min(this._maxZoom, this._desiredZoom + delta));
52735             let currentCenter = this.currentTransform.projectBasic(this._currentCamera.lookat.toArray());
52736             let currentCenterX = currentCenter[0];
52737             let currentCenterY = currentCenter[1];
52738             let zoom0 = Math.pow(2, this._zoom);
52739             let zoom1 = Math.pow(2, this._desiredZoom);
52740             let refX = reference[0];
52741             let refY = reference[1];
52742             if (isSpherical(this.currentTransform.cameraType)) {
52743                 if (refX - currentCenterX > 0.5) {
52744                     refX = refX - 1;
52745                 }
52746                 else if (currentCenterX - refX > 0.5) {
52747                     refX = 1 + refX;
52748                 }
52749             }
52750             let newCenterX = refX - zoom0 / zoom1 * (refX - currentCenterX);
52751             let newCenterY = refY - zoom0 / zoom1 * (refY - currentCenterY);
52752             if (isSpherical(this._currentImage.cameraType)) {
52753                 newCenterX = this._spatial
52754                     .wrap(newCenterX + this._basicRotation[0], 0, 1);
52755                 newCenterY = this._spatial
52756                     .clamp(newCenterY + this._basicRotation[1], 0.05, 0.95);
52757             }
52758             else {
52759                 newCenterX = this._spatial.clamp(newCenterX, 0, 1);
52760                 newCenterY = this._spatial.clamp(newCenterY, 0, 1);
52761             }
52762             this._desiredLookat = new Vector3()
52763                 .fromArray(this.currentTransform.unprojectBasic([newCenterX, newCenterY], this._lookatDepth));
52764         }
52765         setCenter(center) {
52766             this._desiredLookat = null;
52767             this._requestedRotationDelta = null;
52768             this._requestedBasicRotation = null;
52769             this._desiredZoom = this._zoom;
52770             let clamped = [
52771                 this._spatial.clamp(center[0], 0, 1),
52772                 this._spatial.clamp(center[1], 0, 1),
52773             ];
52774             if (this._currentImage == null) {
52775                 this._desiredCenter = clamped;
52776                 return;
52777             }
52778             this._desiredCenter = null;
52779             let currentLookat = new Vector3()
52780                 .fromArray(this.currentTransform.unprojectBasic(clamped, this._lookatDepth));
52781             let previousTransform = this.previousTransform != null ?
52782                 this.previousTransform :
52783                 this.currentTransform;
52784             let previousLookat = new Vector3()
52785                 .fromArray(previousTransform.unprojectBasic(clamped, this._lookatDepth));
52786             this._currentCamera.lookat.copy(currentLookat);
52787             this._previousCamera.lookat.copy(previousLookat);
52788         }
52789         setZoom(zoom) {
52790             this._desiredLookat = null;
52791             this._requestedRotationDelta = null;
52792             this._requestedBasicRotation = null;
52793             this._zoom = this._spatial.clamp(zoom, this._minZoom, this._maxZoom);
52794             this._desiredZoom = this._zoom;
52795         }
52796         _applyRotation(delta, camera) {
52797             if (camera == null) {
52798                 return;
52799             }
52800             let q = new Quaternion().setFromUnitVectors(camera.up, new Vector3(0, 0, 1));
52801             let qInverse = q.clone().invert();
52802             let offset = new Vector3();
52803             offset.copy(camera.lookat).sub(camera.position);
52804             offset.applyQuaternion(q);
52805             let length = offset.length();
52806             let phi = Math.atan2(offset.y, offset.x);
52807             phi += delta.phi;
52808             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
52809             theta += delta.theta;
52810             theta = Math.max(0.1, Math.min(Math.PI - 0.1, theta));
52811             offset.x = Math.sin(theta) * Math.cos(phi);
52812             offset.y = Math.sin(theta) * Math.sin(phi);
52813             offset.z = Math.cos(theta);
52814             offset.applyQuaternion(qInverse);
52815             camera.lookat.copy(camera.position).add(offset.multiplyScalar(length));
52816         }
52817         _applyRotationBasic(basicRotation) {
52818             let currentImage = this._currentImage;
52819             let previousImage = this._previousImage != null ?
52820                 this.previousImage :
52821                 this.currentImage;
52822             let currentCamera = this._currentCamera;
52823             let previousCamera = this._previousCamera;
52824             let currentTransform = this.currentTransform;
52825             let previousTransform = this.previousTransform != null ?
52826                 this.previousTransform :
52827                 this.currentTransform;
52828             let currentBasic = currentTransform.projectBasic(currentCamera.lookat.toArray());
52829             let previousBasic = previousTransform.projectBasic(previousCamera.lookat.toArray());
52830             if (isSpherical(currentImage.cameraType)) {
52831                 currentBasic[0] = this._spatial.wrap(currentBasic[0] + basicRotation[0], 0, 1);
52832                 currentBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0.05, 0.95);
52833             }
52834             else {
52835                 currentBasic[0] = this._spatial.clamp(currentBasic[0] + basicRotation[0], 0, 1);
52836                 currentBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0, 1);
52837             }
52838             if (isSpherical(previousImage.cameraType)) {
52839                 previousBasic[0] = this._spatial.wrap(previousBasic[0] + basicRotation[0], 0, 1);
52840                 previousBasic[1] = this._spatial.clamp(previousBasic[1] + basicRotation[1], 0.05, 0.95);
52841             }
52842             else {
52843                 previousBasic[0] = this._spatial.clamp(previousBasic[0] + basicRotation[0], 0, 1);
52844                 previousBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0, 1);
52845             }
52846             let currentLookat = currentTransform.unprojectBasic(currentBasic, this._lookatDepth);
52847             currentCamera.lookat.fromArray(currentLookat);
52848             let previousLookat = previousTransform.unprojectBasic(previousBasic, this._lookatDepth);
52849             previousCamera.lookat.fromArray(previousLookat);
52850         }
52851         _updateZoom(animationSpeed) {
52852             let diff = this._desiredZoom - this._zoom;
52853             let sign = diff > 0 ? 1 : diff < 0 ? -1 : 0;
52854             if (diff === 0) {
52855                 return;
52856             }
52857             else if (Math.abs(diff) < 2e-3) {
52858                 this._zoom = this._desiredZoom;
52859                 if (this._desiredLookat != null) {
52860                     this._desiredLookat = null;
52861                 }
52862             }
52863             else {
52864                 this._zoom += sign * Math.max(Math.abs(5 * animationSpeed * diff), 2e-3);
52865             }
52866         }
52867         _updateLookat(animationSpeed) {
52868             if (this._desiredLookat === null) {
52869                 return;
52870             }
52871             let diff = this._desiredLookat.distanceToSquared(this._currentCamera.lookat);
52872             if (Math.abs(diff) < 1e-6) {
52873                 this._currentCamera.lookat.copy(this._desiredLookat);
52874                 this._desiredLookat = null;
52875             }
52876             else {
52877                 this._currentCamera.lookat.lerp(this._desiredLookat, 5 * animationSpeed);
52878             }
52879         }
52880         _updateRotation() {
52881             if (this._requestedRotationDelta != null) {
52882                 let length = this._rotationDelta.lengthSquared();
52883                 let requestedLength = this._requestedRotationDelta.lengthSquared();
52884                 if (requestedLength > length) {
52885                     this._rotationDelta.lerp(this._requestedRotationDelta, this._rotationIncreaseAlpha);
52886                 }
52887                 else {
52888                     this._rotationDelta.lerp(this._requestedRotationDelta, this._rotationDecreaseAlpha);
52889                 }
52890                 this._requestedRotationDelta = null;
52891                 return;
52892             }
52893             if (this._rotationDelta.isZero) {
52894                 return;
52895             }
52896             const alpha = isSpherical(this.currentImage.cameraType) ?
52897                 1 : this._alpha;
52898             this._rotationDelta.multiply(this._rotationAcceleration * alpha);
52899             this._rotationDelta.threshold(this._rotationThreshold);
52900         }
52901         _updateRotationBasic() {
52902             if (this._requestedBasicRotation != null) {
52903                 let x = this._basicRotation[0];
52904                 let y = this._basicRotation[1];
52905                 let reqX = this._requestedBasicRotation[0];
52906                 let reqY = this._requestedBasicRotation[1];
52907                 if (Math.abs(reqX) > Math.abs(x)) {
52908                     this._basicRotation[0] = (1 - this._rotationIncreaseAlpha) * x + this._rotationIncreaseAlpha * reqX;
52909                 }
52910                 else {
52911                     this._basicRotation[0] = (1 - this._rotationDecreaseAlpha) * x + this._rotationDecreaseAlpha * reqX;
52912                 }
52913                 if (Math.abs(reqY) > Math.abs(y)) {
52914                     this._basicRotation[1] = (1 - this._rotationIncreaseAlpha) * y + this._rotationIncreaseAlpha * reqY;
52915                 }
52916                 else {
52917                     this._basicRotation[1] = (1 - this._rotationDecreaseAlpha) * y + this._rotationDecreaseAlpha * reqY;
52918                 }
52919                 this._requestedBasicRotation = null;
52920                 return;
52921             }
52922             if (this._requestedBasicRotationUnbounded != null) {
52923                 let reqX = this._requestedBasicRotationUnbounded[0];
52924                 let reqY = this._requestedBasicRotationUnbounded[1];
52925                 if (Math.abs(reqX) > 0) {
52926                     this._basicRotation[0] = (1 - this._unboundedRotationAlpha) * this._basicRotation[0] + this._unboundedRotationAlpha * reqX;
52927                 }
52928                 if (Math.abs(reqY) > 0) {
52929                     this._basicRotation[1] = (1 - this._unboundedRotationAlpha) * this._basicRotation[1] + this._unboundedRotationAlpha * reqY;
52930                 }
52931                 if (this._desiredLookat != null) {
52932                     let desiredBasicLookat = this.currentTransform.projectBasic(this._desiredLookat.toArray());
52933                     desiredBasicLookat[0] += reqX;
52934                     desiredBasicLookat[1] += reqY;
52935                     this._desiredLookat = new Vector3()
52936                         .fromArray(this.currentTransform.unprojectBasic(desiredBasicLookat, this._lookatDepth));
52937                 }
52938                 this._requestedBasicRotationUnbounded = null;
52939             }
52940             if (this._basicRotation[0] === 0 && this._basicRotation[1] === 0) {
52941                 return;
52942             }
52943             this._basicRotation[0] = this._rotationAcceleration * this._basicRotation[0];
52944             this._basicRotation[1] = this._rotationAcceleration * this._basicRotation[1];
52945             if (Math.abs(this._basicRotation[0]) < this._rotationThreshold / Math.pow(2, this._zoom) &&
52946                 Math.abs(this._basicRotation[1]) < this._rotationThreshold / Math.pow(2, this._zoom)) {
52947                 this._basicRotation = [0, 0];
52948             }
52949         }
52950         _clearRotation() {
52951             if (isSpherical(this._currentImage.cameraType)) {
52952                 return;
52953             }
52954             if (this._requestedRotationDelta != null) {
52955                 this._requestedRotationDelta = null;
52956             }
52957             if (!this._rotationDelta.isZero) {
52958                 this._rotationDelta.reset();
52959             }
52960             if (this._requestedBasicRotation != null) {
52961                 this._requestedBasicRotation = null;
52962             }
52963             if (this._basicRotation[0] > 0 || this._basicRotation[1] > 0) {
52964                 this._basicRotation = [0, 0];
52965             }
52966         }
52967         _setDesiredCenter() {
52968             if (this._desiredCenter == null) {
52969                 return;
52970             }
52971             let lookatDirection = new Vector3()
52972                 .fromArray(this.currentTransform.unprojectBasic(this._desiredCenter, this._lookatDepth))
52973                 .sub(this._currentCamera.position);
52974             this._currentCamera.lookat.copy(this._currentCamera.position.clone().add(lookatDirection));
52975             this._previousCamera.lookat.copy(this._previousCamera.position.clone().add(lookatDirection));
52976             this._desiredCenter = null;
52977         }
52978         _setDesiredZoom() {
52979             this._desiredZoom =
52980                 isSpherical(this._currentImage.cameraType) ||
52981                     this._previousImage == null ?
52982                     this._zoom : 0;
52983         }
52984     }
52985
52986     class TraversingState extends InteractiveStateBase {
52987         constructor(state) {
52988             super(state);
52989             this._adjustCameras();
52990             this._motionless = this._motionlessTransition();
52991             this._baseAlpha = this._alpha;
52992             this._speedCoefficient = 1;
52993             this._unitBezier =
52994                 new TraversingState._interpolator(0.74, 0.67, 0.38, 0.96);
52995             this._useBezier = false;
52996         }
52997         static register(interpolator) {
52998             TraversingState._interpolator = interpolator;
52999         }
53000         append(images) {
53001             let emptyTrajectory = this._trajectory.length === 0;
53002             if (emptyTrajectory) {
53003                 this._resetTransition();
53004             }
53005             super.append(images);
53006             if (emptyTrajectory) {
53007                 this._setDesiredCenter();
53008                 this._setDesiredZoom();
53009             }
53010         }
53011         prepend(images) {
53012             let emptyTrajectory = this._trajectory.length === 0;
53013             if (emptyTrajectory) {
53014                 this._resetTransition();
53015             }
53016             super.prepend(images);
53017             if (emptyTrajectory) {
53018                 this._setDesiredCenter();
53019                 this._setDesiredZoom();
53020             }
53021         }
53022         set(images) {
53023             super.set(images);
53024             this._desiredLookat = null;
53025             this._resetTransition();
53026             this._clearRotation();
53027             this._setDesiredCenter();
53028             this._setDesiredZoom();
53029             if (this._trajectory.length < 3) {
53030                 this._useBezier = true;
53031             }
53032         }
53033         setSpeed(speed) {
53034             this._speedCoefficient = this._spatial.clamp(speed, 0, 10);
53035         }
53036         update(fps) {
53037             if (this._alpha === 1 && this._currentIndex + this._alpha < this._trajectory.length) {
53038                 this._currentIndex += 1;
53039                 this._useBezier = this._trajectory.length < 3 &&
53040                     this._currentIndex + 1 === this._trajectory.length;
53041                 this._setCurrent();
53042                 this._resetTransition();
53043                 this._clearRotation();
53044                 this._desiredZoom =
53045                     isSpherical(this._currentImage.cameraType) ?
53046                         this._zoom : 0;
53047                 this._desiredLookat = null;
53048             }
53049             let animationSpeed = this._animationSpeed * (60 / fps);
53050             this._baseAlpha = Math.min(1, this._baseAlpha + this._speedCoefficient * animationSpeed);
53051             if (this._useBezier) {
53052                 this._alpha = this._unitBezier.solve(this._baseAlpha);
53053             }
53054             else {
53055                 this._alpha = this._baseAlpha;
53056             }
53057             this._updateRotation();
53058             if (!this._rotationDelta.isZero) {
53059                 this._applyRotation(this._rotationDelta, this._previousCamera);
53060                 this._applyRotation(this._rotationDelta, this._currentCamera);
53061             }
53062             this._updateRotationBasic();
53063             if (this._basicRotation[0] !== 0 || this._basicRotation[1] !== 0) {
53064                 this._applyRotationBasic(this._basicRotation);
53065             }
53066             this._updateZoom(animationSpeed);
53067             this._updateLookat(animationSpeed);
53068             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
53069         }
53070         _getAlpha() {
53071             return this._motionless ? Math.ceil(this._alpha) : this._alpha;
53072         }
53073         _setCurrentCamera() {
53074             super._setCurrentCamera();
53075             this._adjustCameras();
53076         }
53077         _adjustCameras() {
53078             if (this._previousImage == null) {
53079                 return;
53080             }
53081             let lookat = this._camera.lookat.clone().sub(this._camera.position);
53082             this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
53083             if (isSpherical(this._currentImage.cameraType)) {
53084                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
53085             }
53086         }
53087         _resetTransition() {
53088             this._alpha = 0;
53089             this._baseAlpha = 0;
53090             this._motionless = this._motionlessTransition();
53091         }
53092     }
53093
53094     class ComponentService {
53095         constructor(container, navigator) {
53096             this._components = {};
53097             for (const componentName in ComponentService.registeredComponents) {
53098                 if (!ComponentService.registeredComponents.hasOwnProperty(componentName)) {
53099                     continue;
53100                 }
53101                 const component = ComponentService.registeredComponents[componentName];
53102                 this._components[componentName] = {
53103                     active: false,
53104                     component: new component(componentName, container, navigator),
53105                 };
53106             }
53107             this._coverComponent = new ComponentService.registeredCoverComponent("cover", container, navigator);
53108             this._coverComponent.activate();
53109             this._coverActivated = true;
53110         }
53111         static register(component) {
53112             if (ComponentService.registeredComponents[component.componentName] === undefined) {
53113                 ComponentService.registeredComponents[component.componentName] = component;
53114             }
53115         }
53116         static registerCover(coverComponent) {
53117             ComponentService.registeredCoverComponent = coverComponent;
53118         }
53119         get coverActivated() {
53120             return this._coverActivated;
53121         }
53122         activateCover() {
53123             if (this._coverActivated) {
53124                 return;
53125             }
53126             this._coverActivated = true;
53127             for (const componentName in this._components) {
53128                 if (!this._components.hasOwnProperty(componentName)) {
53129                     continue;
53130                 }
53131                 const component = this._components[componentName];
53132                 if (component.active) {
53133                     component.component.deactivate();
53134                 }
53135             }
53136         }
53137         deactivateCover() {
53138             if (!this._coverActivated) {
53139                 return;
53140             }
53141             this._coverActivated = false;
53142             for (const componentName in this._components) {
53143                 if (!this._components.hasOwnProperty(componentName)) {
53144                     continue;
53145                 }
53146                 const component = this._components[componentName];
53147                 if (component.active) {
53148                     component.component.activate();
53149                 }
53150             }
53151         }
53152         activate(name) {
53153             this._checkName(name);
53154             this._components[name].active = true;
53155             if (!this._coverActivated) {
53156                 this.get(name).activate();
53157             }
53158         }
53159         configure(name, conf) {
53160             this._checkName(name);
53161             this.get(name).configure(conf);
53162         }
53163         deactivate(name) {
53164             this._checkName(name);
53165             this._components[name].active = false;
53166             if (!this._coverActivated) {
53167                 this.get(name).deactivate();
53168             }
53169         }
53170         get(name) {
53171             return this._components[name].component;
53172         }
53173         getCover() {
53174             return this._coverComponent;
53175         }
53176         remove() {
53177             this._coverComponent.deactivate();
53178             for (const componentName in this._components) {
53179                 if (!this._components.hasOwnProperty(componentName)) {
53180                     continue;
53181                 }
53182                 this._components[componentName].component.deactivate();
53183             }
53184         }
53185         _checkName(name) {
53186             if (!(name in this._components)) {
53187                 throw new ArgumentMapillaryError(`Component does not exist: ${name}`);
53188             }
53189         }
53190     }
53191     ComponentService.registeredComponents = {};
53192
53193     var nativeIsArray = Array.isArray;
53194     var toString$2 = Object.prototype.toString;
53195
53196     var xIsArray = nativeIsArray || isArray;
53197
53198     function isArray(obj) {
53199         return toString$2.call(obj) === "[object Array]"
53200     }
53201
53202     var version = "2";
53203
53204     VirtualPatch.NONE = 0;
53205     VirtualPatch.VTEXT = 1;
53206     VirtualPatch.VNODE = 2;
53207     VirtualPatch.WIDGET = 3;
53208     VirtualPatch.PROPS = 4;
53209     VirtualPatch.ORDER = 5;
53210     VirtualPatch.INSERT = 6;
53211     VirtualPatch.REMOVE = 7;
53212     VirtualPatch.THUNK = 8;
53213
53214     var vpatch = VirtualPatch;
53215
53216     function VirtualPatch(type, vNode, patch) {
53217         this.type = Number(type);
53218         this.vNode = vNode;
53219         this.patch = patch;
53220     }
53221
53222     VirtualPatch.prototype.version = version;
53223     VirtualPatch.prototype.type = "VirtualPatch";
53224
53225     var isVnode = isVirtualNode;
53226
53227     function isVirtualNode(x) {
53228         return x && x.type === "VirtualNode" && x.version === version
53229     }
53230
53231     var isVtext = isVirtualText;
53232
53233     function isVirtualText(x) {
53234         return x && x.type === "VirtualText" && x.version === version
53235     }
53236
53237     var isWidget_1 = isWidget;
53238
53239     function isWidget(w) {
53240         return w && w.type === "Widget"
53241     }
53242
53243     var isThunk_1 = isThunk;
53244
53245     function isThunk(t) {
53246         return t && t.type === "Thunk"
53247     }
53248
53249     var handleThunk_1 = handleThunk;
53250
53251     function handleThunk(a, b) {
53252         var renderedA = a;
53253         var renderedB = b;
53254
53255         if (isThunk_1(b)) {
53256             renderedB = renderThunk(b, a);
53257         }
53258
53259         if (isThunk_1(a)) {
53260             renderedA = renderThunk(a, null);
53261         }
53262
53263         return {
53264             a: renderedA,
53265             b: renderedB
53266         }
53267     }
53268
53269     function renderThunk(thunk, previous) {
53270         var renderedThunk = thunk.vnode;
53271
53272         if (!renderedThunk) {
53273             renderedThunk = thunk.vnode = thunk.render(previous);
53274         }
53275
53276         if (!(isVnode(renderedThunk) ||
53277                 isVtext(renderedThunk) ||
53278                 isWidget_1(renderedThunk))) {
53279             throw new Error("thunk did not return a valid node");
53280         }
53281
53282         return renderedThunk
53283     }
53284
53285     var isObject = function isObject(x) {
53286         return typeof x === 'object' && x !== null;
53287     };
53288
53289     var isVhook = isHook;
53290
53291     function isHook(hook) {
53292         return hook &&
53293           (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
53294            typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
53295     }
53296
53297     var diffProps_1 = diffProps;
53298
53299     function diffProps(a, b) {
53300         var diff;
53301
53302         for (var aKey in a) {
53303             if (!(aKey in b)) {
53304                 diff = diff || {};
53305                 diff[aKey] = undefined;
53306             }
53307
53308             var aValue = a[aKey];
53309             var bValue = b[aKey];
53310
53311             if (aValue === bValue) {
53312                 continue
53313             } else if (isObject(aValue) && isObject(bValue)) {
53314                 if (getPrototype$1(bValue) !== getPrototype$1(aValue)) {
53315                     diff = diff || {};
53316                     diff[aKey] = bValue;
53317                 } else if (isVhook(bValue)) {
53318                      diff = diff || {};
53319                      diff[aKey] = bValue;
53320                 } else {
53321                     var objectDiff = diffProps(aValue, bValue);
53322                     if (objectDiff) {
53323                         diff = diff || {};
53324                         diff[aKey] = objectDiff;
53325                     }
53326                 }
53327             } else {
53328                 diff = diff || {};
53329                 diff[aKey] = bValue;
53330             }
53331         }
53332
53333         for (var bKey in b) {
53334             if (!(bKey in a)) {
53335                 diff = diff || {};
53336                 diff[bKey] = b[bKey];
53337             }
53338         }
53339
53340         return diff
53341     }
53342
53343     function getPrototype$1(value) {
53344       if (Object.getPrototypeOf) {
53345         return Object.getPrototypeOf(value)
53346       } else if (value.__proto__) {
53347         return value.__proto__
53348       } else if (value.constructor) {
53349         return value.constructor.prototype
53350       }
53351     }
53352
53353     var diff_1$1 = diff;
53354
53355     function diff(a, b) {
53356         var patch = { a: a };
53357         walk(a, b, patch, 0);
53358         return patch
53359     }
53360
53361     function walk(a, b, patch, index) {
53362         if (a === b) {
53363             return
53364         }
53365
53366         var apply = patch[index];
53367         var applyClear = false;
53368
53369         if (isThunk_1(a) || isThunk_1(b)) {
53370             thunks(a, b, patch, index);
53371         } else if (b == null) {
53372
53373             // If a is a widget we will add a remove patch for it
53374             // Otherwise any child widgets/hooks must be destroyed.
53375             // This prevents adding two remove patches for a widget.
53376             if (!isWidget_1(a)) {
53377                 clearState(a, patch, index);
53378                 apply = patch[index];
53379             }
53380
53381             apply = appendPatch(apply, new vpatch(vpatch.REMOVE, a, b));
53382         } else if (isVnode(b)) {
53383             if (isVnode(a)) {
53384                 if (a.tagName === b.tagName &&
53385                     a.namespace === b.namespace &&
53386                     a.key === b.key) {
53387                     var propsPatch = diffProps_1(a.properties, b.properties);
53388                     if (propsPatch) {
53389                         apply = appendPatch(apply,
53390                             new vpatch(vpatch.PROPS, a, propsPatch));
53391                     }
53392                     apply = diffChildren(a, b, patch, apply, index);
53393                 } else {
53394                     apply = appendPatch(apply, new vpatch(vpatch.VNODE, a, b));
53395                     applyClear = true;
53396                 }
53397             } else {
53398                 apply = appendPatch(apply, new vpatch(vpatch.VNODE, a, b));
53399                 applyClear = true;
53400             }
53401         } else if (isVtext(b)) {
53402             if (!isVtext(a)) {
53403                 apply = appendPatch(apply, new vpatch(vpatch.VTEXT, a, b));
53404                 applyClear = true;
53405             } else if (a.text !== b.text) {
53406                 apply = appendPatch(apply, new vpatch(vpatch.VTEXT, a, b));
53407             }
53408         } else if (isWidget_1(b)) {
53409             if (!isWidget_1(a)) {
53410                 applyClear = true;
53411             }
53412
53413             apply = appendPatch(apply, new vpatch(vpatch.WIDGET, a, b));
53414         }
53415
53416         if (apply) {
53417             patch[index] = apply;
53418         }
53419
53420         if (applyClear) {
53421             clearState(a, patch, index);
53422         }
53423     }
53424
53425     function diffChildren(a, b, patch, apply, index) {
53426         var aChildren = a.children;
53427         var orderedSet = reorder(aChildren, b.children);
53428         var bChildren = orderedSet.children;
53429
53430         var aLen = aChildren.length;
53431         var bLen = bChildren.length;
53432         var len = aLen > bLen ? aLen : bLen;
53433
53434         for (var i = 0; i < len; i++) {
53435             var leftNode = aChildren[i];
53436             var rightNode = bChildren[i];
53437             index += 1;
53438
53439             if (!leftNode) {
53440                 if (rightNode) {
53441                     // Excess nodes in b need to be added
53442                     apply = appendPatch(apply,
53443                         new vpatch(vpatch.INSERT, null, rightNode));
53444                 }
53445             } else {
53446                 walk(leftNode, rightNode, patch, index);
53447             }
53448
53449             if (isVnode(leftNode) && leftNode.count) {
53450                 index += leftNode.count;
53451             }
53452         }
53453
53454         if (orderedSet.moves) {
53455             // Reorder nodes last
53456             apply = appendPatch(apply, new vpatch(
53457                 vpatch.ORDER,
53458                 a,
53459                 orderedSet.moves
53460             ));
53461         }
53462
53463         return apply
53464     }
53465
53466     function clearState(vNode, patch, index) {
53467         // TODO: Make this a single walk, not two
53468         unhook(vNode, patch, index);
53469         destroyWidgets(vNode, patch, index);
53470     }
53471
53472     // Patch records for all destroyed widgets must be added because we need
53473     // a DOM node reference for the destroy function
53474     function destroyWidgets(vNode, patch, index) {
53475         if (isWidget_1(vNode)) {
53476             if (typeof vNode.destroy === "function") {
53477                 patch[index] = appendPatch(
53478                     patch[index],
53479                     new vpatch(vpatch.REMOVE, vNode, null)
53480                 );
53481             }
53482         } else if (isVnode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
53483             var children = vNode.children;
53484             var len = children.length;
53485             for (var i = 0; i < len; i++) {
53486                 var child = children[i];
53487                 index += 1;
53488
53489                 destroyWidgets(child, patch, index);
53490
53491                 if (isVnode(child) && child.count) {
53492                     index += child.count;
53493                 }
53494             }
53495         } else if (isThunk_1(vNode)) {
53496             thunks(vNode, null, patch, index);
53497         }
53498     }
53499
53500     // Create a sub-patch for thunks
53501     function thunks(a, b, patch, index) {
53502         var nodes = handleThunk_1(a, b);
53503         var thunkPatch = diff(nodes.a, nodes.b);
53504         if (hasPatches(thunkPatch)) {
53505             patch[index] = new vpatch(vpatch.THUNK, null, thunkPatch);
53506         }
53507     }
53508
53509     function hasPatches(patch) {
53510         for (var index in patch) {
53511             if (index !== "a") {
53512                 return true
53513             }
53514         }
53515
53516         return false
53517     }
53518
53519     // Execute hooks when two nodes are identical
53520     function unhook(vNode, patch, index) {
53521         if (isVnode(vNode)) {
53522             if (vNode.hooks) {
53523                 patch[index] = appendPatch(
53524                     patch[index],
53525                     new vpatch(
53526                         vpatch.PROPS,
53527                         vNode,
53528                         undefinedKeys(vNode.hooks)
53529                     )
53530                 );
53531             }
53532
53533             if (vNode.descendantHooks || vNode.hasThunks) {
53534                 var children = vNode.children;
53535                 var len = children.length;
53536                 for (var i = 0; i < len; i++) {
53537                     var child = children[i];
53538                     index += 1;
53539
53540                     unhook(child, patch, index);
53541
53542                     if (isVnode(child) && child.count) {
53543                         index += child.count;
53544                     }
53545                 }
53546             }
53547         } else if (isThunk_1(vNode)) {
53548             thunks(vNode, null, patch, index);
53549         }
53550     }
53551
53552     function undefinedKeys(obj) {
53553         var result = {};
53554
53555         for (var key in obj) {
53556             result[key] = undefined;
53557         }
53558
53559         return result
53560     }
53561
53562     // List diff, naive left to right reordering
53563     function reorder(aChildren, bChildren) {
53564         // O(M) time, O(M) memory
53565         var bChildIndex = keyIndex(bChildren);
53566         var bKeys = bChildIndex.keys;
53567         var bFree = bChildIndex.free;
53568
53569         if (bFree.length === bChildren.length) {
53570             return {
53571                 children: bChildren,
53572                 moves: null
53573             }
53574         }
53575
53576         // O(N) time, O(N) memory
53577         var aChildIndex = keyIndex(aChildren);
53578         var aKeys = aChildIndex.keys;
53579         var aFree = aChildIndex.free;
53580
53581         if (aFree.length === aChildren.length) {
53582             return {
53583                 children: bChildren,
53584                 moves: null
53585             }
53586         }
53587
53588         // O(MAX(N, M)) memory
53589         var newChildren = [];
53590
53591         var freeIndex = 0;
53592         var freeCount = bFree.length;
53593         var deletedItems = 0;
53594
53595         // Iterate through a and match a node in b
53596         // O(N) time,
53597         for (var i = 0 ; i < aChildren.length; i++) {
53598             var aItem = aChildren[i];
53599             var itemIndex;
53600
53601             if (aItem.key) {
53602                 if (bKeys.hasOwnProperty(aItem.key)) {
53603                     // Match up the old keys
53604                     itemIndex = bKeys[aItem.key];
53605                     newChildren.push(bChildren[itemIndex]);
53606
53607                 } else {
53608                     // Remove old keyed items
53609                     itemIndex = i - deletedItems++;
53610                     newChildren.push(null);
53611                 }
53612             } else {
53613                 // Match the item in a with the next free item in b
53614                 if (freeIndex < freeCount) {
53615                     itemIndex = bFree[freeIndex++];
53616                     newChildren.push(bChildren[itemIndex]);
53617                 } else {
53618                     // There are no free items in b to match with
53619                     // the free items in a, so the extra free nodes
53620                     // are deleted.
53621                     itemIndex = i - deletedItems++;
53622                     newChildren.push(null);
53623                 }
53624             }
53625         }
53626
53627         var lastFreeIndex = freeIndex >= bFree.length ?
53628             bChildren.length :
53629             bFree[freeIndex];
53630
53631         // Iterate through b and append any new keys
53632         // O(M) time
53633         for (var j = 0; j < bChildren.length; j++) {
53634             var newItem = bChildren[j];
53635
53636             if (newItem.key) {
53637                 if (!aKeys.hasOwnProperty(newItem.key)) {
53638                     // Add any new keyed items
53639                     // We are adding new items to the end and then sorting them
53640                     // in place. In future we should insert new items in place.
53641                     newChildren.push(newItem);
53642                 }
53643             } else if (j >= lastFreeIndex) {
53644                 // Add any leftover non-keyed items
53645                 newChildren.push(newItem);
53646             }
53647         }
53648
53649         var simulate = newChildren.slice();
53650         var simulateIndex = 0;
53651         var removes = [];
53652         var inserts = [];
53653         var simulateItem;
53654
53655         for (var k = 0; k < bChildren.length;) {
53656             var wantedItem = bChildren[k];
53657             simulateItem = simulate[simulateIndex];
53658
53659             // remove items
53660             while (simulateItem === null && simulate.length) {
53661                 removes.push(remove(simulate, simulateIndex, null));
53662                 simulateItem = simulate[simulateIndex];
53663             }
53664
53665             if (!simulateItem || simulateItem.key !== wantedItem.key) {
53666                 // if we need a key in this position...
53667                 if (wantedItem.key) {
53668                     if (simulateItem && simulateItem.key) {
53669                         // if an insert doesn't put this key in place, it needs to move
53670                         if (bKeys[simulateItem.key] !== k + 1) {
53671                             removes.push(remove(simulate, simulateIndex, simulateItem.key));
53672                             simulateItem = simulate[simulateIndex];
53673                             // if the remove didn't put the wanted item in place, we need to insert it
53674                             if (!simulateItem || simulateItem.key !== wantedItem.key) {
53675                                 inserts.push({key: wantedItem.key, to: k});
53676                             }
53677                             // items are matching, so skip ahead
53678                             else {
53679                                 simulateIndex++;
53680                             }
53681                         }
53682                         else {
53683                             inserts.push({key: wantedItem.key, to: k});
53684                         }
53685                     }
53686                     else {
53687                         inserts.push({key: wantedItem.key, to: k});
53688                     }
53689                     k++;
53690                 }
53691                 // a key in simulate has no matching wanted key, remove it
53692                 else if (simulateItem && simulateItem.key) {
53693                     removes.push(remove(simulate, simulateIndex, simulateItem.key));
53694                 }
53695             }
53696             else {
53697                 simulateIndex++;
53698                 k++;
53699             }
53700         }
53701
53702         // remove all the remaining nodes from simulate
53703         while(simulateIndex < simulate.length) {
53704             simulateItem = simulate[simulateIndex];
53705             removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key));
53706         }
53707
53708         // If the only moves we have are deletes then we can just
53709         // let the delete patch remove these items.
53710         if (removes.length === deletedItems && !inserts.length) {
53711             return {
53712                 children: newChildren,
53713                 moves: null
53714             }
53715         }
53716
53717         return {
53718             children: newChildren,
53719             moves: {
53720                 removes: removes,
53721                 inserts: inserts
53722             }
53723         }
53724     }
53725
53726     function remove(arr, index, key) {
53727         arr.splice(index, 1);
53728
53729         return {
53730             from: index,
53731             key: key
53732         }
53733     }
53734
53735     function keyIndex(children) {
53736         var keys = {};
53737         var free = [];
53738         var length = children.length;
53739
53740         for (var i = 0; i < length; i++) {
53741             var child = children[i];
53742
53743             if (child.key) {
53744                 keys[child.key] = i;
53745             } else {
53746                 free.push(i);
53747             }
53748         }
53749
53750         return {
53751             keys: keys,     // A hash of key name to index
53752             free: free      // An array of unkeyed item indices
53753         }
53754     }
53755
53756     function appendPatch(apply, patch) {
53757         if (apply) {
53758             if (xIsArray(apply)) {
53759                 apply.push(patch);
53760             } else {
53761                 apply = [apply, patch];
53762             }
53763
53764             return apply
53765         } else {
53766             return patch
53767         }
53768     }
53769
53770     var diff_1 = diff_1$1;
53771
53772     var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
53773
53774     function getAugmentedNamespace(n) {
53775         if (n.__esModule) return n;
53776         var a = Object.defineProperty({}, '__esModule', {value: true});
53777         Object.keys(n).forEach(function (k) {
53778                 var d = Object.getOwnPropertyDescriptor(n, k);
53779                 Object.defineProperty(a, k, d.get ? d : {
53780                         enumerable: true,
53781                         get: function () {
53782                                 return n[k];
53783                         }
53784                 });
53785         });
53786         return a;
53787     }
53788
53789     function createCommonjsModule(fn) {
53790       var module = { exports: {} };
53791         return fn(module, module.exports), module.exports;
53792     }
53793
53794     function commonjsRequire (target) {
53795         throw new Error('Could not dynamically require "' + target + '". Please configure the dynamicRequireTargets option of @rollup/plugin-commonjs appropriately for this require call to behave properly.');
53796     }
53797
53798     var slice = Array.prototype.slice;
53799
53800     var domWalk = iterativelyWalk;
53801
53802     function iterativelyWalk(nodes, cb) {
53803         if (!('length' in nodes)) {
53804             nodes = [nodes];
53805         }
53806         
53807         nodes = slice.call(nodes);
53808
53809         while(nodes.length) {
53810             var node = nodes.shift(),
53811                 ret = cb(node);
53812
53813             if (ret) {
53814                 return ret
53815             }
53816
53817             if (node.childNodes && node.childNodes.length) {
53818                 nodes = slice.call(node.childNodes).concat(nodes);
53819             }
53820         }
53821     }
53822
53823     var domComment = Comment;
53824
53825     function Comment(data, owner) {
53826         if (!(this instanceof Comment)) {
53827             return new Comment(data, owner)
53828         }
53829
53830         this.data = data;
53831         this.nodeValue = data;
53832         this.length = data.length;
53833         this.ownerDocument = owner || null;
53834     }
53835
53836     Comment.prototype.nodeType = 8;
53837     Comment.prototype.nodeName = "#comment";
53838
53839     Comment.prototype.toString = function _Comment_toString() {
53840         return "[object Comment]"
53841     };
53842
53843     var domText = DOMText;
53844
53845     function DOMText(value, owner) {
53846         if (!(this instanceof DOMText)) {
53847             return new DOMText(value)
53848         }
53849
53850         this.data = value || "";
53851         this.length = this.data.length;
53852         this.ownerDocument = owner || null;
53853     }
53854
53855     DOMText.prototype.type = "DOMTextNode";
53856     DOMText.prototype.nodeType = 3;
53857     DOMText.prototype.nodeName = "#text";
53858
53859     DOMText.prototype.toString = function _Text_toString() {
53860         return this.data
53861     };
53862
53863     DOMText.prototype.replaceData = function replaceData(index, length, value) {
53864         var current = this.data;
53865         var left = current.substring(0, index);
53866         var right = current.substring(index + length, current.length);
53867         this.data = left + value + right;
53868         this.length = this.data.length;
53869     };
53870
53871     var dispatchEvent_1 = dispatchEvent;
53872
53873     function dispatchEvent(ev) {
53874         var elem = this;
53875         var type = ev.type;
53876
53877         if (!ev.target) {
53878             ev.target = elem;
53879         }
53880
53881         if (!elem.listeners) {
53882             elem.listeners = {};
53883         }
53884
53885         var listeners = elem.listeners[type];
53886
53887         if (listeners) {
53888             return listeners.forEach(function (listener) {
53889                 ev.currentTarget = elem;
53890                 if (typeof listener === 'function') {
53891                     listener(ev);
53892                 } else {
53893                     listener.handleEvent(ev);
53894                 }
53895             })
53896         }
53897
53898         if (elem.parentNode) {
53899             elem.parentNode.dispatchEvent(ev);
53900         }
53901     }
53902
53903     var addEventListener_1 = addEventListener;
53904
53905     function addEventListener(type, listener) {
53906         var elem = this;
53907
53908         if (!elem.listeners) {
53909             elem.listeners = {};
53910         }
53911
53912         if (!elem.listeners[type]) {
53913             elem.listeners[type] = [];
53914         }
53915
53916         if (elem.listeners[type].indexOf(listener) === -1) {
53917             elem.listeners[type].push(listener);
53918         }
53919     }
53920
53921     var removeEventListener_1 = removeEventListener;
53922
53923     function removeEventListener(type, listener) {
53924         var elem = this;
53925
53926         if (!elem.listeners) {
53927             return
53928         }
53929
53930         if (!elem.listeners[type]) {
53931             return
53932         }
53933
53934         var list = elem.listeners[type];
53935         var index = list.indexOf(listener);
53936         if (index !== -1) {
53937             list.splice(index, 1);
53938         }
53939     }
53940
53941     var serialize = serializeNode;
53942
53943     var voidElements = ["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];
53944
53945     function serializeNode(node) {
53946         switch (node.nodeType) {
53947             case 3:
53948                 return escapeText(node.data)
53949             case 8:
53950                 return "<!--" + node.data + "-->"
53951             default:
53952                 return serializeElement(node)
53953         }
53954     }
53955
53956     function serializeElement(elem) {
53957         var strings = [];
53958
53959         var tagname = elem.tagName;
53960
53961         if (elem.namespaceURI === "http://www.w3.org/1999/xhtml") {
53962             tagname = tagname.toLowerCase();
53963         }
53964
53965         strings.push("<" + tagname + properties(elem) + datasetify(elem));
53966
53967         if (voidElements.indexOf(tagname) > -1) {
53968             strings.push(" />");
53969         } else {
53970             strings.push(">");
53971
53972             if (elem.childNodes.length) {
53973                 strings.push.apply(strings, elem.childNodes.map(serializeNode));
53974             } else if (elem.textContent || elem.innerText) {
53975                 strings.push(escapeText(elem.textContent || elem.innerText));
53976             } else if (elem.innerHTML) {
53977                 strings.push(elem.innerHTML);
53978             }
53979
53980             strings.push("</" + tagname + ">");
53981         }
53982
53983         return strings.join("")
53984     }
53985
53986     function isProperty(elem, key) {
53987         var type = typeof elem[key];
53988
53989         if (key === "style" && Object.keys(elem.style).length > 0) {
53990           return true
53991         }
53992
53993         return elem.hasOwnProperty(key) &&
53994             (type === "string" || type === "boolean" || type === "number") &&
53995             key !== "nodeName" && key !== "className" && key !== "tagName" &&
53996             key !== "textContent" && key !== "innerText" && key !== "namespaceURI" &&  key !== "innerHTML"
53997     }
53998
53999     function stylify(styles) {
54000         if (typeof styles === 'string') return styles
54001         var attr = "";
54002         Object.keys(styles).forEach(function (key) {
54003             var value = styles[key];
54004             key = key.replace(/[A-Z]/g, function(c) {
54005                 return "-" + c.toLowerCase();
54006             });
54007             attr += key + ":" + value + ";";
54008         });
54009         return attr
54010     }
54011
54012     function datasetify(elem) {
54013         var ds = elem.dataset;
54014         var props = [];
54015
54016         for (var key in ds) {
54017             props.push({ name: "data-" + key, value: ds[key] });
54018         }
54019
54020         return props.length ? stringify(props) : ""
54021     }
54022
54023     function stringify(list) {
54024         var attributes = [];
54025         list.forEach(function (tuple) {
54026             var name = tuple.name;
54027             var value = tuple.value;
54028
54029             if (name === "style") {
54030                 value = stylify(value);
54031             }
54032
54033             attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"");
54034         });
54035
54036         return attributes.length ? " " + attributes.join(" ") : ""
54037     }
54038
54039     function properties(elem) {
54040         var props = [];
54041         for (var key in elem) {
54042             if (isProperty(elem, key)) {
54043                 props.push({ name: key, value: elem[key] });
54044             }
54045         }
54046
54047         for (var ns in elem._attributes) {
54048           for (var attribute in elem._attributes[ns]) {
54049             var prop = elem._attributes[ns][attribute];
54050             var name = (prop.prefix ? prop.prefix + ":" : "") + attribute;
54051             props.push({ name: name, value: prop.value });
54052           }
54053         }
54054
54055         if (elem.className) {
54056             props.push({ name: "class", value: elem.className });
54057         }
54058
54059         return props.length ? stringify(props) : ""
54060     }
54061
54062     function escapeText(s) {
54063         var str = '';
54064
54065         if (typeof(s) === 'string') { 
54066             str = s; 
54067         } else if (s) {
54068             str = s.toString();
54069         }
54070
54071         return str
54072             .replace(/&/g, "&amp;")
54073             .replace(/</g, "&lt;")
54074             .replace(/>/g, "&gt;")
54075     }
54076
54077     function escapeAttributeValue(str) {
54078         return escapeText(str).replace(/"/g, "&quot;")
54079     }
54080
54081     var htmlns = "http://www.w3.org/1999/xhtml";
54082
54083     var domElement = DOMElement;
54084
54085     function DOMElement(tagName, owner, namespace) {
54086         if (!(this instanceof DOMElement)) {
54087             return new DOMElement(tagName)
54088         }
54089
54090         var ns = namespace === undefined ? htmlns : (namespace || null);
54091
54092         this.tagName = ns === htmlns ? String(tagName).toUpperCase() : tagName;
54093         this.nodeName = this.tagName;
54094         this.className = "";
54095         this.dataset = {};
54096         this.childNodes = [];
54097         this.parentNode = null;
54098         this.style = {};
54099         this.ownerDocument = owner || null;
54100         this.namespaceURI = ns;
54101         this._attributes = {};
54102
54103         if (this.tagName === 'INPUT') {
54104           this.type = 'text';
54105         }
54106     }
54107
54108     DOMElement.prototype.type = "DOMElement";
54109     DOMElement.prototype.nodeType = 1;
54110
54111     DOMElement.prototype.appendChild = function _Element_appendChild(child) {
54112         if (child.parentNode) {
54113             child.parentNode.removeChild(child);
54114         }
54115
54116         this.childNodes.push(child);
54117         child.parentNode = this;
54118
54119         return child
54120     };
54121
54122     DOMElement.prototype.replaceChild =
54123         function _Element_replaceChild(elem, needle) {
54124             // TODO: Throw NotFoundError if needle.parentNode !== this
54125
54126             if (elem.parentNode) {
54127                 elem.parentNode.removeChild(elem);
54128             }
54129
54130             var index = this.childNodes.indexOf(needle);
54131
54132             needle.parentNode = null;
54133             this.childNodes[index] = elem;
54134             elem.parentNode = this;
54135
54136             return needle
54137         };
54138
54139     DOMElement.prototype.removeChild = function _Element_removeChild(elem) {
54140         // TODO: Throw NotFoundError if elem.parentNode !== this
54141
54142         var index = this.childNodes.indexOf(elem);
54143         this.childNodes.splice(index, 1);
54144
54145         elem.parentNode = null;
54146         return elem
54147     };
54148
54149     DOMElement.prototype.insertBefore =
54150         function _Element_insertBefore(elem, needle) {
54151             // TODO: Throw NotFoundError if referenceElement is a dom node
54152             // and parentNode !== this
54153
54154             if (elem.parentNode) {
54155                 elem.parentNode.removeChild(elem);
54156             }
54157
54158             var index = needle === null || needle === undefined ?
54159                 -1 :
54160                 this.childNodes.indexOf(needle);
54161
54162             if (index > -1) {
54163                 this.childNodes.splice(index, 0, elem);
54164             } else {
54165                 this.childNodes.push(elem);
54166             }
54167
54168             elem.parentNode = this;
54169             return elem
54170         };
54171
54172     DOMElement.prototype.setAttributeNS =
54173         function _Element_setAttributeNS(namespace, name, value) {
54174             var prefix = null;
54175             var localName = name;
54176             var colonPosition = name.indexOf(":");
54177             if (colonPosition > -1) {
54178                 prefix = name.substr(0, colonPosition);
54179                 localName = name.substr(colonPosition + 1);
54180             }
54181             if (this.tagName === 'INPUT' && name === 'type') {
54182               this.type = value;
54183             }
54184             else {
54185               var attributes = this._attributes[namespace] || (this._attributes[namespace] = {});
54186               attributes[localName] = {value: value, prefix: prefix};
54187             }
54188         };
54189
54190     DOMElement.prototype.getAttributeNS =
54191         function _Element_getAttributeNS(namespace, name) {
54192             var attributes = this._attributes[namespace];
54193             var value = attributes && attributes[name] && attributes[name].value;
54194             if (this.tagName === 'INPUT' && name === 'type') {
54195               return this.type;
54196             }
54197             if (typeof value !== "string") {
54198                 return null
54199             }
54200             return value
54201         };
54202
54203     DOMElement.prototype.removeAttributeNS =
54204         function _Element_removeAttributeNS(namespace, name) {
54205             var attributes = this._attributes[namespace];
54206             if (attributes) {
54207                 delete attributes[name];
54208             }
54209         };
54210
54211     DOMElement.prototype.hasAttributeNS =
54212         function _Element_hasAttributeNS(namespace, name) {
54213             var attributes = this._attributes[namespace];
54214             return !!attributes && name in attributes;
54215         };
54216
54217     DOMElement.prototype.setAttribute = function _Element_setAttribute(name, value) {
54218         return this.setAttributeNS(null, name, value)
54219     };
54220
54221     DOMElement.prototype.getAttribute = function _Element_getAttribute(name) {
54222         return this.getAttributeNS(null, name)
54223     };
54224
54225     DOMElement.prototype.removeAttribute = function _Element_removeAttribute(name) {
54226         return this.removeAttributeNS(null, name)
54227     };
54228
54229     DOMElement.prototype.hasAttribute = function _Element_hasAttribute(name) {
54230         return this.hasAttributeNS(null, name)
54231     };
54232
54233     DOMElement.prototype.removeEventListener = removeEventListener_1;
54234     DOMElement.prototype.addEventListener = addEventListener_1;
54235     DOMElement.prototype.dispatchEvent = dispatchEvent_1;
54236
54237     // Un-implemented
54238     DOMElement.prototype.focus = function _Element_focus() {
54239         return void 0
54240     };
54241
54242     DOMElement.prototype.toString = function _Element_toString() {
54243         return serialize(this)
54244     };
54245
54246     DOMElement.prototype.getElementsByClassName = function _Element_getElementsByClassName(classNames) {
54247         var classes = classNames.split(" ");
54248         var elems = [];
54249
54250         domWalk(this, function (node) {
54251             if (node.nodeType === 1) {
54252                 var nodeClassName = node.className || "";
54253                 var nodeClasses = nodeClassName.split(" ");
54254
54255                 if (classes.every(function (item) {
54256                     return nodeClasses.indexOf(item) !== -1
54257                 })) {
54258                     elems.push(node);
54259                 }
54260             }
54261         });
54262
54263         return elems
54264     };
54265
54266     DOMElement.prototype.getElementsByTagName = function _Element_getElementsByTagName(tagName) {
54267         tagName = tagName.toLowerCase();
54268         var elems = [];
54269
54270         domWalk(this.childNodes, function (node) {
54271             if (node.nodeType === 1 && (tagName === '*' || node.tagName.toLowerCase() === tagName)) {
54272                 elems.push(node);
54273             }
54274         });
54275
54276         return elems
54277     };
54278
54279     DOMElement.prototype.contains = function _Element_contains(element) {
54280         return domWalk(this, function (node) {
54281             return element === node
54282         }) || false
54283     };
54284
54285     var domFragment = DocumentFragment;
54286
54287     function DocumentFragment(owner) {
54288         if (!(this instanceof DocumentFragment)) {
54289             return new DocumentFragment()
54290         }
54291
54292         this.childNodes = [];
54293         this.parentNode = null;
54294         this.ownerDocument = owner || null;
54295     }
54296
54297     DocumentFragment.prototype.type = "DocumentFragment";
54298     DocumentFragment.prototype.nodeType = 11;
54299     DocumentFragment.prototype.nodeName = "#document-fragment";
54300
54301     DocumentFragment.prototype.appendChild  = domElement.prototype.appendChild;
54302     DocumentFragment.prototype.replaceChild = domElement.prototype.replaceChild;
54303     DocumentFragment.prototype.removeChild  = domElement.prototype.removeChild;
54304
54305     DocumentFragment.prototype.toString =
54306         function _DocumentFragment_toString() {
54307             return this.childNodes.map(function (node) {
54308                 return String(node)
54309             }).join("")
54310         };
54311
54312     var event = Event;
54313
54314     function Event(family) {}
54315
54316     Event.prototype.initEvent = function _Event_initEvent(type, bubbles, cancelable) {
54317         this.type = type;
54318         this.bubbles = bubbles;
54319         this.cancelable = cancelable;
54320     };
54321
54322     Event.prototype.preventDefault = function _Event_preventDefault() {
54323         
54324     };
54325
54326     var document$1 = Document;
54327
54328     function Document() {
54329         if (!(this instanceof Document)) {
54330             return new Document();
54331         }
54332
54333         this.head = this.createElement("head");
54334         this.body = this.createElement("body");
54335         this.documentElement = this.createElement("html");
54336         this.documentElement.appendChild(this.head);
54337         this.documentElement.appendChild(this.body);
54338         this.childNodes = [this.documentElement];
54339         this.nodeType = 9;
54340     }
54341
54342     var proto = Document.prototype;
54343     proto.createTextNode = function createTextNode(value) {
54344         return new domText(value, this)
54345     };
54346
54347     proto.createElementNS = function createElementNS(namespace, tagName) {
54348         var ns = namespace === null ? null : String(namespace);
54349         return new domElement(tagName, this, ns)
54350     };
54351
54352     proto.createElement = function createElement(tagName) {
54353         return new domElement(tagName, this)
54354     };
54355
54356     proto.createDocumentFragment = function createDocumentFragment() {
54357         return new domFragment(this)
54358     };
54359
54360     proto.createEvent = function createEvent(family) {
54361         return new event(family)
54362     };
54363
54364     proto.createComment = function createComment(data) {
54365         return new domComment(data, this)
54366     };
54367
54368     proto.getElementById = function getElementById(id) {
54369         id = String(id);
54370
54371         var result = domWalk(this.childNodes, function (node) {
54372             if (String(node.id) === id) {
54373                 return node
54374             }
54375         });
54376
54377         return result || null
54378     };
54379
54380     proto.getElementsByClassName = domElement.prototype.getElementsByClassName;
54381     proto.getElementsByTagName = domElement.prototype.getElementsByTagName;
54382     proto.contains = domElement.prototype.contains;
54383
54384     proto.removeEventListener = removeEventListener_1;
54385     proto.addEventListener = addEventListener_1;
54386     proto.dispatchEvent = dispatchEvent_1;
54387
54388     var minDocument = new document$1();
54389
54390     var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
54391         typeof window !== 'undefined' ? window : {};
54392
54393
54394     var doccy;
54395
54396     if (typeof document !== 'undefined') {
54397         doccy = document;
54398     } else {
54399         doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
54400
54401         if (!doccy) {
54402             doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDocument;
54403         }
54404     }
54405
54406     var document_1 = doccy;
54407
54408     var applyProperties_1 = applyProperties;
54409
54410     function applyProperties(node, props, previous) {
54411         for (var propName in props) {
54412             var propValue = props[propName];
54413
54414             if (propValue === undefined) {
54415                 removeProperty(node, propName, propValue, previous);
54416             } else if (isVhook(propValue)) {
54417                 removeProperty(node, propName, propValue, previous);
54418                 if (propValue.hook) {
54419                     propValue.hook(node,
54420                         propName,
54421                         previous ? previous[propName] : undefined);
54422                 }
54423             } else {
54424                 if (isObject(propValue)) {
54425                     patchObject(node, props, previous, propName, propValue);
54426                 } else {
54427                     node[propName] = propValue;
54428                 }
54429             }
54430         }
54431     }
54432
54433     function removeProperty(node, propName, propValue, previous) {
54434         if (previous) {
54435             var previousValue = previous[propName];
54436
54437             if (!isVhook(previousValue)) {
54438                 if (propName === "attributes") {
54439                     for (var attrName in previousValue) {
54440                         node.removeAttribute(attrName);
54441                     }
54442                 } else if (propName === "style") {
54443                     for (var i in previousValue) {
54444                         node.style[i] = "";
54445                     }
54446                 } else if (typeof previousValue === "string") {
54447                     node[propName] = "";
54448                 } else {
54449                     node[propName] = null;
54450                 }
54451             } else if (previousValue.unhook) {
54452                 previousValue.unhook(node, propName, propValue);
54453             }
54454         }
54455     }
54456
54457     function patchObject(node, props, previous, propName, propValue) {
54458         var previousValue = previous ? previous[propName] : undefined;
54459
54460         // Set attributes
54461         if (propName === "attributes") {
54462             for (var attrName in propValue) {
54463                 var attrValue = propValue[attrName];
54464
54465                 if (attrValue === undefined) {
54466                     node.removeAttribute(attrName);
54467                 } else {
54468                     node.setAttribute(attrName, attrValue);
54469                 }
54470             }
54471
54472             return
54473         }
54474
54475         if(previousValue && isObject(previousValue) &&
54476             getPrototype(previousValue) !== getPrototype(propValue)) {
54477             node[propName] = propValue;
54478             return
54479         }
54480
54481         if (!isObject(node[propName])) {
54482             node[propName] = {};
54483         }
54484
54485         var replacer = propName === "style" ? "" : undefined;
54486
54487         for (var k in propValue) {
54488             var value = propValue[k];
54489             node[propName][k] = (value === undefined) ? replacer : value;
54490         }
54491     }
54492
54493     function getPrototype(value) {
54494         if (Object.getPrototypeOf) {
54495             return Object.getPrototypeOf(value)
54496         } else if (value.__proto__) {
54497             return value.__proto__
54498         } else if (value.constructor) {
54499             return value.constructor.prototype
54500         }
54501     }
54502
54503     var createElement_1$1 = createElement;
54504
54505     function createElement(vnode, opts) {
54506         var doc = opts ? opts.document || document_1 : document_1;
54507         var warn = opts ? opts.warn : null;
54508
54509         vnode = handleThunk_1(vnode).a;
54510
54511         if (isWidget_1(vnode)) {
54512             return vnode.init()
54513         } else if (isVtext(vnode)) {
54514             return doc.createTextNode(vnode.text)
54515         } else if (!isVnode(vnode)) {
54516             if (warn) {
54517                 warn("Item is not a valid virtual dom node", vnode);
54518             }
54519             return null
54520         }
54521
54522         var node = (vnode.namespace === null) ?
54523             doc.createElement(vnode.tagName) :
54524             doc.createElementNS(vnode.namespace, vnode.tagName);
54525
54526         var props = vnode.properties;
54527         applyProperties_1(node, props);
54528
54529         var children = vnode.children;
54530
54531         for (var i = 0; i < children.length; i++) {
54532             var childNode = createElement(children[i], opts);
54533             if (childNode) {
54534                 node.appendChild(childNode);
54535             }
54536         }
54537
54538         return node
54539     }
54540
54541     // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
54542     // We don't want to read all of the DOM nodes in the tree so we use
54543     // the in-order tree indexing to eliminate recursion down certain branches.
54544     // We only recurse into a DOM node if we know that it contains a child of
54545     // interest.
54546
54547     var noChild = {};
54548
54549     var domIndex_1 = domIndex;
54550
54551     function domIndex(rootNode, tree, indices, nodes) {
54552         if (!indices || indices.length === 0) {
54553             return {}
54554         } else {
54555             indices.sort(ascending);
54556             return recurse(rootNode, tree, indices, nodes, 0)
54557         }
54558     }
54559
54560     function recurse(rootNode, tree, indices, nodes, rootIndex) {
54561         nodes = nodes || {};
54562
54563
54564         if (rootNode) {
54565             if (indexInRange(indices, rootIndex, rootIndex)) {
54566                 nodes[rootIndex] = rootNode;
54567             }
54568
54569             var vChildren = tree.children;
54570
54571             if (vChildren) {
54572
54573                 var childNodes = rootNode.childNodes;
54574
54575                 for (var i = 0; i < tree.children.length; i++) {
54576                     rootIndex += 1;
54577
54578                     var vChild = vChildren[i] || noChild;
54579                     var nextIndex = rootIndex + (vChild.count || 0);
54580
54581                     // skip recursion down the tree if there are no nodes down here
54582                     if (indexInRange(indices, rootIndex, nextIndex)) {
54583                         recurse(childNodes[i], vChild, indices, nodes, rootIndex);
54584                     }
54585
54586                     rootIndex = nextIndex;
54587                 }
54588             }
54589         }
54590
54591         return nodes
54592     }
54593
54594     // Binary search for an index in the interval [left, right]
54595     function indexInRange(indices, left, right) {
54596         if (indices.length === 0) {
54597             return false
54598         }
54599
54600         var minIndex = 0;
54601         var maxIndex = indices.length - 1;
54602         var currentIndex;
54603         var currentItem;
54604
54605         while (minIndex <= maxIndex) {
54606             currentIndex = ((maxIndex + minIndex) / 2) >> 0;
54607             currentItem = indices[currentIndex];
54608
54609             if (minIndex === maxIndex) {
54610                 return currentItem >= left && currentItem <= right
54611             } else if (currentItem < left) {
54612                 minIndex = currentIndex + 1;
54613             } else  if (currentItem > right) {
54614                 maxIndex = currentIndex - 1;
54615             } else {
54616                 return true
54617             }
54618         }
54619
54620         return false;
54621     }
54622
54623     function ascending(a, b) {
54624         return a > b ? 1 : -1
54625     }
54626
54627     var updateWidget_1 = updateWidget;
54628
54629     function updateWidget(a, b) {
54630         if (isWidget_1(a) && isWidget_1(b)) {
54631             if ("name" in a && "name" in b) {
54632                 return a.id === b.id
54633             } else {
54634                 return a.init === b.init
54635             }
54636         }
54637
54638         return false
54639     }
54640
54641     var patchOp = applyPatch$1;
54642
54643     function applyPatch$1(vpatch$1, domNode, renderOptions) {
54644         var type = vpatch$1.type;
54645         var vNode = vpatch$1.vNode;
54646         var patch = vpatch$1.patch;
54647
54648         switch (type) {
54649             case vpatch.REMOVE:
54650                 return removeNode$1(domNode, vNode)
54651             case vpatch.INSERT:
54652                 return insertNode$1(domNode, patch, renderOptions)
54653             case vpatch.VTEXT:
54654                 return stringPatch(domNode, vNode, patch, renderOptions)
54655             case vpatch.WIDGET:
54656                 return widgetPatch(domNode, vNode, patch, renderOptions)
54657             case vpatch.VNODE:
54658                 return vNodePatch(domNode, vNode, patch, renderOptions)
54659             case vpatch.ORDER:
54660                 reorderChildren(domNode, patch);
54661                 return domNode
54662             case vpatch.PROPS:
54663                 applyProperties_1(domNode, patch, vNode.properties);
54664                 return domNode
54665             case vpatch.THUNK:
54666                 return replaceRoot(domNode,
54667                     renderOptions.patch(domNode, patch, renderOptions))
54668             default:
54669                 return domNode
54670         }
54671     }
54672
54673     function removeNode$1(domNode, vNode) {
54674         var parentNode = domNode.parentNode;
54675
54676         if (parentNode) {
54677             parentNode.removeChild(domNode);
54678         }
54679
54680         destroyWidget(domNode, vNode);
54681
54682         return null
54683     }
54684
54685     function insertNode$1(parentNode, vNode, renderOptions) {
54686         var newNode = renderOptions.render(vNode, renderOptions);
54687
54688         if (parentNode) {
54689             parentNode.appendChild(newNode);
54690         }
54691
54692         return parentNode
54693     }
54694
54695     function stringPatch(domNode, leftVNode, vText, renderOptions) {
54696         var newNode;
54697
54698         if (domNode.nodeType === 3) {
54699             domNode.replaceData(0, domNode.length, vText.text);
54700             newNode = domNode;
54701         } else {
54702             var parentNode = domNode.parentNode;
54703             newNode = renderOptions.render(vText, renderOptions);
54704
54705             if (parentNode && newNode !== domNode) {
54706                 parentNode.replaceChild(newNode, domNode);
54707             }
54708         }
54709
54710         return newNode
54711     }
54712
54713     function widgetPatch(domNode, leftVNode, widget, renderOptions) {
54714         var updating = updateWidget_1(leftVNode, widget);
54715         var newNode;
54716
54717         if (updating) {
54718             newNode = widget.update(leftVNode, domNode) || domNode;
54719         } else {
54720             newNode = renderOptions.render(widget, renderOptions);
54721         }
54722
54723         var parentNode = domNode.parentNode;
54724
54725         if (parentNode && newNode !== domNode) {
54726             parentNode.replaceChild(newNode, domNode);
54727         }
54728
54729         if (!updating) {
54730             destroyWidget(domNode, leftVNode);
54731         }
54732
54733         return newNode
54734     }
54735
54736     function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
54737         var parentNode = domNode.parentNode;
54738         var newNode = renderOptions.render(vNode, renderOptions);
54739
54740         if (parentNode && newNode !== domNode) {
54741             parentNode.replaceChild(newNode, domNode);
54742         }
54743
54744         return newNode
54745     }
54746
54747     function destroyWidget(domNode, w) {
54748         if (typeof w.destroy === "function" && isWidget_1(w)) {
54749             w.destroy(domNode);
54750         }
54751     }
54752
54753     function reorderChildren(domNode, moves) {
54754         var childNodes = domNode.childNodes;
54755         var keyMap = {};
54756         var node;
54757         var remove;
54758         var insert;
54759
54760         for (var i = 0; i < moves.removes.length; i++) {
54761             remove = moves.removes[i];
54762             node = childNodes[remove.from];
54763             if (remove.key) {
54764                 keyMap[remove.key] = node;
54765             }
54766             domNode.removeChild(node);
54767         }
54768
54769         var length = childNodes.length;
54770         for (var j = 0; j < moves.inserts.length; j++) {
54771             insert = moves.inserts[j];
54772             node = keyMap[insert.key];
54773             // this is the weirdest bug i've ever seen in webkit
54774             domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]);
54775         }
54776     }
54777
54778     function replaceRoot(oldRoot, newRoot) {
54779         if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
54780             oldRoot.parentNode.replaceChild(newRoot, oldRoot);
54781         }
54782
54783         return newRoot;
54784     }
54785
54786     var patch_1$1 = patch;
54787
54788     function patch(rootNode, patches, renderOptions) {
54789         renderOptions = renderOptions || {};
54790         renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch
54791             ? renderOptions.patch
54792             : patchRecursive;
54793         renderOptions.render = renderOptions.render || createElement_1$1;
54794
54795         return renderOptions.patch(rootNode, patches, renderOptions)
54796     }
54797
54798     function patchRecursive(rootNode, patches, renderOptions) {
54799         var indices = patchIndices(patches);
54800
54801         if (indices.length === 0) {
54802             return rootNode
54803         }
54804
54805         var index = domIndex_1(rootNode, patches.a, indices);
54806         var ownerDocument = rootNode.ownerDocument;
54807
54808         if (!renderOptions.document && ownerDocument !== document_1) {
54809             renderOptions.document = ownerDocument;
54810         }
54811
54812         for (var i = 0; i < indices.length; i++) {
54813             var nodeIndex = indices[i];
54814             rootNode = applyPatch(rootNode,
54815                 index[nodeIndex],
54816                 patches[nodeIndex],
54817                 renderOptions);
54818         }
54819
54820         return rootNode
54821     }
54822
54823     function applyPatch(rootNode, domNode, patchList, renderOptions) {
54824         if (!domNode) {
54825             return rootNode
54826         }
54827
54828         var newNode;
54829
54830         if (xIsArray(patchList)) {
54831             for (var i = 0; i < patchList.length; i++) {
54832                 newNode = patchOp(patchList[i], domNode, renderOptions);
54833
54834                 if (domNode === rootNode) {
54835                     rootNode = newNode;
54836                 }
54837             }
54838         } else {
54839             newNode = patchOp(patchList, domNode, renderOptions);
54840
54841             if (domNode === rootNode) {
54842                 rootNode = newNode;
54843             }
54844         }
54845
54846         return rootNode
54847     }
54848
54849     function patchIndices(patches) {
54850         var indices = [];
54851
54852         for (var key in patches) {
54853             if (key !== "a") {
54854                 indices.push(Number(key));
54855             }
54856         }
54857
54858         return indices
54859     }
54860
54861     var patch_1 = patch_1$1;
54862
54863     var vnode = VirtualNode;
54864
54865     var noProperties = {};
54866     var noChildren = [];
54867
54868     function VirtualNode(tagName, properties, children, key, namespace) {
54869         this.tagName = tagName;
54870         this.properties = properties || noProperties;
54871         this.children = children || noChildren;
54872         this.key = key != null ? String(key) : undefined;
54873         this.namespace = (typeof namespace === "string") ? namespace : null;
54874
54875         var count = (children && children.length) || 0;
54876         var descendants = 0;
54877         var hasWidgets = false;
54878         var hasThunks = false;
54879         var descendantHooks = false;
54880         var hooks;
54881
54882         for (var propName in properties) {
54883             if (properties.hasOwnProperty(propName)) {
54884                 var property = properties[propName];
54885                 if (isVhook(property) && property.unhook) {
54886                     if (!hooks) {
54887                         hooks = {};
54888                     }
54889
54890                     hooks[propName] = property;
54891                 }
54892             }
54893         }
54894
54895         for (var i = 0; i < count; i++) {
54896             var child = children[i];
54897             if (isVnode(child)) {
54898                 descendants += child.count || 0;
54899
54900                 if (!hasWidgets && child.hasWidgets) {
54901                     hasWidgets = true;
54902                 }
54903
54904                 if (!hasThunks && child.hasThunks) {
54905                     hasThunks = true;
54906                 }
54907
54908                 if (!descendantHooks && (child.hooks || child.descendantHooks)) {
54909                     descendantHooks = true;
54910                 }
54911             } else if (!hasWidgets && isWidget_1(child)) {
54912                 if (typeof child.destroy === "function") {
54913                     hasWidgets = true;
54914                 }
54915             } else if (!hasThunks && isThunk_1(child)) {
54916                 hasThunks = true;
54917             }
54918         }
54919
54920         this.count = count + descendants;
54921         this.hasWidgets = hasWidgets;
54922         this.hasThunks = hasThunks;
54923         this.hooks = hooks;
54924         this.descendantHooks = descendantHooks;
54925     }
54926
54927     VirtualNode.prototype.version = version;
54928     VirtualNode.prototype.type = "VirtualNode";
54929
54930     var vtext = VirtualText;
54931
54932     function VirtualText(text) {
54933         this.text = String(text);
54934     }
54935
54936     VirtualText.prototype.version = version;
54937     VirtualText.prototype.type = "VirtualText";
54938
54939     /*!
54940      * Cross-Browser Split 1.1.1
54941      * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
54942      * Available under the MIT License
54943      * ECMAScript compliant, uniform cross-browser split method
54944      */
54945     /**
54946      * Splits a string into an array of strings using a regex or string separator. Matches of the
54947      * separator are not included in the result array. However, if `separator` is a regex that contains
54948      * capturing groups, backreferences are spliced into the result each time `separator` is matched.
54949      * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
54950      * cross-browser.
54951      * @param {String} str String to split.
54952      * @param {RegExp|String} separator Regex or string to use for separating the string.
54953      * @param {Number} [limit] Maximum number of items to include in the result array.
54954      * @returns {Array} Array of substrings.
54955      * @example
54956      *
54957      * // Basic use
54958      * split('a b c d', ' ');
54959      * // -> ['a', 'b', 'c', 'd']
54960      *
54961      * // With limit
54962      * split('a b c d', ' ', 2);
54963      * // -> ['a', 'b']
54964      *
54965      * // Backreferences in result array
54966      * split('..word1 word2..', /([a-z]+)(\d+)/i);
54967      * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
54968      */
54969     var browserSplit = (function split(undef) {
54970
54971       var nativeSplit = String.prototype.split,
54972         compliantExecNpcg = /()??/.exec("")[1] === undef,
54973         // NPCG: nonparticipating capturing group
54974         self;
54975
54976       self = function(str, separator, limit) {
54977         // If `separator` is not a regex, use `nativeSplit`
54978         if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
54979           return nativeSplit.call(str, separator, limit);
54980         }
54981         var output = [],
54982           flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
54983           (separator.sticky ? "y" : ""),
54984           // Firefox 3+
54985           lastLastIndex = 0,
54986           // Make `global` and avoid `lastIndex` issues by working with a copy
54987           separator = new RegExp(separator.source, flags + "g"),
54988           separator2, match, lastIndex, lastLength;
54989         str += ""; // Type-convert
54990         if (!compliantExecNpcg) {
54991           // Doesn't need flags gy, but they don't hurt
54992           separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
54993         }
54994         /* Values for `limit`, per the spec:
54995          * If undefined: 4294967295 // Math.pow(2, 32) - 1
54996          * If 0, Infinity, or NaN: 0
54997          * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
54998          * If negative number: 4294967296 - Math.floor(Math.abs(limit))
54999          * If other: Type-convert, then use the above rules
55000          */
55001         limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
55002         limit >>> 0; // ToUint32(limit)
55003         while (match = separator.exec(str)) {
55004           // `separator.lastIndex` is not reliable cross-browser
55005           lastIndex = match.index + match[0].length;
55006           if (lastIndex > lastLastIndex) {
55007             output.push(str.slice(lastLastIndex, match.index));
55008             // Fix browsers whose `exec` methods don't consistently return `undefined` for
55009             // nonparticipating capturing groups
55010             if (!compliantExecNpcg && match.length > 1) {
55011               match[0].replace(separator2, function() {
55012                 for (var i = 1; i < arguments.length - 2; i++) {
55013                   if (arguments[i] === undef) {
55014                     match[i] = undef;
55015                   }
55016                 }
55017               });
55018             }
55019             if (match.length > 1 && match.index < str.length) {
55020               Array.prototype.push.apply(output, match.slice(1));
55021             }
55022             lastLength = match[0].length;
55023             lastLastIndex = lastIndex;
55024             if (output.length >= limit) {
55025               break;
55026             }
55027           }
55028           if (separator.lastIndex === match.index) {
55029             separator.lastIndex++; // Avoid an infinite loop
55030           }
55031         }
55032         if (lastLastIndex === str.length) {
55033           if (lastLength || !separator.test("")) {
55034             output.push("");
55035           }
55036         } else {
55037           output.push(str.slice(lastLastIndex));
55038         }
55039         return output.length > limit ? output.slice(0, limit) : output;
55040       };
55041
55042       return self;
55043     })();
55044
55045     var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/;
55046     var notClassId = /^\.|#/;
55047
55048     var parseTag_1 = parseTag;
55049
55050     function parseTag(tag, props) {
55051         if (!tag) {
55052             return 'DIV';
55053         }
55054
55055         var noId = !(props.hasOwnProperty('id'));
55056
55057         var tagParts = browserSplit(tag, classIdSplit);
55058         var tagName = null;
55059
55060         if (notClassId.test(tagParts[1])) {
55061             tagName = 'DIV';
55062         }
55063
55064         var classes, part, type, i;
55065
55066         for (i = 0; i < tagParts.length; i++) {
55067             part = tagParts[i];
55068
55069             if (!part) {
55070                 continue;
55071             }
55072
55073             type = part.charAt(0);
55074
55075             if (!tagName) {
55076                 tagName = part;
55077             } else if (type === '.') {
55078                 classes = classes || [];
55079                 classes.push(part.substring(1, part.length));
55080             } else if (type === '#' && noId) {
55081                 props.id = part.substring(1, part.length);
55082             }
55083         }
55084
55085         if (classes) {
55086             if (props.className) {
55087                 classes.push(props.className);
55088             }
55089
55090             props.className = classes.join(' ');
55091         }
55092
55093         return props.namespace ? tagName : tagName.toUpperCase();
55094     }
55095
55096     var softSetHook = SoftSetHook;
55097
55098     function SoftSetHook(value) {
55099         if (!(this instanceof SoftSetHook)) {
55100             return new SoftSetHook(value);
55101         }
55102
55103         this.value = value;
55104     }
55105
55106     SoftSetHook.prototype.hook = function (node, propertyName) {
55107         if (node[propertyName] !== this.value) {
55108             node[propertyName] = this.value;
55109         }
55110     };
55111
55112     /*global window, global*/
55113
55114     var root = typeof window !== 'undefined' ?
55115         window : typeof commonjsGlobal !== 'undefined' ?
55116         commonjsGlobal : {};
55117
55118     var individual = Individual;
55119
55120     function Individual(key, value) {
55121         if (key in root) {
55122             return root[key];
55123         }
55124
55125         root[key] = value;
55126
55127         return value;
55128     }
55129
55130     var oneVersion = OneVersion;
55131
55132     function OneVersion(moduleName, version, defaultValue) {
55133         var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName;
55134         var enforceKey = key + '_ENFORCE_SINGLETON';
55135
55136         var versionValue = individual(enforceKey, version);
55137
55138         if (versionValue !== version) {
55139             throw new Error('Can only have one copy of ' +
55140                 moduleName + '.\n' +
55141                 'You already have version ' + versionValue +
55142                 ' installed.\n' +
55143                 'This means you cannot install version ' + version);
55144         }
55145
55146         return individual(key, defaultValue);
55147     }
55148
55149     var MY_VERSION = '7';
55150     oneVersion('ev-store', MY_VERSION);
55151
55152     var hashKey = '__EV_STORE_KEY@' + MY_VERSION;
55153
55154     var evStore = EvStore;
55155
55156     function EvStore(elem) {
55157         var hash = elem[hashKey];
55158
55159         if (!hash) {
55160             hash = elem[hashKey] = {};
55161         }
55162
55163         return hash;
55164     }
55165
55166     var evHook = EvHook;
55167
55168     function EvHook(value) {
55169         if (!(this instanceof EvHook)) {
55170             return new EvHook(value);
55171         }
55172
55173         this.value = value;
55174     }
55175
55176     EvHook.prototype.hook = function (node, propertyName) {
55177         var es = evStore(node);
55178         var propName = propertyName.substr(3);
55179
55180         es[propName] = this.value;
55181     };
55182
55183     EvHook.prototype.unhook = function(node, propertyName) {
55184         var es = evStore(node);
55185         var propName = propertyName.substr(3);
55186
55187         es[propName] = undefined;
55188     };
55189
55190     var virtualHyperscript = h;
55191
55192     function h(tagName, properties, children) {
55193         var childNodes = [];
55194         var tag, props, key, namespace;
55195
55196         if (!children && isChildren(properties)) {
55197             children = properties;
55198             props = {};
55199         }
55200
55201         props = props || properties || {};
55202         tag = parseTag_1(tagName, props);
55203
55204         // support keys
55205         if (props.hasOwnProperty('key')) {
55206             key = props.key;
55207             props.key = undefined;
55208         }
55209
55210         // support namespace
55211         if (props.hasOwnProperty('namespace')) {
55212             namespace = props.namespace;
55213             props.namespace = undefined;
55214         }
55215
55216         // fix cursor bug
55217         if (tag === 'INPUT' &&
55218             !namespace &&
55219             props.hasOwnProperty('value') &&
55220             props.value !== undefined &&
55221             !isVhook(props.value)
55222         ) {
55223             props.value = softSetHook(props.value);
55224         }
55225
55226         transformProperties(props);
55227
55228         if (children !== undefined && children !== null) {
55229             addChild(children, childNodes, tag, props);
55230         }
55231
55232
55233         return new vnode(tag, props, childNodes, key, namespace);
55234     }
55235
55236     function addChild(c, childNodes, tag, props) {
55237         if (typeof c === 'string') {
55238             childNodes.push(new vtext(c));
55239         } else if (typeof c === 'number') {
55240             childNodes.push(new vtext(String(c)));
55241         } else if (isChild(c)) {
55242             childNodes.push(c);
55243         } else if (xIsArray(c)) {
55244             for (var i = 0; i < c.length; i++) {
55245                 addChild(c[i], childNodes, tag, props);
55246             }
55247         } else if (c === null || c === undefined) {
55248             return;
55249         } else {
55250             throw UnexpectedVirtualElement({
55251                 foreignObject: c,
55252                 parentVnode: {
55253                     tagName: tag,
55254                     properties: props
55255                 }
55256             });
55257         }
55258     }
55259
55260     function transformProperties(props) {
55261         for (var propName in props) {
55262             if (props.hasOwnProperty(propName)) {
55263                 var value = props[propName];
55264
55265                 if (isVhook(value)) {
55266                     continue;
55267                 }
55268
55269                 if (propName.substr(0, 3) === 'ev-') {
55270                     // add ev-foo support
55271                     props[propName] = evHook(value);
55272                 }
55273             }
55274         }
55275     }
55276
55277     function isChild(x) {
55278         return isVnode(x) || isVtext(x) || isWidget_1(x) || isThunk_1(x);
55279     }
55280
55281     function isChildren(x) {
55282         return typeof x === 'string' || xIsArray(x) || isChild(x);
55283     }
55284
55285     function UnexpectedVirtualElement(data) {
55286         var err = new Error();
55287
55288         err.type = 'virtual-hyperscript.unexpected.virtual-element';
55289         err.message = 'Unexpected virtual child passed to h().\n' +
55290             'Expected a VNode / Vthunk / VWidget / string but:\n' +
55291             'got:\n' +
55292             errorString(data.foreignObject) +
55293             '.\n' +
55294             'The parent vnode is:\n' +
55295             errorString(data.parentVnode);
55296         err.foreignObject = data.foreignObject;
55297         err.parentVnode = data.parentVnode;
55298
55299         return err;
55300     }
55301
55302     function errorString(obj) {
55303         try {
55304             return JSON.stringify(obj, null, '    ');
55305         } catch (e) {
55306             return String(obj);
55307         }
55308     }
55309
55310     var h_1 = virtualHyperscript;
55311
55312     var createElement_1 = createElement_1$1;
55313
55314     var virtualDom = {
55315         diff: diff_1,
55316         patch: patch_1,
55317         h: h_1,
55318         create: createElement_1,
55319         VNode: vnode,
55320         VText: vtext
55321     };
55322
55323     class EventEmitter {
55324         constructor() { this._events = {}; }
55325         /**
55326          * Subscribe to an event by its name.
55327          * @param {string} type - The name of the event
55328          * to subscribe to.
55329          * @param {(event: T) => void} handler - The
55330          * handler called when the event occurs.
55331          */
55332         on(type, handler) {
55333             this._events[type] = this._events[type] || [];
55334             this._events[type].push(handler);
55335         }
55336         /**
55337          * Unsubscribe from an event by its name.
55338          * @param {string} type - The name of the event
55339          * to unsubscribe from.
55340          * @param {(event: T) => void} handler - The
55341          * handler to remove.
55342          */
55343         off(type, handler) {
55344             if (!type) {
55345                 this._events = {};
55346                 return;
55347             }
55348             if (this._listens(type)) {
55349                 const index = this._events[type].indexOf(handler);
55350                 if (index >= 0) {
55351                     this._events[type].splice(index, 1);
55352                 }
55353                 if (!this._events[type].length) {
55354                     delete this._events[type];
55355                 }
55356             }
55357         }
55358         /**
55359          * @ignore
55360          */
55361         fire(type, event) {
55362             if (!this._listens(type)) {
55363                 return;
55364             }
55365             for (const handler of this._events[type]) {
55366                 handler(event);
55367             }
55368         }
55369         _listens(eventType) {
55370             return eventType in this._events;
55371         }
55372     }
55373
55374     class SubscriptionHolder {
55375         constructor() {
55376             this._subscriptions = [];
55377         }
55378         push(subscription) {
55379             this._subscriptions.push(subscription);
55380         }
55381         unsubscribe() {
55382             for (const sub of this._subscriptions) {
55383                 sub.unsubscribe();
55384             }
55385             this._subscriptions = [];
55386         }
55387     }
55388
55389     class Component extends EventEmitter {
55390         constructor(name, container, navigator) {
55391             super();
55392             this._activated$ = new BehaviorSubject(false);
55393             this._configurationSubject$ = new Subject();
55394             this._activated = false;
55395             this._container = container;
55396             this._name = name;
55397             this._navigator = navigator;
55398             this._subscriptions = new SubscriptionHolder();
55399             this._configuration$ =
55400                 this._configurationSubject$.pipe(startWith(this.defaultConfiguration), scan((conf, newConf) => {
55401                     for (let key in newConf) {
55402                         if (newConf.hasOwnProperty(key)) {
55403                             conf[key] = newConf[key];
55404                         }
55405                     }
55406                     return conf;
55407                 }), publishReplay(1), refCount());
55408             this._configuration$.subscribe(() => { });
55409         }
55410         /**
55411          * Get activated.
55412          *
55413          * @returns {boolean} Value indicating if the component is
55414          * currently active.
55415          */
55416         get activated() {
55417             return this._activated;
55418         }
55419         /** @ignore */
55420         get activated$() {
55421             return this._activated$;
55422         }
55423         /**
55424          * Get default configuration.
55425          *
55426          * @returns {TConfiguration} Default configuration for component.
55427          */
55428         get defaultConfiguration() {
55429             return this._getDefaultConfiguration();
55430         }
55431         /** @ignore */
55432         get configuration$() {
55433             return this._configuration$;
55434         }
55435         /**
55436          * Get name.
55437          *
55438          * @description The name of the component. Used when interacting with the
55439          * component through the Viewer's API.
55440          */
55441         get name() {
55442             return this._name;
55443         }
55444         /** @ignore */
55445         activate(conf) {
55446             if (this._activated) {
55447                 return;
55448             }
55449             if (conf !== undefined) {
55450                 this._configurationSubject$.next(conf);
55451             }
55452             this._activated = true;
55453             this._activate();
55454             this._activated$.next(true);
55455         }
55456         /**
55457          * Configure the component.
55458          *
55459          * @param configuration Component configuration.
55460          */
55461         configure(configuration) {
55462             this._configurationSubject$.next(configuration);
55463         }
55464         /** @ignore */
55465         deactivate() {
55466             if (!this._activated) {
55467                 return;
55468             }
55469             this._activated = false;
55470             this._deactivate();
55471             this._container.domRenderer.clear(this._name);
55472             this._container.glRenderer.clear(this._name);
55473             this._activated$.next(false);
55474         }
55475         /** @inheritdoc */
55476         fire(type, event) {
55477             super.fire(type, event);
55478         }
55479         /** @inheritdoc */
55480         off(type, handler) {
55481             super.off(type, handler);
55482         }
55483         /** @inheritdoc */
55484         on(type, handler) {
55485             super.on(type, handler);
55486         }
55487         /**
55488          * Detect the viewer's new width and height and resize the component's
55489          * rendered elements accordingly if applicable.
55490          *
55491          * @ignore
55492          */
55493         resize() { return; }
55494     }
55495
55496     var CoverState;
55497     (function (CoverState) {
55498         CoverState[CoverState["Hidden"] = 0] = "Hidden";
55499         CoverState[CoverState["Loading"] = 1] = "Loading";
55500         CoverState[CoverState["Visible"] = 2] = "Visible";
55501     })(CoverState || (CoverState = {}));
55502
55503     class CoverComponent extends Component {
55504         constructor(name, container, navigator) {
55505             super(name, container, navigator);
55506         }
55507         _activate() {
55508             const originalSrc$ = this.configuration$.pipe(first((c) => {
55509                 return !!c.id;
55510             }), filter((c) => {
55511                 return !c.src;
55512             }), switchMap((c) => {
55513                 return this._getImageSrc$(c.id).pipe(catchError((error) => {
55514                     console.error(error);
55515                     return empty();
55516                 }));
55517             }), publishReplay(1), refCount());
55518             const subs = this._subscriptions;
55519             subs.push(originalSrc$.pipe(map((src) => {
55520                 return { src: src };
55521             }))
55522                 .subscribe((c) => {
55523                 this._configurationSubject$.next(c);
55524             }));
55525             subs.push(combineLatest(this.configuration$, originalSrc$).pipe(filter(([c, src]) => {
55526                 return !!c.src && c.src !== src;
55527             }), first())
55528                 .subscribe(([, src]) => {
55529                 window.URL.revokeObjectURL(src);
55530             }));
55531             subs.push(this._configuration$.pipe(distinctUntilChanged(undefined, (configuration) => {
55532                 return configuration.state;
55533             }), switchMap((configuration) => {
55534                 return combineLatest(of(configuration.state), this._navigator.stateService.currentImage$);
55535             }), switchMap(([state, image]) => {
55536                 const keySrc$ = combineLatest(of(image.id), image.image$.pipe(filter((imageElement) => {
55537                     return !!imageElement;
55538                 }), map((imageElement) => {
55539                     return imageElement.src;
55540                 })));
55541                 return state === CoverState.Visible ? keySrc$.pipe(first()) : keySrc$;
55542             }), distinctUntilChanged(([k1, s1], [k2, s2]) => {
55543                 return k1 === k2 && s1 === s2;
55544             }), map(([key, src]) => {
55545                 return { id: key, src: src };
55546             }))
55547                 .subscribe(this._configurationSubject$));
55548             subs.push(combineLatest(this._configuration$, this._container.configurationService.exploreUrl$, this._container.renderService.size$).pipe(map(([configuration, exploreUrl, size]) => {
55549                 if (!configuration.src) {
55550                     return { name: this._name, vNode: virtualDom.h("div", []) };
55551                 }
55552                 const compactClass = size.width <= 640 || size.height <= 480 ? ".mapillary-cover-compact" : "";
55553                 if (configuration.state === CoverState.Hidden) {
55554                     const doneContainer = virtualDom.h("div.mapillary-cover-container.mapillary-cover-done" + compactClass, [this._getCoverBackgroundVNode(configuration)]);
55555                     return { name: this._name, vNode: doneContainer };
55556                 }
55557                 const container = virtualDom.h("div.mapillary-cover-container" + compactClass, [this._getCoverButtonVNode(configuration, exploreUrl)]);
55558                 return { name: this._name, vNode: container };
55559             }))
55560                 .subscribe(this._container.domRenderer.render$));
55561         }
55562         _deactivate() {
55563             this._subscriptions.unsubscribe();
55564         }
55565         _getDefaultConfiguration() {
55566             return { state: CoverState.Visible };
55567         }
55568         _getCoverButtonVNode(configuration, exploreUrl) {
55569             const cover = configuration.state === CoverState.Loading ? "div.mapillary-cover.mapillary-cover-loading" : "div.mapillary-cover";
55570             const coverButton = virtualDom.h("div.mapillary-cover-button", [virtualDom.h("div.mapillary-cover-button-icon", [])]);
55571             const coverLogo = virtualDom.h("a.mapillary-cover-logo", { href: exploreUrl, target: "_blank" }, []);
55572             const coverIndicator = virtualDom.h("div.mapillary-cover-indicator", { onclick: () => { this.configure({ state: CoverState.Loading }); } }, []);
55573             return virtualDom.h(cover, [
55574                 this._getCoverBackgroundVNode(configuration),
55575                 coverIndicator,
55576                 coverButton,
55577                 coverLogo,
55578             ]);
55579         }
55580         _getCoverBackgroundVNode(conf) {
55581             const properties = {
55582                 style: { backgroundImage: `url(${conf.src})` },
55583             };
55584             const children = [];
55585             if (conf.state === CoverState.Loading) {
55586                 children.push(virtualDom.h("div.mapillary-cover-spinner", {}, []));
55587             }
55588             return virtualDom.h("div.mapillary-cover-background", properties, children);
55589         }
55590         _getImageSrc$(id) {
55591             return Observable.create((subscriber) => {
55592                 this._navigator.api.getImages$([id])
55593                     .subscribe((items) => {
55594                     for (const item of items) {
55595                         if (item.node_id !== id) {
55596                             continue;
55597                         }
55598                         this._navigator.api.data
55599                             .getImageBuffer(item.node.thumb.url)
55600                             .then((buffer) => {
55601                             const image = new Image();
55602                             image.crossOrigin = "Anonymous";
55603                             image.onload = () => {
55604                                 subscriber.next(image.src);
55605                                 subscriber.complete();
55606                             };
55607                             image.onerror = () => {
55608                                 subscriber.error(new Error(`Failed to load cover ` +
55609                                     `image (${id})`));
55610                             };
55611                             const blob = new Blob([buffer]);
55612                             image.src = window.URL
55613                                 .createObjectURL(blob);
55614                         }, (error) => {
55615                             subscriber.error(error);
55616                         });
55617                         return;
55618                     }
55619                     subscriber.error(new MapillaryError(`Non existent cover key: ${id}`));
55620                 }, (error) => {
55621                     subscriber.error(error);
55622                 });
55623             });
55624         }
55625     }
55626     CoverComponent.componentName = "cover";
55627
55628     class AttributionComponent extends Component {
55629         _activate() {
55630             this._subscriptions.push(combineLatest(this._container.configurationService.exploreUrl$, this._navigator.stateService.currentImage$, this._container.renderService.size$).pipe(map(([exploreUrl, image, size]) => {
55631                 const attribution = this._makeAttribution(image.creatorUsername, exploreUrl, image.id, image.capturedAt, size.width);
55632                 return {
55633                     name: this._name,
55634                     vNode: attribution,
55635                 };
55636             }))
55637                 .subscribe(this._container.domRenderer.render$));
55638         }
55639         _deactivate() {
55640             this._subscriptions.unsubscribe();
55641         }
55642         _getDefaultConfiguration() {
55643             return {};
55644         }
55645         makeImageUrl(exploreUrl, id) {
55646             return `${exploreUrl}/app/?pKey=${id}&focus=photo`;
55647         }
55648         _makeAttribution(creatorUsername, exploreUrl, imageId, capturedAt, viewportWidth) {
55649             const compact = viewportWidth <= 640;
55650             const date = this._makeDate(capturedAt, compact);
55651             const by = this._makeBy(creatorUsername, exploreUrl, imageId, compact);
55652             const compactClass = compact ?
55653                 ".mapillary-attribution-compact" : "";
55654             return virtualDom.h("div.mapillary-attribution-container" + compactClass, {}, [...by, date]);
55655         }
55656         _makeBy(creatorUsername, exploreUrl, imageId, compact) {
55657             const icon = virtualDom.h("div.mapillary-attribution-logo", []);
55658             return creatorUsername ?
55659                 this._makeCreatorBy(icon, creatorUsername, exploreUrl, imageId, compact) :
55660                 this._makeGeneralBy(icon, exploreUrl, imageId, compact);
55661         }
55662         _makeCreatorBy(icon, creatorUsername, exploreUrl, imageId, compact) {
55663             const mapillary = virtualDom.h("a.mapillary-attribution-icon-container", { href: exploreUrl, rel: "noreferrer", target: "_blank" }, [icon]);
55664             const content = compact ?
55665                 `${creatorUsername}` : `image by ${creatorUsername}`;
55666             const imageBy = virtualDom.h("div.mapillary-attribution-username", { textContent: content }, []);
55667             const image = virtualDom.h("a.mapillary-attribution-image-container", {
55668                 href: this.makeImageUrl(exploreUrl, imageId),
55669                 rel: "noreferrer",
55670                 target: "_blank",
55671             }, [imageBy]);
55672             return [mapillary, image];
55673         }
55674         _makeGeneralBy(icon, exploreUrl, imageId, compact) {
55675             const imagesBy = virtualDom.h("div.mapillary-attribution-username", { textContent: 'images by' }, []);
55676             const mapillary = virtualDom.h("div.mapillary-attribution-icon-container", {}, [icon]);
55677             const contributors = virtualDom.h("div.mapillary-attribution-username", { textContent: 'contributors' }, []);
55678             const children = [mapillary, contributors];
55679             if (!compact) {
55680                 children.unshift(imagesBy);
55681             }
55682             const image = virtualDom.h("a.mapillary-attribution-image-container", {
55683                 href: this.makeImageUrl(exploreUrl, imageId),
55684                 rel: "noreferrer",
55685                 target: "_blank",
55686             }, children);
55687             return [image];
55688         }
55689         _makeDate(capturedAt, compact) {
55690             const date = new Date(capturedAt)
55691                 .toDateString()
55692                 .split(" ");
55693             const formatted = (date.length > 3 ?
55694                 compact ?
55695                     [date[3]] :
55696                     [date[1], date[2] + ",", date[3]] :
55697                 date).join(" ");
55698             return virtualDom.h("div.mapillary-attribution-date", { textContent: formatted }, []);
55699         }
55700     }
55701     AttributionComponent.componentName = "attribution";
55702
55703     /**
55704      * @class ViewportCoords
55705      *
55706      * @classdesc Provides methods for calculating 2D coordinate conversions
55707      * as well as 3D projection and unprojection.
55708      *
55709      * Basic coordinates are 2D coordinates on the [0, 1] interval and
55710      * have the origin point, (0, 0), at the top left corner and the
55711      * maximum value, (1, 1), at the bottom right corner of the original
55712      * image.
55713      *
55714      * Viewport coordinates are 2D coordinates on the [-1, 1] interval and
55715      * have the origin point in the center. The bottom left corner point is
55716      * (-1, -1) and the top right corner point is (1, 1).
55717      *
55718      * Canvas coordiantes are 2D pixel coordinates on the [0, canvasWidth] and
55719      * [0, canvasHeight] intervals. The origin point (0, 0) is in the top left
55720      * corner and the maximum value is (canvasWidth, canvasHeight) is in the
55721      * bottom right corner.
55722      *
55723      * 3D coordinates are in the topocentric world reference frame.
55724      */
55725     class ViewportCoords {
55726         constructor() {
55727             this._unprojectDepth = 200;
55728         }
55729         /**
55730          * Convert basic coordinates to canvas coordinates.
55731          *
55732          * @description Transform origin and camera position needs to be the
55733          * equal for reliable return value.
55734          *
55735          * @param {number} basicX - Basic X coordinate.
55736          * @param {number} basicY - Basic Y coordinate.
55737          * @param {HTMLElement} container - The viewer container.
55738          * @param {Transform} transform - Transform of the image to unproject from.
55739          * @param {THREE.Camera} camera - Camera used in rendering.
55740          * @returns {Array<number>} 2D canvas coordinates.
55741          */
55742         basicToCanvas(basicX, basicY, container, transform, camera) {
55743             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
55744             const canvas = this.projectToCanvas(point3d, container, camera);
55745             return canvas;
55746         }
55747         /**
55748          * Convert basic coordinates to canvas coordinates safely. If 3D point is
55749          * behind camera null will be returned.
55750          *
55751          * @description Transform origin and camera position needs to be the
55752          * equal for reliable return value.
55753          *
55754          * @param {number} basicX - Basic X coordinate.
55755          * @param {number} basicY - Basic Y coordinate.
55756          * @param {HTMLElement} container - The viewer container.
55757          * @param {Transform} transform - Transform of the image to unproject from.
55758          * @param {THREE.Camera} camera - Camera used in rendering.
55759          * @returns {Array<number>} 2D canvas coordinates if the basic point represents a 3D point
55760          * in front of the camera, otherwise null.
55761          */
55762         basicToCanvasSafe(basicX, basicY, container, transform, camera) {
55763             const viewport = this.basicToViewportSafe(basicX, basicY, transform, camera);
55764             if (viewport === null) {
55765                 return null;
55766             }
55767             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
55768             return canvas;
55769         }
55770         /**
55771          * Convert basic coordinates to viewport coordinates.
55772          *
55773          * @description Transform origin and camera position needs to be the
55774          * equal for reliable return value.
55775          *
55776          * @param {number} basicX - Basic X coordinate.
55777          * @param {number} basicY - Basic Y coordinate.
55778          * @param {Transform} transform - Transform of the image to unproject from.
55779          * @param {THREE.Camera} camera - Camera used in rendering.
55780          * @returns {Array<number>} 2D viewport coordinates.
55781          */
55782         basicToViewport(basicX, basicY, transform, camera) {
55783             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
55784             const viewport = this.projectToViewport(point3d, camera);
55785             return viewport;
55786         }
55787         /**
55788          * Convert basic coordinates to viewport coordinates safely. If 3D point is
55789          * behind camera null will be returned.
55790          *
55791          * @description Transform origin and camera position needs to be the
55792          * equal for reliable return value.
55793          *
55794          * @param {number} basicX - Basic X coordinate.
55795          * @param {number} basicY - Basic Y coordinate.
55796          * @param {Transform} transform - Transform of the image to unproject from.
55797          * @param {THREE.Camera} camera - Camera used in rendering.
55798          * @returns {Array<number>} 2D viewport coordinates.
55799          */
55800         basicToViewportSafe(basicX, basicY, transform, camera) {
55801             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
55802             const pointCamera = this.worldToCamera(point3d, camera);
55803             if (pointCamera[2] > 0) {
55804                 return null;
55805             }
55806             const viewport = this.projectToViewport(point3d, camera);
55807             return viewport;
55808         }
55809         /**
55810          * Convert camera 3D coordinates to viewport coordinates.
55811          *
55812          * @param {number} pointCamera - 3D point in camera coordinate system.
55813          * @param {THREE.Camera} camera - Camera used in rendering.
55814          * @returns {Array<number>} 2D viewport coordinates.
55815          */
55816         cameraToViewport(pointCamera, camera) {
55817             const viewport = new Vector3().fromArray(pointCamera)
55818                 .applyMatrix4(camera.projectionMatrix);
55819             return [viewport.x, viewport.y];
55820         }
55821         /**
55822          * Get canvas pixel position from event.
55823          *
55824          * @param {Event} event - Event containing clientX and clientY properties.
55825          * @param {HTMLElement} element - HTML element.
55826          * @returns {Array<number>} 2D canvas coordinates.
55827          */
55828         canvasPosition(event, element) {
55829             const clientRect = element.getBoundingClientRect();
55830             const canvasX = event.clientX - clientRect.left - element.clientLeft;
55831             const canvasY = event.clientY - clientRect.top - element.clientTop;
55832             return [canvasX, canvasY];
55833         }
55834         /**
55835          * Convert canvas coordinates to basic coordinates.
55836          *
55837          * @description Transform origin and camera position needs to be the
55838          * equal for reliable return value.
55839          *
55840          * @param {number} canvasX - Canvas X coordinate.
55841          * @param {number} canvasY - Canvas Y coordinate.
55842          * @param {HTMLElement} container - The viewer container.
55843          * @param {Transform} transform - Transform of the image to unproject from.
55844          * @param {THREE.Camera} camera - Camera used in rendering.
55845          * @returns {Array<number>} 2D basic coordinates.
55846          */
55847         canvasToBasic(canvasX, canvasY, container, transform, camera) {
55848             const point3d = this.unprojectFromCanvas(canvasX, canvasY, container, camera)
55849                 .toArray();
55850             const basic = transform.projectBasic(point3d);
55851             return basic;
55852         }
55853         /**
55854          * Convert canvas coordinates to viewport coordinates.
55855          *
55856          * @param {number} canvasX - Canvas X coordinate.
55857          * @param {number} canvasY - Canvas Y coordinate.
55858          * @param {HTMLElement} container - The viewer container.
55859          * @returns {Array<number>} 2D viewport coordinates.
55860          */
55861         canvasToViewport(canvasX, canvasY, container) {
55862             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
55863             const viewportX = 2 * canvasX / canvasWidth - 1;
55864             const viewportY = 1 - 2 * canvasY / canvasHeight;
55865             return [viewportX, viewportY];
55866         }
55867         /**
55868          * Determines the width and height of the container in canvas coordinates.
55869          *
55870          * @param {HTMLElement} container - The viewer container.
55871          * @returns {Array<number>} 2D canvas coordinates.
55872          */
55873         containerToCanvas(container) {
55874             return [container.offsetWidth, container.offsetHeight];
55875         }
55876         /**
55877          * Determine basic distances from image to canvas corners.
55878          *
55879          * @description Transform origin and camera position needs to be the
55880          * equal for reliable return value.
55881          *
55882          * Determines the smallest basic distance for every side of the canvas.
55883          *
55884          * @param {Transform} transform - Transform of the image to unproject from.
55885          * @param {THREE.Camera} camera - Camera used in rendering.
55886          * @returns {Array<number>} Array of basic distances as [top, right, bottom, left].
55887          */
55888         getBasicDistances(transform, camera) {
55889             const topLeftBasic = this.viewportToBasic(-1, 1, transform, camera);
55890             const topRightBasic = this.viewportToBasic(1, 1, transform, camera);
55891             const bottomRightBasic = this.viewportToBasic(1, -1, transform, camera);
55892             const bottomLeftBasic = this.viewportToBasic(-1, -1, transform, camera);
55893             let topBasicDistance = 0;
55894             let rightBasicDistance = 0;
55895             let bottomBasicDistance = 0;
55896             let leftBasicDistance = 0;
55897             if (topLeftBasic[1] < 0 && topRightBasic[1] < 0) {
55898                 topBasicDistance = topLeftBasic[1] > topRightBasic[1] ?
55899                     -topLeftBasic[1] :
55900                     -topRightBasic[1];
55901             }
55902             if (topRightBasic[0] > 1 && bottomRightBasic[0] > 1) {
55903                 rightBasicDistance = topRightBasic[0] < bottomRightBasic[0] ?
55904                     topRightBasic[0] - 1 :
55905                     bottomRightBasic[0] - 1;
55906             }
55907             if (bottomRightBasic[1] > 1 && bottomLeftBasic[1] > 1) {
55908                 bottomBasicDistance = bottomRightBasic[1] < bottomLeftBasic[1] ?
55909                     bottomRightBasic[1] - 1 :
55910                     bottomLeftBasic[1] - 1;
55911             }
55912             if (bottomLeftBasic[0] < 0 && topLeftBasic[0] < 0) {
55913                 leftBasicDistance = bottomLeftBasic[0] > topLeftBasic[0] ?
55914                     -bottomLeftBasic[0] :
55915                     -topLeftBasic[0];
55916             }
55917             return [topBasicDistance, rightBasicDistance, bottomBasicDistance, leftBasicDistance];
55918         }
55919         /**
55920          * Determine pixel distances from image to canvas corners.
55921          *
55922          * @description Transform origin and camera position needs to be the
55923          * equal for reliable return value.
55924          *
55925          * Determines the smallest pixel distance for every side of the canvas.
55926          *
55927          * @param {HTMLElement} container - The viewer container.
55928          * @param {Transform} transform - Transform of the image to unproject from.
55929          * @param {THREE.Camera} camera - Camera used in rendering.
55930          * @returns {Array<number>} Array of pixel distances as [top, right, bottom, left].
55931          */
55932         getPixelDistances(container, transform, camera) {
55933             const topLeftBasic = this.viewportToBasic(-1, 1, transform, camera);
55934             const topRightBasic = this.viewportToBasic(1, 1, transform, camera);
55935             const bottomRightBasic = this.viewportToBasic(1, -1, transform, camera);
55936             const bottomLeftBasic = this.viewportToBasic(-1, -1, transform, camera);
55937             let topPixelDistance = 0;
55938             let rightPixelDistance = 0;
55939             let bottomPixelDistance = 0;
55940             let leftPixelDistance = 0;
55941             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
55942             if (topLeftBasic[1] < 0 && topRightBasic[1] < 0) {
55943                 const basicX = topLeftBasic[1] > topRightBasic[1] ?
55944                     topLeftBasic[0] :
55945                     topRightBasic[0];
55946                 const canvas = this.basicToCanvas(basicX, 0, container, transform, camera);
55947                 topPixelDistance = canvas[1] > 0 ? canvas[1] : 0;
55948             }
55949             if (topRightBasic[0] > 1 && bottomRightBasic[0] > 1) {
55950                 const basicY = topRightBasic[0] < bottomRightBasic[0] ?
55951                     topRightBasic[1] :
55952                     bottomRightBasic[1];
55953                 const canvas = this.basicToCanvas(1, basicY, container, transform, camera);
55954                 rightPixelDistance = canvas[0] < canvasWidth ? canvasWidth - canvas[0] : 0;
55955             }
55956             if (bottomRightBasic[1] > 1 && bottomLeftBasic[1] > 1) {
55957                 const basicX = bottomRightBasic[1] < bottomLeftBasic[1] ?
55958                     bottomRightBasic[0] :
55959                     bottomLeftBasic[0];
55960                 const canvas = this.basicToCanvas(basicX, 1, container, transform, camera);
55961                 bottomPixelDistance = canvas[1] < canvasHeight ? canvasHeight - canvas[1] : 0;
55962             }
55963             if (bottomLeftBasic[0] < 0 && topLeftBasic[0] < 0) {
55964                 const basicY = bottomLeftBasic[0] > topLeftBasic[0] ?
55965                     bottomLeftBasic[1] :
55966                     topLeftBasic[1];
55967                 const canvas = this.basicToCanvas(0, basicY, container, transform, camera);
55968                 leftPixelDistance = canvas[0] > 0 ? canvas[0] : 0;
55969             }
55970             return [topPixelDistance, rightPixelDistance, bottomPixelDistance, leftPixelDistance];
55971         }
55972         /**
55973          * Determine if an event occured inside an element.
55974          *
55975          * @param {Event} event - Event containing clientX and clientY properties.
55976          * @param {HTMLElement} element - HTML element.
55977          * @returns {boolean} Value indicating if the event occured inside the element or not.
55978          */
55979         insideElement(event, element) {
55980             const clientRect = element.getBoundingClientRect();
55981             const minX = clientRect.left + element.clientLeft;
55982             const maxX = minX + element.clientWidth;
55983             const minY = clientRect.top + element.clientTop;
55984             const maxY = minY + element.clientHeight;
55985             return event.clientX > minX &&
55986                 event.clientX < maxX &&
55987                 event.clientY > minY &&
55988                 event.clientY < maxY;
55989         }
55990         /**
55991          * Project 3D world coordinates to canvas coordinates.
55992          *
55993          * @param {Array<number>} point3D - 3D world coordinates.
55994          * @param {HTMLElement} container - The viewer container.
55995          * @param {THREE.Camera} camera - Camera used in rendering.
55996          * @returns {Array<number>} 2D canvas coordinates.
55997          */
55998         projectToCanvas(point3d, container, camera) {
55999             const viewport = this.projectToViewport(point3d, camera);
56000             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
56001             return canvas;
56002         }
56003         /**
56004          * Project 3D world coordinates to canvas coordinates safely. If 3D
56005          * point is behind camera null will be returned.
56006          *
56007          * @param {Array<number>} point3D - 3D world coordinates.
56008          * @param {HTMLElement} container - The viewer container.
56009          * @param {THREE.Camera} camera - Camera used in rendering.
56010          * @returns {Array<number>} 2D canvas coordinates.
56011          */
56012         projectToCanvasSafe(point3d, container, camera) {
56013             const pointCamera = this.worldToCamera(point3d, camera);
56014             if (pointCamera[2] > 0) {
56015                 return null;
56016             }
56017             const viewport = this.projectToViewport(point3d, camera);
56018             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
56019             return canvas;
56020         }
56021         /**
56022          * Project 3D world coordinates to viewport coordinates.
56023          *
56024          * @param {Array<number>} point3D - 3D world coordinates.
56025          * @param {THREE.Camera} camera - Camera used in rendering.
56026          * @returns {Array<number>} 2D viewport coordinates.
56027          */
56028         projectToViewport(point3d, camera) {
56029             const viewport = new Vector3(point3d[0], point3d[1], point3d[2])
56030                 .project(camera);
56031             return [viewport.x, viewport.y];
56032         }
56033         /**
56034          * Uproject canvas coordinates to 3D world coordinates.
56035          *
56036          * @param {number} canvasX - Canvas X coordinate.
56037          * @param {number} canvasY - Canvas Y coordinate.
56038          * @param {HTMLElement} container - The viewer container.
56039          * @param {THREE.Camera} camera - Camera used in rendering.
56040          * @returns {Array<number>} 3D world coordinates.
56041          */
56042         unprojectFromCanvas(canvasX, canvasY, container, camera) {
56043             const viewport = this.canvasToViewport(canvasX, canvasY, container);
56044             const point3d = this.unprojectFromViewport(viewport[0], viewport[1], camera);
56045             return point3d;
56046         }
56047         /**
56048          * Unproject viewport coordinates to 3D world coordinates.
56049          *
56050          * @param {number} viewportX - Viewport X coordinate.
56051          * @param {number} viewportY - Viewport Y coordinate.
56052          * @param {THREE.Camera} camera - Camera used in rendering.
56053          * @returns {Array<number>} 3D world coordinates.
56054          */
56055         unprojectFromViewport(viewportX, viewportY, camera) {
56056             const point3d = new Vector3(viewportX, viewportY, 1)
56057                 .unproject(camera);
56058             return point3d;
56059         }
56060         /**
56061          * Convert viewport coordinates to basic coordinates.
56062          *
56063          * @description Transform origin and camera position needs to be the
56064          * equal for reliable return value.
56065          *
56066          * @param {number} viewportX - Viewport X coordinate.
56067          * @param {number} viewportY - Viewport Y coordinate.
56068          * @param {Transform} transform - Transform of the image to unproject from.
56069          * @param {THREE.Camera} camera - Camera used in rendering.
56070          * @returns {Array<number>} 2D basic coordinates.
56071          */
56072         viewportToBasic(viewportX, viewportY, transform, camera) {
56073             const point3d = new Vector3(viewportX, viewportY, 1)
56074                 .unproject(camera)
56075                 .toArray();
56076             const basic = transform.projectBasic(point3d);
56077             return basic;
56078         }
56079         /**
56080          * Convert viewport coordinates to canvas coordinates.
56081          *
56082          * @param {number} viewportX - Viewport X coordinate.
56083          * @param {number} viewportY - Viewport Y coordinate.
56084          * @param {HTMLElement} container - The viewer container.
56085          * @returns {Array<number>} 2D canvas coordinates.
56086          */
56087         viewportToCanvas(viewportX, viewportY, container) {
56088             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
56089             const canvasX = canvasWidth * (viewportX + 1) / 2;
56090             const canvasY = -canvasHeight * (viewportY - 1) / 2;
56091             return [canvasX, canvasY];
56092         }
56093         /**
56094          * Convert 3D world coordinates to 3D camera coordinates.
56095          *
56096          * @param {number} point3D - 3D point in world coordinate system.
56097          * @param {THREE.Camera} camera - Camera used in rendering.
56098          * @returns {Array<number>} 3D camera coordinates.
56099          */
56100         worldToCamera(point3d, camera) {
56101             const pointCamera = new Vector3(point3d[0], point3d[1], point3d[2])
56102                 .applyMatrix4(camera.matrixWorldInverse);
56103             return pointCamera.toArray();
56104         }
56105     }
56106
56107     /**
56108      * Enumeration for component size.
56109      * @enum {number}
56110      * @readonly
56111      * @description May be used by a component to allow for resizing
56112      * of the UI elements rendered by the component.
56113      */
56114     exports.ComponentSize = void 0;
56115     (function (ComponentSize) {
56116         /**
56117          * Automatic size. The size of the elements will automatically
56118          * change at a predefined threshold.
56119          */
56120         ComponentSize[ComponentSize["Automatic"] = 0] = "Automatic";
56121         /**
56122          * Large size. The size of the elements will be fixed until another
56123          * component size is configured.
56124          */
56125         ComponentSize[ComponentSize["Large"] = 1] = "Large";
56126         /**
56127          * Small size. The size of the elements will be fixed until another
56128          * component size is configured.
56129          */
56130         ComponentSize[ComponentSize["Small"] = 2] = "Small";
56131     })(exports.ComponentSize || (exports.ComponentSize = {}));
56132
56133     /**
56134      * @class BearingComponent
56135      *
56136      * @classdesc Component for indicating bearing and field of view.
56137      *
56138      * @example
56139      * ```js
56140      * var viewer = new Viewer({ ... });
56141      * var bearingComponent = viewer.getComponent("bearing");
56142      * bearingComponent.configure({ size: ComponentSize.Small });
56143      * ```
56144      */
56145     class BearingComponent extends Component {
56146         /** @ignore */
56147         constructor(name, container, navigator) {
56148             super(name, container, navigator);
56149             this._spatial = new Spatial();
56150             this._viewportCoords = new ViewportCoords();
56151             this._svgNamespace = "http://www.w3.org/2000/svg";
56152             this._distinctThreshold = Math.PI / 360;
56153             this._animationSpeed = 0.075;
56154             this._unitBezier = new unitbezier(0.74, 0.67, 0.38, 0.96);
56155         }
56156         _activate() {
56157             const subs = this._subscriptions;
56158             const cameraBearingFov$ = this._container.renderService.renderCamera$.pipe(map((rc) => {
56159                 let vFov = this._spatial.degToRad(rc.perspective.fov);
56160                 let hFov = rc.perspective.aspect === Number.POSITIVE_INFINITY ?
56161                     Math.PI :
56162                     Math.atan(rc.perspective.aspect * Math.tan(0.5 * vFov)) * 2;
56163                 return [this._spatial.azimuthalToBearing(rc.rotation.phi), hFov];
56164             }), distinctUntilChanged((a1, a2) => {
56165                 return Math.abs(a2[0] - a1[0]) < this._distinctThreshold &&
56166                     Math.abs(a2[1] - a1[1]) < this._distinctThreshold;
56167             }));
56168             const imageFov$ = combineLatest(this._navigator.stateService.currentState$.pipe(distinctUntilChanged(undefined, (frame) => {
56169                 return frame.state.currentImage.id;
56170             })), this._navigator.panService.panImages$).pipe(map(([frame, panImages]) => {
56171                 const image = frame.state.currentImage;
56172                 const transform = frame.state.currentTransform;
56173                 if (isSpherical(image.cameraType)) {
56174                     return [Math.PI, Math.PI];
56175                 }
56176                 const currentProjectedPoints = this._computeProjectedPoints(transform);
56177                 const hFov = this._spatial
56178                     .degToRad(this._computeHorizontalFov(currentProjectedPoints));
56179                 let hFovLeft = hFov / 2;
56180                 let hFovRight = hFov / 2;
56181                 for (const [n, , f] of panImages) {
56182                     const diff = this._spatial.wrap(n.compassAngle - image.compassAngle, -180, 180);
56183                     if (diff < 0) {
56184                         hFovLeft = this._spatial.degToRad(Math.abs(diff)) + f / 2;
56185                     }
56186                     else {
56187                         hFovRight = this._spatial.degToRad(Math.abs(diff)) + f / 2;
56188                     }
56189                 }
56190                 return [hFovLeft, hFovRight];
56191             }), distinctUntilChanged(([hFovLeft1, hFovRight1], [hFovLeft2, hFovRight2]) => {
56192                 return Math.abs(hFovLeft2 - hFovLeft1) < this._distinctThreshold &&
56193                     Math.abs(hFovRight2 - hFovRight1) < this._distinctThreshold;
56194             }));
56195             const offset$ = combineLatest(this._navigator.stateService.currentState$.pipe(distinctUntilChanged(undefined, (frame) => {
56196                 return frame.state.currentImage.id;
56197             })), this._container.renderService.bearing$).pipe(map(([frame, bearing]) => {
56198                 const offset = this._spatial.degToRad(frame.state.currentImage.compassAngle - bearing);
56199                 return offset;
56200             }));
56201             const imageFovOperation$ = new Subject();
56202             const smoothImageFov$ = imageFovOperation$.pipe(scan((state, operation) => {
56203                 return operation(state);
56204             }, { alpha: 0, curr: [0, 0, 0], prev: [0, 0, 0] }), map((state) => {
56205                 const alpha = this._unitBezier.solve(state.alpha);
56206                 const curr = state.curr;
56207                 const prev = state.prev;
56208                 return [
56209                     this._interpolate(prev[0], curr[0], alpha),
56210                     this._interpolate(prev[1], curr[1], alpha),
56211                 ];
56212             }));
56213             subs.push(imageFov$.pipe(map((nbf) => {
56214                 return (state) => {
56215                     const a = this._unitBezier.solve(state.alpha);
56216                     const c = state.curr;
56217                     const p = state.prev;
56218                     const prev = [
56219                         this._interpolate(p[0], c[0], a),
56220                         this._interpolate(p[1], c[1], a),
56221                     ];
56222                     const curr = nbf.slice();
56223                     return {
56224                         alpha: 0,
56225                         curr: curr,
56226                         prev: prev,
56227                     };
56228                 };
56229             }))
56230                 .subscribe(imageFovOperation$));
56231             subs.push(imageFov$.pipe(switchMap(() => {
56232                 return this._container.renderService.renderCameraFrame$.pipe(skip(1), scan((alpha) => {
56233                     return alpha + this._animationSpeed;
56234                 }, 0), takeWhile((alpha) => {
56235                     return alpha <= 1 + this._animationSpeed;
56236                 }), map((alpha) => {
56237                     return Math.min(alpha, 1);
56238                 }));
56239             }), map((alpha) => {
56240                 return (nbfState) => {
56241                     return {
56242                         alpha: alpha,
56243                         curr: nbfState.curr.slice(),
56244                         prev: nbfState.prev.slice(),
56245                     };
56246                 };
56247             }))
56248                 .subscribe(imageFovOperation$));
56249             const imageBearingFov$ = combineLatest(offset$, smoothImageFov$).pipe(map(([offset, fov]) => {
56250                 return [offset, fov[0], fov[1]];
56251             }));
56252             subs.push(combineLatest(cameraBearingFov$, imageBearingFov$, this._configuration$, this._container.renderService.size$).pipe(map(([[cb, cf], [no, nfl, nfr], configuration, size]) => {
56253                 const background = this._createBackground(cb);
56254                 const fovIndicator = this._createFovIndicator(nfl, nfr, no);
56255                 const north = this._createNorth(cb);
56256                 const cameraSector = this._createCircleSectorCompass(this._createCircleSector(Math.max(Math.PI / 20, cf), "#FFF"));
56257                 const compact = configuration.size === exports.ComponentSize.Small ||
56258                     configuration.size === exports.ComponentSize.Automatic && size.width < 640 ?
56259                     ".mapillary-bearing-compact" : "";
56260                 return {
56261                     name: this._name,
56262                     vNode: virtualDom.h("div.mapillary-bearing-indicator-container" + compact, { oncontextmenu: (event) => { event.preventDefault(); } }, [
56263                         background,
56264                         fovIndicator,
56265                         north,
56266                         cameraSector,
56267                     ]),
56268                 };
56269             }))
56270                 .subscribe(this._container.domRenderer.render$));
56271         }
56272         _deactivate() {
56273             this._subscriptions.unsubscribe();
56274         }
56275         _getDefaultConfiguration() {
56276             return { size: exports.ComponentSize.Automatic };
56277         }
56278         _createFovIndicator(fovLeft, fovRigth, offset) {
56279             const arc = this._createFovArc(fovLeft, fovRigth);
56280             const group = virtualDom.h("g", {
56281                 attributes: { transform: "translate(18,18)" },
56282                 namespace: this._svgNamespace,
56283             }, [arc]);
56284             const svg = virtualDom.h("svg", {
56285                 attributes: { viewBox: "0 0 36 36" },
56286                 namespace: this._svgNamespace,
56287                 style: {
56288                     height: "36px",
56289                     left: "2px",
56290                     position: "absolute",
56291                     top: "2px",
56292                     transform: `rotateZ(${this._spatial.radToDeg(offset)}deg)`,
56293                     width: "36px",
56294                 },
56295             }, [group]);
56296             return svg;
56297         }
56298         _createFovArc(fovLeft, fovRigth) {
56299             const radius = 16.75;
56300             const strokeWidth = 2.5;
56301             const fov = fovLeft + fovRigth;
56302             if (fov > 2 * Math.PI - Math.PI / 90) {
56303                 return virtualDom.h("circle", {
56304                     attributes: {
56305                         cx: "0",
56306                         cy: "0",
56307                         "fill-opacity": "0",
56308                         r: `${radius}`,
56309                         stroke: "#FFF",
56310                         "stroke-width": `${strokeWidth}`,
56311                     },
56312                     namespace: this._svgNamespace,
56313                 }, []);
56314             }
56315             let arcStart = -Math.PI / 2 - fovLeft;
56316             let arcEnd = arcStart + fov;
56317             let startX = radius * Math.cos(arcStart);
56318             let startY = radius * Math.sin(arcStart);
56319             let endX = radius * Math.cos(arcEnd);
56320             let endY = radius * Math.sin(arcEnd);
56321             let largeArc = fov >= Math.PI ? 1 : 0;
56322             let description = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArc} 1 ${endX} ${endY}`;
56323             return virtualDom.h("path", {
56324                 attributes: {
56325                     d: description,
56326                     "fill-opacity": "0",
56327                     stroke: "#FFF",
56328                     "stroke-width": `${strokeWidth}`,
56329                 },
56330                 namespace: this._svgNamespace,
56331             }, []);
56332         }
56333         _createCircleSectorCompass(cameraSector) {
56334             let group = virtualDom.h("g", {
56335                 attributes: { transform: "translate(1,1)" },
56336                 namespace: this._svgNamespace,
56337             }, [cameraSector]);
56338             let svg = virtualDom.h("svg", {
56339                 attributes: { viewBox: "0 0 2 2" },
56340                 namespace: this._svgNamespace,
56341                 style: {
56342                     height: "26px",
56343                     left: "7px",
56344                     position: "absolute",
56345                     top: "7px",
56346                     width: "26px",
56347                 },
56348             }, [group]);
56349             return svg;
56350         }
56351         _createCircleSector(fov, fill) {
56352             if (fov > 2 * Math.PI - Math.PI / 90) {
56353                 return virtualDom.h("circle", {
56354                     attributes: { cx: "0", cy: "0", fill: fill, r: "1" },
56355                     namespace: this._svgNamespace,
56356                 }, []);
56357             }
56358             let arcStart = -Math.PI / 2 - fov / 2;
56359             let arcEnd = arcStart + fov;
56360             let startX = Math.cos(arcStart);
56361             let startY = Math.sin(arcStart);
56362             let endX = Math.cos(arcEnd);
56363             let endY = Math.sin(arcEnd);
56364             let largeArc = fov >= Math.PI ? 1 : 0;
56365             let description = `M 0 0 ${startX} ${startY} A 1 1 0 ${largeArc} 1 ${endX} ${endY}`;
56366             return virtualDom.h("path", {
56367                 attributes: { d: description, fill: fill },
56368                 namespace: this._svgNamespace,
56369             }, []);
56370         }
56371         _createNorth(bearing) {
56372             const north = virtualDom.h("div.mapillary-bearing-north", []);
56373             const container = virtualDom.h("div.mapillary-bearing-north-container", { style: { transform: `rotateZ(${this._spatial.radToDeg(-bearing)}deg)` } }, [north]);
56374             return container;
56375         }
56376         _createBackground(bearing) {
56377             return virtualDom.h("div.mapillary-bearing-indicator-background", { style: { transform: `rotateZ(${this._spatial.radToDeg(-bearing)}deg)` } }, [
56378                 virtualDom.h("div.mapillary-bearing-indicator-background-circle", []),
56379                 virtualDom.h("div.mapillary-bearing-indicator-background-arrow-container", [
56380                     virtualDom.h("div.mapillary-bearing-indicator-background-arrow", []),
56381                 ]),
56382             ]);
56383         }
56384         _computeProjectedPoints(transform) {
56385             const vertices = [[1, 0]];
56386             const directions = [[0, 0.5]];
56387             const pointsPerLine = 12;
56388             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
56389         }
56390         _computeHorizontalFov(projectedPoints) {
56391             const fovs = projectedPoints
56392                 .map((projectedPoint) => {
56393                 return this._coordToFov(projectedPoint[0]);
56394             });
56395             const fov = Math.min(...fovs);
56396             return fov;
56397         }
56398         _coordToFov(x) {
56399             return this._spatial.radToDeg(2 * Math.atan(x));
56400         }
56401         _interpolate(x1, x2, alpha) {
56402             return (1 - alpha) * x1 + alpha * x2;
56403         }
56404     }
56405     BearingComponent.componentName = "bearing";
56406
56407     class CacheComponent extends Component {
56408         /** @ignore */
56409         constructor(name, container, navigator) {
56410             super(name, container, navigator);
56411         }
56412         _activate() {
56413             const subs = this._subscriptions;
56414             subs.push(combineLatest(this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
56415                 return image.sequenceEdges$;
56416             }), filter((status) => {
56417                 return status.cached;
56418             })), this._configuration$).pipe(switchMap((nc) => {
56419                 let status = nc[0];
56420                 let configuration = nc[1];
56421                 let sequenceDepth = Math.max(0, Math.min(4, configuration.depth.sequence));
56422                 let next$ = this._cache$(status.edges, exports.NavigationDirection.Next, sequenceDepth);
56423                 let prev$ = this._cache$(status.edges, exports.NavigationDirection.Prev, sequenceDepth);
56424                 return merge(next$, prev$).pipe(catchError((error) => {
56425                     console.error("Failed to cache sequence edges.", error);
56426                     return empty();
56427                 }));
56428             }))
56429                 .subscribe(() => { }));
56430             subs.push(combineLatest(this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
56431                 return combineLatest(of(image), image.spatialEdges$.pipe(filter((status) => {
56432                     return status.cached;
56433                 })));
56434             })), this._configuration$).pipe(switchMap(([[image, edgeStatus], configuration]) => {
56435                 let edges = edgeStatus.edges;
56436                 let depth = configuration.depth;
56437                 let sphericalDepth = Math.max(0, Math.min(2, depth.spherical));
56438                 let stepDepth = isSpherical(image.cameraType) ?
56439                     0 : Math.max(0, Math.min(3, depth.step));
56440                 let turnDepth = isSpherical(image.cameraType) ?
56441                     0 : Math.max(0, Math.min(1, depth.turn));
56442                 let spherical$ = this._cache$(edges, exports.NavigationDirection.Spherical, sphericalDepth);
56443                 let forward$ = this._cache$(edges, exports.NavigationDirection.StepForward, stepDepth);
56444                 let backward$ = this._cache$(edges, exports.NavigationDirection.StepBackward, stepDepth);
56445                 let left$ = this._cache$(edges, exports.NavigationDirection.StepLeft, stepDepth);
56446                 let right$ = this._cache$(edges, exports.NavigationDirection.StepRight, stepDepth);
56447                 let turnLeft$ = this._cache$(edges, exports.NavigationDirection.TurnLeft, turnDepth);
56448                 let turnRight$ = this._cache$(edges, exports.NavigationDirection.TurnRight, turnDepth);
56449                 let turnU$ = this._cache$(edges, exports.NavigationDirection.TurnU, turnDepth);
56450                 return merge(forward$, backward$, left$, right$, spherical$, turnLeft$, turnRight$, turnU$).pipe(catchError((error) => {
56451                     console.error("Failed to cache spatial edges.", error);
56452                     return empty();
56453                 }));
56454             }))
56455                 .subscribe(() => { }));
56456         }
56457         _deactivate() {
56458             this._subscriptions.unsubscribe();
56459         }
56460         _getDefaultConfiguration() {
56461             return { depth: { spherical: 1, sequence: 2, step: 1, turn: 0 } };
56462         }
56463         _cache$(edges, direction, depth) {
56464             return zip(of(edges), of(depth)).pipe(expand((ed) => {
56465                 let es = ed[0];
56466                 let d = ed[1];
56467                 let edgesDepths$ = [];
56468                 if (d > 0) {
56469                     for (let edge of es) {
56470                         if (edge.data.direction === direction) {
56471                             edgesDepths$.push(zip(this._navigator.graphService.cacheImage$(edge.target).pipe(mergeMap((n) => {
56472                                 return this._imageToEdges$(n, direction);
56473                             })), of(d - 1)));
56474                         }
56475                     }
56476                 }
56477                 return from(edgesDepths$).pipe(mergeAll());
56478             }), skip(1));
56479         }
56480         _imageToEdges$(image, direction) {
56481             return ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
56482                 image.sequenceEdges$ :
56483                 image.spatialEdges$).pipe(first((status) => {
56484                 return status.cached;
56485             }), map((status) => {
56486                 return status.edges;
56487             }));
56488         }
56489     }
56490     CacheComponent.componentName = "cache";
56491
56492     /**
56493      * @class CancelMapillaryError
56494      *
56495      * @classdesc Error thrown when a move to request has been
56496      * cancelled before completing because of a subsequent request.
56497      */
56498     class CancelMapillaryError extends MapillaryError {
56499         constructor(message) {
56500             super(message != null ? message : "The request was cancelled.");
56501             Object.setPrototypeOf(this, CancelMapillaryError.prototype);
56502             this.name = "CancelMapillaryError";
56503         }
56504     }
56505
56506     /**
56507      * @class DirectionDOMCalculator
56508      * @classdesc Helper class for calculating DOM CSS properties.
56509      */
56510     class DirectionDOMCalculator {
56511         constructor(configuration, size) {
56512             this._spatial = new Spatial();
56513             this._minThresholdWidth = 320;
56514             this._maxThresholdWidth = 1480;
56515             this._minThresholdHeight = 240;
56516             this._maxThresholdHeight = 820;
56517             this._configure(configuration);
56518             this._resize(size);
56519             this._reset();
56520         }
56521         get minWidth() {
56522             return this._minWidth;
56523         }
56524         get maxWidth() {
56525             return this._maxWidth;
56526         }
56527         get containerWidth() {
56528             return this._containerWidth;
56529         }
56530         get containerWidthCss() {
56531             return this._containerWidthCss;
56532         }
56533         get containerMarginCss() {
56534             return this._containerMarginCss;
56535         }
56536         get containerLeftCss() {
56537             return this._containerLeftCss;
56538         }
56539         get containerHeight() {
56540             return this._containerHeight;
56541         }
56542         get containerHeightCss() {
56543             return this._containerHeightCss;
56544         }
56545         get containerBottomCss() {
56546             return this._containerBottomCss;
56547         }
56548         get stepCircleSize() {
56549             return this._stepCircleSize;
56550         }
56551         get stepCircleSizeCss() {
56552             return this._stepCircleSizeCss;
56553         }
56554         get stepCircleMarginCss() {
56555             return this._stepCircleMarginCss;
56556         }
56557         get turnCircleSize() {
56558             return this._turnCircleSize;
56559         }
56560         get turnCircleSizeCss() {
56561             return this._turnCircleSizeCss;
56562         }
56563         get outerRadius() {
56564             return this._outerRadius;
56565         }
56566         get innerRadius() {
56567             return this._innerRadius;
56568         }
56569         get shadowOffset() {
56570             return this._shadowOffset;
56571         }
56572         /**
56573          * Configures the min and max width values.
56574          *
56575          * @param {DirectionConfiguration} configuration Configuration
56576          * with min and max width values.
56577          */
56578         configure(configuration) {
56579             this._configure(configuration);
56580             this._reset();
56581         }
56582         /**
56583          * Resizes all properties according to the width and height
56584          * of the size object.
56585          *
56586          * @param {ViewportSize} size The size of the container element.
56587          */
56588         resize(size) {
56589             this._resize(size);
56590             this._reset();
56591         }
56592         /**
56593          * Calculates the coordinates on the unit circle for an angle.
56594          *
56595          * @param {number} angle Angle in radians.
56596          * @returns {Array<number>} The x and y coordinates on the unit circle.
56597          */
56598         angleToCoordinates(angle) {
56599             return [Math.cos(angle), Math.sin(angle)];
56600         }
56601         /**
56602          * Calculates the coordinates on the unit circle for the
56603          * relative angle between the first and second angle.
56604          *
56605          * @param {number} first Angle in radians.
56606          * @param {number} second Angle in radians.
56607          * @returns {Array<number>} The x and y coordinates on the unit circle
56608          * for the relative angle between the first and second angle.
56609          */
56610         relativeAngleToCoordiantes(first, second) {
56611             let relativeAngle = this._spatial.wrapAngle(first - second);
56612             return this.angleToCoordinates(relativeAngle);
56613         }
56614         _configure(configuration) {
56615             this._minWidth = configuration.minWidth;
56616             this._maxWidth = this._getMaxWidth(configuration.minWidth, configuration.maxWidth);
56617         }
56618         _resize(size) {
56619             this._elementWidth = size.width;
56620             this._elementHeight = size.height;
56621         }
56622         _reset() {
56623             this._containerWidth = this._getContainerWidth(this._elementWidth, this._elementHeight);
56624             this._containerHeight = this._getContainerHeight(this.containerWidth);
56625             this._stepCircleSize = this._getStepCircleDiameter(this._containerHeight);
56626             this._turnCircleSize = this._getTurnCircleDiameter(this.containerHeight);
56627             this._outerRadius = this._getOuterRadius(this._containerHeight);
56628             this._innerRadius = this._getInnerRadius(this._containerHeight);
56629             this._shadowOffset = 3;
56630             this._containerWidthCss = this._numberToCssPixels(this._containerWidth);
56631             this._containerMarginCss = this._numberToCssPixels(-0.5 * this._containerWidth);
56632             this._containerLeftCss = this._numberToCssPixels(Math.floor(0.5 * this._elementWidth));
56633             this._containerHeightCss = this._numberToCssPixels(this._containerHeight);
56634             this._containerBottomCss = this._numberToCssPixels(Math.floor(-0.08 * this._containerHeight));
56635             this._stepCircleSizeCss = this._numberToCssPixels(this._stepCircleSize);
56636             this._stepCircleMarginCss = this._numberToCssPixels(-0.5 * this._stepCircleSize);
56637             this._turnCircleSizeCss = this._numberToCssPixels(this._turnCircleSize);
56638         }
56639         _getContainerWidth(elementWidth, elementHeight) {
56640             let relativeWidth = (elementWidth - this._minThresholdWidth) / (this._maxThresholdWidth - this._minThresholdWidth);
56641             let relativeHeight = (elementHeight - this._minThresholdHeight) / (this._maxThresholdHeight - this._minThresholdHeight);
56642             let coeff = Math.max(0, Math.min(1, Math.min(relativeWidth, relativeHeight)));
56643             coeff = 0.04 * Math.round(25 * coeff);
56644             return this._minWidth + coeff * (this._maxWidth - this._minWidth);
56645         }
56646         _getContainerHeight(containerWidth) {
56647             return 0.77 * containerWidth;
56648         }
56649         _getStepCircleDiameter(containerHeight) {
56650             return 0.34 * containerHeight;
56651         }
56652         _getTurnCircleDiameter(containerHeight) {
56653             return 0.3 * containerHeight;
56654         }
56655         _getOuterRadius(containerHeight) {
56656             return 0.31 * containerHeight;
56657         }
56658         _getInnerRadius(containerHeight) {
56659             return 0.125 * containerHeight;
56660         }
56661         _numberToCssPixels(value) {
56662             return value + "px";
56663         }
56664         _getMaxWidth(value, minWidth) {
56665             return value > minWidth ? value : minWidth;
56666         }
56667     }
56668
56669     /**
56670      * @class DirectionDOMRenderer
56671      * @classdesc DOM renderer for direction arrows.
56672      */
56673     class DirectionDOMRenderer {
56674         constructor(configuration, size) {
56675             this._isEdge = false;
56676             this._spatial = new Spatial();
56677             this._calculator = new DirectionDOMCalculator(configuration, size);
56678             this._image = null;
56679             this._rotation = { phi: 0, theta: 0 };
56680             this._epsilon = 0.5 * Math.PI / 180;
56681             this._highlightKey = null;
56682             this._distinguishSequence = false;
56683             this._needsRender = false;
56684             this._stepEdges = [];
56685             this._turnEdges = [];
56686             this._sphericalEdges = [];
56687             this._sequenceEdgeKeys = [];
56688             this._stepDirections = [
56689                 exports.NavigationDirection.StepForward,
56690                 exports.NavigationDirection.StepBackward,
56691                 exports.NavigationDirection.StepLeft,
56692                 exports.NavigationDirection.StepRight,
56693             ];
56694             this._turnDirections = [
56695                 exports.NavigationDirection.TurnLeft,
56696                 exports.NavigationDirection.TurnRight,
56697                 exports.NavigationDirection.TurnU,
56698             ];
56699             this._turnNames = {};
56700             this._turnNames[exports.NavigationDirection.TurnLeft] = "mapillary-direction-turn-left";
56701             this._turnNames[exports.NavigationDirection.TurnRight] = "mapillary-direction-turn-right";
56702             this._turnNames[exports.NavigationDirection.TurnU] = "mapillary-direction-turn-around";
56703             // detects IE 8-11, then Edge 20+.
56704             let isIE = !!document.documentMode;
56705             this._isEdge = !isIE && !!window.StyleMedia;
56706         }
56707         /**
56708          * Get needs render.
56709          *
56710          * @returns {boolean} Value indicating whether render should be called.
56711          */
56712         get needsRender() {
56713             return this._needsRender;
56714         }
56715         /**
56716          * Renders virtual DOM elements.
56717          *
56718          * @description Calling render resets the needs render property.
56719          */
56720         render(navigator) {
56721             this._needsRender = false;
56722             let rotation = this._rotation;
56723             let steps = [];
56724             let turns = [];
56725             if (isSpherical(this._image.cameraType)) {
56726                 steps = steps.concat(this._createSphericalArrows(navigator, rotation));
56727             }
56728             else {
56729                 steps = steps.concat(this._createPerspectiveToSphericalArrows(navigator, rotation));
56730                 steps = steps.concat(this._createStepArrows(navigator, rotation));
56731                 turns = turns.concat(this._createTurnArrows(navigator));
56732             }
56733             return this._getContainer(steps, turns, rotation);
56734         }
56735         setEdges(edgeStatus, sequence) {
56736             this._setEdges(edgeStatus, sequence);
56737             this._setNeedsRender();
56738         }
56739         /**
56740          * Set image for which to show edges.
56741          *
56742          * @param {Image} image
56743          */
56744         setImage(image) {
56745             this._image = image;
56746             this._clearEdges();
56747             this._setNeedsRender();
56748         }
56749         /**
56750          * Set the render camera to use for calculating rotations.
56751          *
56752          * @param {RenderCamera} renderCamera
56753          */
56754         setRenderCamera(renderCamera) {
56755             let rotation = renderCamera.rotation;
56756             if (Math.abs(rotation.phi - this._rotation.phi) < this._epsilon) {
56757                 return;
56758             }
56759             this._rotation = rotation;
56760             this._setNeedsRender();
56761         }
56762         /**
56763          * Set configuration values.
56764          *
56765          * @param {DirectionConfiguration} configuration
56766          */
56767         setConfiguration(configuration) {
56768             let needsRender = false;
56769             if (this._highlightKey !== configuration.highlightId ||
56770                 this._distinguishSequence !== configuration.distinguishSequence) {
56771                 this._highlightKey = configuration.highlightId;
56772                 this._distinguishSequence = configuration.distinguishSequence;
56773                 needsRender = true;
56774             }
56775             if (this._calculator.minWidth !== configuration.minWidth ||
56776                 this._calculator.maxWidth !== configuration.maxWidth) {
56777                 this._calculator.configure(configuration);
56778                 needsRender = true;
56779             }
56780             if (needsRender) {
56781                 this._setNeedsRender();
56782             }
56783         }
56784         /**
56785          * Detect the element's width and height and resize
56786          * elements accordingly.
56787          *
56788          * @param {ViewportSize} size Size of vßiewer container element.
56789          */
56790         resize(size) {
56791             this._calculator.resize(size);
56792             this._setNeedsRender();
56793         }
56794         _setNeedsRender() {
56795             if (this._image != null) {
56796                 this._needsRender = true;
56797             }
56798         }
56799         _clearEdges() {
56800             this._stepEdges = [];
56801             this._turnEdges = [];
56802             this._sphericalEdges = [];
56803             this._sequenceEdgeKeys = [];
56804         }
56805         _setEdges(edgeStatus, sequence) {
56806             this._stepEdges = [];
56807             this._turnEdges = [];
56808             this._sphericalEdges = [];
56809             this._sequenceEdgeKeys = [];
56810             for (let edge of edgeStatus.edges) {
56811                 let direction = edge.data.direction;
56812                 if (this._stepDirections.indexOf(direction) > -1) {
56813                     this._stepEdges.push(edge);
56814                     continue;
56815                 }
56816                 if (this._turnDirections.indexOf(direction) > -1) {
56817                     this._turnEdges.push(edge);
56818                     continue;
56819                 }
56820                 if (edge.data.direction === exports.NavigationDirection.Spherical) {
56821                     this._sphericalEdges.push(edge);
56822                 }
56823             }
56824             if (this._distinguishSequence && sequence != null) {
56825                 let edges = this._sphericalEdges
56826                     .concat(this._stepEdges)
56827                     .concat(this._turnEdges);
56828                 for (let edge of edges) {
56829                     let edgeKey = edge.target;
56830                     for (let sequenceKey of sequence.imageIds) {
56831                         if (sequenceKey === edgeKey) {
56832                             this._sequenceEdgeKeys.push(edgeKey);
56833                             break;
56834                         }
56835                     }
56836                 }
56837             }
56838         }
56839         _createSphericalArrows(navigator, rotation) {
56840             let arrows = [];
56841             for (let sphericalEdge of this._sphericalEdges) {
56842                 arrows.push(this._createVNodeByKey(navigator, sphericalEdge.target, sphericalEdge.data.worldMotionAzimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-spherical"));
56843             }
56844             for (let stepEdge of this._stepEdges) {
56845                 arrows.push(this._createSphericalToPerspectiveArrow(navigator, stepEdge.target, stepEdge.data.worldMotionAzimuth, rotation, stepEdge.data.direction));
56846             }
56847             return arrows;
56848         }
56849         _createSphericalToPerspectiveArrow(navigator, key, azimuth, rotation, direction) {
56850             let threshold = Math.PI / 8;
56851             let relativePhi = rotation.phi;
56852             switch (direction) {
56853                 case exports.NavigationDirection.StepBackward:
56854                     relativePhi = rotation.phi - Math.PI;
56855                     break;
56856                 case exports.NavigationDirection.StepLeft:
56857                     relativePhi = rotation.phi + Math.PI / 2;
56858                     break;
56859                 case exports.NavigationDirection.StepRight:
56860                     relativePhi = rotation.phi - Math.PI / 2;
56861                     break;
56862             }
56863             if (Math.abs(this._spatial.wrapAngle(azimuth - relativePhi)) < threshold) {
56864                 return this._createVNodeByKey(navigator, key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-step");
56865             }
56866             return this._createVNodeInactive(key, azimuth, rotation);
56867         }
56868         _createPerspectiveToSphericalArrows(navigator, rotation) {
56869             let arrows = [];
56870             for (let sphericalEdge of this._sphericalEdges) {
56871                 arrows.push(this._createVNodeByKey(navigator, sphericalEdge.target, sphericalEdge.data.worldMotionAzimuth, rotation, this._calculator.innerRadius, "mapillary-direction-arrow-spherical", true));
56872             }
56873             return arrows;
56874         }
56875         _createStepArrows(navigator, rotation) {
56876             let arrows = [];
56877             for (let stepEdge of this._stepEdges) {
56878                 arrows.push(this._createVNodeByDirection(navigator, stepEdge.target, stepEdge.data.worldMotionAzimuth, rotation, stepEdge.data.direction));
56879             }
56880             return arrows;
56881         }
56882         _createTurnArrows(navigator) {
56883             let turns = [];
56884             for (let turnEdge of this._turnEdges) {
56885                 let direction = turnEdge.data.direction;
56886                 let name = this._turnNames[direction];
56887                 turns.push(this._createVNodeByTurn(navigator, turnEdge.target, name, direction));
56888             }
56889             return turns;
56890         }
56891         _createVNodeByKey(navigator, key, azimuth, rotation, offset, className, shiftVertically) {
56892             let onClick = (e) => {
56893                 navigator.moveTo$(key)
56894                     .subscribe(undefined, (error) => {
56895                     if (!(error instanceof CancelMapillaryError)) {
56896                         console.error(error);
56897                     }
56898                 });
56899             };
56900             return this._createVNode(key, azimuth, rotation, offset, className, "mapillary-direction-circle", onClick, shiftVertically);
56901         }
56902         _createVNodeByDirection(navigator, key, azimuth, rotation, direction) {
56903             let onClick = (e) => {
56904                 navigator.moveDir$(direction)
56905                     .subscribe(undefined, (error) => {
56906                     if (!(error instanceof CancelMapillaryError)) {
56907                         console.error(error);
56908                     }
56909                 });
56910             };
56911             return this._createVNode(key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-step", "mapillary-direction-circle", onClick);
56912         }
56913         _createVNodeByTurn(navigator, key, className, direction) {
56914             let onClick = (e) => {
56915                 navigator.moveDir$(direction)
56916                     .subscribe(undefined, (error) => {
56917                     if (!(error instanceof CancelMapillaryError)) {
56918                         console.error(error);
56919                     }
56920                 });
56921             };
56922             let style = {
56923                 height: this._calculator.turnCircleSizeCss,
56924                 transform: "rotate(0)",
56925                 width: this._calculator.turnCircleSizeCss,
56926             };
56927             switch (direction) {
56928                 case exports.NavigationDirection.TurnLeft:
56929                     style.left = "5px";
56930                     style.top = "5px";
56931                     break;
56932                 case exports.NavigationDirection.TurnRight:
56933                     style.right = "5px";
56934                     style.top = "5px";
56935                     break;
56936                 case exports.NavigationDirection.TurnU:
56937                     style.left = "5px";
56938                     style.bottom = "5px";
56939                     break;
56940             }
56941             let circleProperties = {
56942                 attributes: {
56943                     "data-id": key,
56944                 },
56945                 onclick: onClick,
56946                 style: style,
56947             };
56948             let circleClassName = "mapillary-direction-turn-circle";
56949             if (this._sequenceEdgeKeys.indexOf(key) > -1) {
56950                 circleClassName += "-sequence";
56951             }
56952             if (this._highlightKey === key) {
56953                 circleClassName += "-highlight";
56954             }
56955             let turn = virtualDom.h(`div.${className}`, {}, []);
56956             return virtualDom.h("div." + circleClassName, circleProperties, [turn]);
56957         }
56958         _createVNodeInactive(key, azimuth, rotation) {
56959             return this._createVNode(key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-inactive", "mapillary-direction-circle-inactive");
56960         }
56961         _createVNode(key, azimuth, rotation, radius, className, circleClassName, onClick, shiftVertically) {
56962             let translation = this._calculator.angleToCoordinates(azimuth - rotation.phi);
56963             // rotate 90 degrees clockwise and flip over X-axis
56964             let translationX = Math.round(-radius * translation[1] + 0.5 * this._calculator.containerWidth);
56965             let translationY = Math.round(-radius * translation[0] + 0.5 * this._calculator.containerHeight);
56966             let shadowTranslation = this._calculator.relativeAngleToCoordiantes(azimuth, rotation.phi);
56967             let shadowOffset = this._calculator.shadowOffset;
56968             let shadowTranslationX = -shadowOffset * shadowTranslation[1];
56969             let shadowTranslationY = shadowOffset * shadowTranslation[0];
56970             let filter = `drop-shadow(${shadowTranslationX}px ${shadowTranslationY}px 1px rgba(0,0,0,0.8))`;
56971             let properties = {
56972                 style: {
56973                     "-webkit-filter": filter,
56974                     filter: filter,
56975                 },
56976             };
56977             let chevron = virtualDom.h("div." + className, properties, []);
56978             let azimuthDeg = -this._spatial.radToDeg(azimuth - rotation.phi);
56979             let circleTransform = shiftVertically ?
56980                 `translate(${translationX}px, ${translationY}px) rotate(${azimuthDeg}deg) translateZ(-0.01px)` :
56981                 `translate(${translationX}px, ${translationY}px) rotate(${azimuthDeg}deg)`;
56982             let circleProperties = {
56983                 attributes: { "data-id": key },
56984                 onclick: onClick,
56985                 style: {
56986                     height: this._calculator.stepCircleSizeCss,
56987                     marginLeft: this._calculator.stepCircleMarginCss,
56988                     marginTop: this._calculator.stepCircleMarginCss,
56989                     transform: circleTransform,
56990                     width: this._calculator.stepCircleSizeCss,
56991                 },
56992             };
56993             if (this._sequenceEdgeKeys.indexOf(key) > -1) {
56994                 circleClassName += "-sequence";
56995             }
56996             if (this._highlightKey === key) {
56997                 circleClassName += "-highlight";
56998             }
56999             return virtualDom.h("div." + circleClassName, circleProperties, [chevron]);
57000         }
57001         _getContainer(steps, turns, rotation) {
57002             // edge does not handle hover on perspective transforms.
57003             let transform = this._isEdge ?
57004                 "rotateX(60deg)" :
57005                 `perspective(${this._calculator.containerWidthCss}) rotateX(60deg)`;
57006             let properties = {
57007                 oncontextmenu: (event) => { event.preventDefault(); },
57008                 style: {
57009                     bottom: this._calculator.containerBottomCss,
57010                     height: this._calculator.containerHeightCss,
57011                     left: this._calculator.containerLeftCss,
57012                     marginLeft: this._calculator.containerMarginCss,
57013                     transform: transform,
57014                     width: this._calculator.containerWidthCss,
57015                 },
57016             };
57017             return virtualDom.h("div.mapillary-direction-perspective", properties, turns.concat(steps));
57018         }
57019     }
57020
57021     /**
57022      * @class DirectionComponent
57023      * @classdesc Component showing navigation arrows for steps and turns.
57024      */
57025     class DirectionComponent extends Component {
57026         /** @ignore */
57027         constructor(name, container, navigator, directionDOMRenderer) {
57028             super(name, container, navigator);
57029             this._renderer = !!directionDOMRenderer ?
57030                 directionDOMRenderer :
57031                 new DirectionDOMRenderer(this.defaultConfiguration, { height: container.container.offsetHeight, width: container.container.offsetWidth });
57032             this._hoveredIdSubject$ = new Subject();
57033             this._hoveredId$ = this._hoveredIdSubject$.pipe(share());
57034         }
57035         fire(type, event) {
57036             super.fire(type, event);
57037         }
57038         off(type, handler) {
57039             super.off(type, handler);
57040         }
57041         on(type, handler) {
57042             super.on(type, handler);
57043         }
57044         _activate() {
57045             const subs = this._subscriptions;
57046             subs.push(this._configuration$
57047                 .subscribe((configuration) => {
57048                 this._renderer.setConfiguration(configuration);
57049             }));
57050             subs.push(this._container.renderService.size$
57051                 .subscribe((size) => {
57052                 this._renderer.resize(size);
57053             }));
57054             subs.push(this._navigator.stateService.currentImage$.pipe(tap((image) => {
57055                 this._container.domRenderer.render$.next({ name: this._name, vNode: virtualDom.h("div", {}, []) });
57056                 this._renderer.setImage(image);
57057             }), withLatestFrom(this._configuration$), switchMap(([image, configuration]) => {
57058                 return combineLatest(image.spatialEdges$, configuration.distinguishSequence ?
57059                     this._navigator.graphService
57060                         .cacheSequence$(image.sequenceId).pipe(catchError((error) => {
57061                         console.error(`Failed to cache sequence (${image.sequenceId})`, error);
57062                         return of(null);
57063                     })) :
57064                     of(null));
57065             }))
57066                 .subscribe(([edgeStatus, sequence]) => {
57067                 this._renderer.setEdges(edgeStatus, sequence);
57068             }));
57069             subs.push(this._container.renderService.renderCameraFrame$.pipe(tap((renderCamera) => {
57070                 this._renderer.setRenderCamera(renderCamera);
57071             }), map(() => {
57072                 return this._renderer;
57073             }), filter((renderer) => {
57074                 return renderer.needsRender;
57075             }), map((renderer) => {
57076                 return { name: this._name, vNode: renderer.render(this._navigator) };
57077             }))
57078                 .subscribe(this._container.domRenderer.render$));
57079             subs.push(combineLatest(this._container.domRenderer.element$, this._container.renderService.renderCamera$, this._container.mouseService.mouseMove$.pipe(startWith(null)), this._container.mouseService.mouseUp$.pipe(startWith(null))).pipe(map(([element]) => {
57080                 let elements = element.getElementsByClassName("mapillary-direction-perspective");
57081                 for (let i = 0; i < elements.length; i++) {
57082                     let hovered = elements.item(i).querySelector(":hover");
57083                     if (hovered != null && hovered.hasAttribute("data-id")) {
57084                         return hovered.getAttribute("data-id");
57085                     }
57086                 }
57087                 return null;
57088             }), distinctUntilChanged())
57089                 .subscribe(this._hoveredIdSubject$));
57090             subs.push(this._hoveredId$
57091                 .subscribe((id) => {
57092                 const type = "hover";
57093                 const event = {
57094                     id,
57095                     target: this,
57096                     type,
57097                 };
57098                 this.fire(type, event);
57099             }));
57100         }
57101         _deactivate() {
57102             this._subscriptions.unsubscribe();
57103         }
57104         _getDefaultConfiguration() {
57105             return {
57106                 distinguishSequence: false,
57107                 maxWidth: 460,
57108                 minWidth: 260,
57109             };
57110         }
57111     }
57112     /** @inheritdoc */
57113     DirectionComponent.componentName = "direction";
57114
57115     const sphericalFrag = `
57116 #ifdef GL_FRAGMENT_PRECISION_HIGH
57117 precision highp float;
57118 #else
57119 precision mediump float;
57120 #endif
57121
57122 #define tau 6.28318530718
57123
57124 uniform sampler2D projectorTex;
57125 uniform float opacity;
57126
57127 varying vec4 vRstq;
57128
57129 void main()
57130 {
57131     vec3 b = normalize(vRstq.xyz);
57132     float lat = -asin(b.y);
57133     float lng = atan(b.x, b.z);
57134     float x = lng / tau + 0.5;
57135     float y = lat / tau * 2.0 + 0.5;
57136     vec4 baseColor = texture2D(projectorTex, vec2(x, y));
57137     baseColor.a = opacity;
57138     gl_FragColor = baseColor;
57139 }
57140 `;
57141
57142     const sphericalVert = `
57143 #ifdef GL_ES
57144 precision highp float;
57145 #endif
57146
57147 uniform mat4 projectorMat;
57148
57149 varying vec4 vRstq;
57150
57151 void main()
57152 {
57153     vRstq = projectorMat * vec4(position, 1.0);
57154     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57155 }
57156 `;
57157
57158     const sphericalCurtainFrag = `
57159 #ifdef GL_FRAGMENT_PRECISION_HIGH
57160 precision highp float;
57161 #else
57162 precision mediump float;
57163 #endif
57164
57165 #define tau 6.28318530718
57166
57167 uniform sampler2D projectorTex;
57168 uniform float curtain;
57169 uniform float opacity;
57170
57171 varying vec4 vRstq;
57172
57173 void main()
57174 {
57175     vec3 b = normalize(vRstq.xyz);
57176     float lat = -asin(b.y);
57177     float lng = atan(b.x, b.z);
57178     float x = lng / tau + 0.5;
57179     float y = lat / tau * 2.0 + 0.5;
57180
57181     bool inverted = curtain < 0.5;
57182
57183     float curtainMin = inverted ? curtain + 0.5 : curtain - 0.5;
57184     float curtainMax = curtain;
57185
57186     bool insideCurtain = inverted ?
57187         x > curtainMin || x < curtainMax :
57188         x > curtainMin && x < curtainMax;
57189
57190     vec4 baseColor;
57191     if (insideCurtain) {
57192         baseColor = texture2D(projectorTex, vec2(x, y));
57193         baseColor.a = opacity;
57194     } else {
57195         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57196     }
57197
57198     gl_FragColor = baseColor;
57199 }
57200 `;
57201
57202     const sphericalCurtainVert = `
57203 #ifdef GL_ES
57204 precision highp float;
57205 #endif
57206
57207 uniform mat4 projectorMat;
57208
57209 varying vec4 vRstq;
57210
57211 void main()
57212 {
57213     vRstq = projectorMat * vec4(position, 1.0);
57214     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57215 }
57216 `;
57217
57218     const fisheyeFrag = `
57219 #ifdef GL_FRAGMENT_PRECISION_HIGH
57220 precision highp float;
57221 #else
57222 precision mediump float;
57223 #endif
57224
57225 uniform sampler2D projectorTex;
57226 uniform float opacity;
57227 uniform float focal;
57228 uniform float k1;
57229 uniform float k2;
57230 uniform float scale_x;
57231 uniform float scale_y;
57232 uniform float radial_peak;
57233
57234 varying vec4 vRstq;
57235
57236 void main()
57237 {
57238     float x = vRstq.x;
57239     float y = vRstq.y;
57240     float z = vRstq.z;
57241
57242     float r = sqrt(x * x + y * y);
57243     float theta = atan(r, z);
57244
57245     if (radial_peak > 0. && theta > radial_peak) {
57246         theta = radial_peak;
57247     }
57248
57249     float theta2 = theta * theta;
57250     float theta_d = theta * (1.0 + theta2 * (k1 + theta2 * k2));
57251     float s = focal * theta_d / r;
57252
57253     float u = scale_x * s * x + 0.5;
57254     float v = -scale_y * s * y + 0.5;
57255
57256     vec4 baseColor;
57257     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57258         baseColor = texture2D(projectorTex, vec2(u, v));
57259         baseColor.a = opacity;
57260     } else {
57261         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57262     }
57263
57264     gl_FragColor = baseColor;
57265 }
57266 `;
57267
57268     const fisheyeVert = `
57269 #ifdef GL_ES
57270 precision highp float;
57271 #endif
57272
57273 uniform mat4 projectorMat;
57274
57275 varying vec4 vRstq;
57276
57277 void main()
57278 {
57279     vRstq = projectorMat * vec4(position, 1.0);
57280     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57281 }
57282 `;
57283
57284     const fisheyeCurtainFrag = `
57285 #ifdef GL_FRAGMENT_PRECISION_HIGH
57286 precision highp float;
57287 #else
57288 precision mediump float;
57289 #endif
57290
57291 uniform sampler2D projectorTex;
57292 uniform float opacity;
57293 uniform float focal;
57294 uniform float k1;
57295 uniform float k2;
57296 uniform float scale_x;
57297 uniform float scale_y;
57298 uniform float radial_peak;
57299 uniform float curtain;
57300
57301 varying vec4 vRstq;
57302
57303 void main()
57304 {
57305     float x = vRstq.x;
57306     float y = vRstq.y;
57307     float z = vRstq.z;
57308
57309     float r2 = sqrt(x * x + y * y);
57310     float theta = atan(r2, z);
57311
57312     if (radial_peak > 0. && theta > radial_peak) {
57313         theta = radial_peak;
57314     }
57315
57316     float theta2 = theta * theta;
57317     float theta_d = theta * (1.0 + theta2 * (k1 + theta2 * k2));
57318     float s = focal * theta_d / r2;
57319
57320     float u = scale_x * s * x + 0.5;
57321     float v = -scale_y * s * y + 0.5;
57322
57323     vec4 baseColor;
57324     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57325         baseColor = texture2D(projectorTex, vec2(u, v));
57326         baseColor.a = opacity;
57327     } else {
57328         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57329     }
57330
57331     gl_FragColor = baseColor;
57332 }
57333 `;
57334
57335     const fisheyeCurtainVert = `
57336 #ifdef GL_ES
57337 precision highp float;
57338 #endif
57339
57340 uniform mat4 projectorMat;
57341
57342 varying vec4 vRstq;
57343
57344 void main()
57345 {
57346     vRstq = projectorMat * vec4(position, 1.0);
57347     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57348 }
57349 `;
57350
57351     const perspectiveFrag = `
57352 #ifdef GL_FRAGMENT_PRECISION_HIGH
57353 precision highp float;
57354 #else
57355 precision mediump float;
57356 #endif
57357
57358 uniform sampler2D projectorTex;
57359 uniform float opacity;
57360 uniform float focal;
57361 uniform float k1;
57362 uniform float k2;
57363 uniform float scale_x;
57364 uniform float scale_y;
57365 uniform float radial_peak;
57366
57367 varying vec4 vRstq;
57368
57369 void main()
57370 {
57371     float x = vRstq.x / vRstq.z;
57372     float y = vRstq.y / vRstq.z;
57373     float r2 = x * x + y * y;
57374
57375     if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) {
57376         r2 = radial_peak * radial_peak;
57377     }
57378
57379     float d = 1.0 + k1 * r2 + k2 * r2 * r2;
57380     float u = scale_x * focal * d * x + 0.5;
57381     float v = - scale_y * focal * d * y + 0.5;
57382
57383     vec4 baseColor;
57384     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57385         baseColor = texture2D(projectorTex, vec2(u, v));
57386         baseColor.a = opacity;
57387     } else {
57388         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57389     }
57390
57391     gl_FragColor = baseColor;
57392 }
57393 `;
57394
57395     const perspectiveVert = `
57396 #ifdef GL_ES
57397 precision highp float;
57398 #endif
57399
57400 uniform mat4 projectorMat;
57401
57402 varying vec4 vRstq;
57403
57404 void main()
57405 {
57406     vRstq = projectorMat * vec4(position, 1.0);
57407     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57408 }
57409 `;
57410
57411     const perspectiveCurtainFrag = `
57412 #ifdef GL_FRAGMENT_PRECISION_HIGH
57413 precision highp float;
57414 #else
57415 precision mediump float;
57416 #endif
57417
57418 uniform sampler2D projectorTex;
57419 uniform float opacity;
57420 uniform float focal;
57421 uniform float k1;
57422 uniform float k2;
57423 uniform float scale_x;
57424 uniform float scale_y;
57425 uniform float radial_peak;
57426 uniform float curtain;
57427
57428 varying vec4 vRstq;
57429
57430 void main()
57431 {
57432     float x = vRstq.x / vRstq.z;
57433     float y = vRstq.y / vRstq.z;
57434     float r2 = x * x + y * y;
57435
57436     if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) {
57437         r2 = radial_peak * radial_peak;
57438     }
57439
57440     float d = 1.0 + k1 * r2 + k2 * r2 * r2;
57441     float u = scale_x * focal * d * x + 0.5;
57442     float v = - scale_y * focal * d * y + 0.5;
57443
57444     vec4 baseColor;
57445     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57446         baseColor = texture2D(projectorTex, vec2(u, v));
57447         baseColor.a = opacity;
57448     } else {
57449         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57450     }
57451
57452     gl_FragColor = baseColor;
57453 }
57454 `;
57455
57456     const perspectiveCurtainVert = `
57457 #ifdef GL_ES
57458 precision highp float;
57459 #endif
57460
57461 uniform mat4 projectorMat;
57462
57463 varying vec4 vRstq;
57464
57465 void main()
57466 {
57467     vRstq = projectorMat * vec4(position, 1.0);
57468     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57469 }
57470 `;
57471
57472     const perspectiveDistortedFrag = `
57473 #ifdef GL_FRAGMENT_PRECISION_HIGH
57474 precision highp float;
57475 #else
57476 precision mediump float;
57477 #endif
57478
57479 uniform sampler2D projectorTex;
57480 uniform float opacity;
57481
57482 varying vec4 vRstq;
57483
57484 void main()
57485 {
57486     float u = vRstq.x / vRstq.w;
57487     float v = vRstq.y / vRstq.w;
57488
57489     vec4 baseColor;
57490     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57491         baseColor = texture2D(projectorTex, vec2(u, v));
57492         baseColor.a = opacity;
57493     } else {
57494         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57495     }
57496
57497     gl_FragColor = baseColor;
57498 }
57499 `;
57500
57501     const perspectiveDistortedVert = `
57502 #ifdef GL_ES
57503 precision highp float;
57504 #endif
57505
57506 uniform mat4 projectorMat;
57507
57508 varying vec4 vRstq;
57509
57510 void main()
57511 {
57512     vRstq = projectorMat * vec4(position, 1.0);
57513     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57514 }
57515 `;
57516
57517     const perspectiveDistortedCurtainFrag = `
57518 #ifdef GL_FRAGMENT_PRECISION_HIGH
57519 precision highp float;
57520 #else
57521 precision mediump float;
57522 #endif
57523
57524 uniform sampler2D projectorTex;
57525 uniform float opacity;
57526 uniform float curtain;
57527
57528 varying vec4 vRstq;
57529
57530 void main()
57531 {
57532     float u = vRstq.x / vRstq.w;
57533     float v = vRstq.y / vRstq.w;
57534
57535     vec4 baseColor;
57536     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
57537         baseColor = texture2D(projectorTex, vec2(u, v));
57538         baseColor.a = opacity;
57539     } else {
57540         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
57541     }
57542
57543     gl_FragColor = baseColor;
57544 }
57545 `;
57546
57547     const perspectiveDistortedCurtainVert = `
57548 #ifdef GL_ES
57549 precision highp float;
57550 #endif
57551
57552 uniform mat4 projectorMat;
57553
57554 varying vec4 vRstq;
57555
57556 void main()
57557 {
57558     vRstq = projectorMat * vec4(position, 1.0);
57559     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57560 }
57561 `;
57562
57563     class Shaders {
57564     }
57565     Shaders.fisheye = {
57566         fragment: fisheyeFrag,
57567         vertex: fisheyeVert,
57568     };
57569     Shaders.fisheyeCurtain = {
57570         fragment: fisheyeCurtainFrag,
57571         vertex: fisheyeCurtainVert,
57572     };
57573     Shaders.perspective = {
57574         fragment: perspectiveFrag,
57575         vertex: perspectiveVert,
57576     };
57577     Shaders.perspectiveCurtain = {
57578         fragment: perspectiveCurtainFrag,
57579         vertex: perspectiveCurtainVert,
57580     };
57581     Shaders.perspectiveDistorted = {
57582         fragment: perspectiveDistortedFrag,
57583         vertex: perspectiveDistortedVert,
57584     };
57585     Shaders.perspectiveDistortedCurtain = {
57586         fragment: perspectiveDistortedCurtainFrag,
57587         vertex: perspectiveDistortedCurtainVert,
57588     };
57589     Shaders.spherical = {
57590         fragment: sphericalFrag,
57591         vertex: sphericalVert,
57592     };
57593     Shaders.sphericalCurtain = {
57594         fragment: sphericalCurtainFrag,
57595         vertex: sphericalCurtainVert,
57596     };
57597
57598     class MeshFactory {
57599         constructor(imagePlaneDepth, imageSphereRadius) {
57600             this._imagePlaneDepth = imagePlaneDepth != null ? imagePlaneDepth : 200;
57601             this._imageSphereRadius = imageSphereRadius != null ? imageSphereRadius : 200;
57602         }
57603         createMesh(image, transform) {
57604             if (isSpherical(transform.cameraType)) {
57605                 return this._createImageSphere(image, transform);
57606             }
57607             else if (isFisheye(transform.cameraType)) {
57608                 return this._createImagePlaneFisheye(image, transform);
57609             }
57610             else {
57611                 return this._createImagePlane(image, transform);
57612             }
57613         }
57614         createFlatMesh(image, transform, basicX0, basicX1, basicY0, basicY1) {
57615             let texture = this._createTexture(image.image);
57616             let materialParameters = this._createDistortedPlaneMaterialParameters(transform, texture);
57617             let material = new ShaderMaterial(materialParameters);
57618             let geometry = this._getFlatImagePlaneGeoFromBasic(transform, basicX0, basicX1, basicY0, basicY1);
57619             return new Mesh(geometry, material);
57620         }
57621         createCurtainMesh(image, transform) {
57622             if (isSpherical(transform.cameraType)) {
57623                 return this._createSphereCurtainMesh(image, transform);
57624             }
57625             else if (isFisheye(transform.cameraType)) {
57626                 return this._createCurtainMeshFisheye(image, transform);
57627             }
57628             else {
57629                 return this._createCurtainMesh(image, transform);
57630             }
57631         }
57632         createDistortedCurtainMesh(image, transform) {
57633             return this._createDistortedCurtainMesh(image, transform);
57634         }
57635         _createCurtainMesh(image, transform) {
57636             let texture = this._createTexture(image.image);
57637             let materialParameters = this._createCurtainPlaneMaterialParameters(transform, texture);
57638             let material = new ShaderMaterial(materialParameters);
57639             let geometry = this._useMesh(transform, image) ?
57640                 this._getImagePlaneGeo(transform, image) :
57641                 this._getRegularFlatImagePlaneGeo(transform);
57642             return new Mesh(geometry, material);
57643         }
57644         _createCurtainMeshFisheye(image, transform) {
57645             let texture = this._createTexture(image.image);
57646             let materialParameters = this._createCurtainPlaneMaterialParametersFisheye(transform, texture);
57647             let material = new ShaderMaterial(materialParameters);
57648             let geometry = this._useMesh(transform, image) ?
57649                 this._getImagePlaneGeoFisheye(transform, image) :
57650                 this._getRegularFlatImagePlaneGeo(transform);
57651             return new Mesh(geometry, material);
57652         }
57653         _createDistortedCurtainMesh(image, transform) {
57654             let texture = this._createTexture(image.image);
57655             let materialParameters = this._createDistortedCurtainPlaneMaterialParameters(transform, texture);
57656             let material = new ShaderMaterial(materialParameters);
57657             let geometry = this._getRegularFlatImagePlaneGeo(transform);
57658             return new Mesh(geometry, material);
57659         }
57660         _createSphereCurtainMesh(image, transform) {
57661             let texture = this._createTexture(image.image);
57662             let materialParameters = this._createCurtainSphereMaterialParameters(transform, texture);
57663             let material = new ShaderMaterial(materialParameters);
57664             return this._useMesh(transform, image) ?
57665                 new Mesh(this._getImageSphereGeo(transform, image), material) :
57666                 new Mesh(this._getFlatImageSphereGeo(transform), material);
57667         }
57668         _createImageSphere(image, transform) {
57669             let texture = this._createTexture(image.image);
57670             let materialParameters = this._createSphereMaterialParameters(transform, texture);
57671             let material = new ShaderMaterial(materialParameters);
57672             let mesh = this._useMesh(transform, image) ?
57673                 new Mesh(this._getImageSphereGeo(transform, image), material) :
57674                 new Mesh(this._getFlatImageSphereGeo(transform), material);
57675             return mesh;
57676         }
57677         _createImagePlane(image, transform) {
57678             let texture = this._createTexture(image.image);
57679             let materialParameters = this._createPlaneMaterialParameters(transform, texture);
57680             let material = new ShaderMaterial(materialParameters);
57681             let geometry = this._useMesh(transform, image) ?
57682                 this._getImagePlaneGeo(transform, image) :
57683                 this._getRegularFlatImagePlaneGeo(transform);
57684             return new Mesh(geometry, material);
57685         }
57686         _createImagePlaneFisheye(image, transform) {
57687             let texture = this._createTexture(image.image);
57688             let materialParameters = this._createPlaneMaterialParametersFisheye(transform, texture);
57689             let material = new ShaderMaterial(materialParameters);
57690             let geometry = this._useMesh(transform, image) ?
57691                 this._getImagePlaneGeoFisheye(transform, image) :
57692                 this._getRegularFlatImagePlaneGeoFisheye(transform);
57693             return new Mesh(geometry, material);
57694         }
57695         _createSphereMaterialParameters(transform, texture) {
57696             let materialParameters = {
57697                 depthWrite: false,
57698                 fragmentShader: Shaders.spherical.fragment,
57699                 side: DoubleSide,
57700                 transparent: true,
57701                 uniforms: {
57702                     opacity: { value: 1.0 },
57703                     projectorMat: { value: transform.rt },
57704                     projectorTex: { value: texture },
57705                 },
57706                 vertexShader: Shaders.spherical.vertex,
57707             };
57708             return materialParameters;
57709         }
57710         _createCurtainSphereMaterialParameters(transform, texture) {
57711             let materialParameters = {
57712                 depthWrite: false,
57713                 fragmentShader: Shaders.sphericalCurtain.fragment,
57714                 side: DoubleSide,
57715                 transparent: true,
57716                 uniforms: {
57717                     curtain: { value: 1.0 },
57718                     opacity: { value: 1.0 },
57719                     projectorMat: { value: transform.rt },
57720                     projectorTex: { value: texture },
57721                 },
57722                 vertexShader: Shaders.sphericalCurtain.vertex,
57723             };
57724             return materialParameters;
57725         }
57726         _createPlaneMaterialParameters(transform, texture) {
57727             let materialParameters = {
57728                 depthWrite: false,
57729                 fragmentShader: Shaders.perspective.fragment,
57730                 side: DoubleSide,
57731                 transparent: true,
57732                 uniforms: {
57733                     focal: { value: transform.focal },
57734                     k1: { value: transform.ck1 },
57735                     k2: { value: transform.ck2 },
57736                     opacity: { value: 1.0 },
57737                     projectorMat: { value: transform.basicRt },
57738                     projectorTex: { value: texture },
57739                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
57740                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
57741                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
57742                 },
57743                 vertexShader: Shaders.perspective.vertex,
57744             };
57745             return materialParameters;
57746         }
57747         _createPlaneMaterialParametersFisheye(transform, texture) {
57748             let materialParameters = {
57749                 depthWrite: false,
57750                 fragmentShader: Shaders.fisheye.fragment,
57751                 side: DoubleSide,
57752                 transparent: true,
57753                 uniforms: {
57754                     focal: { value: transform.focal },
57755                     k1: { value: transform.ck1 },
57756                     k2: { value: transform.ck2 },
57757                     opacity: { value: 1.0 },
57758                     projectorMat: { value: transform.basicRt },
57759                     projectorTex: { value: texture },
57760                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
57761                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
57762                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
57763                 },
57764                 vertexShader: Shaders.fisheye.vertex,
57765             };
57766             return materialParameters;
57767         }
57768         _createCurtainPlaneMaterialParametersFisheye(transform, texture) {
57769             let materialParameters = {
57770                 depthWrite: false,
57771                 fragmentShader: Shaders.fisheyeCurtain.fragment,
57772                 side: DoubleSide,
57773                 transparent: true,
57774                 uniforms: {
57775                     curtain: { value: 1.0 },
57776                     focal: { value: transform.focal },
57777                     k1: { value: transform.ck1 },
57778                     k2: { value: transform.ck2 },
57779                     opacity: { value: 1.0 },
57780                     projectorMat: { value: transform.basicRt },
57781                     projectorTex: { value: texture },
57782                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
57783                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
57784                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
57785                 },
57786                 vertexShader: Shaders.fisheyeCurtain.vertex,
57787             };
57788             return materialParameters;
57789         }
57790         _createCurtainPlaneMaterialParameters(transform, texture) {
57791             let materialParameters = {
57792                 depthWrite: false,
57793                 fragmentShader: Shaders.perspectiveCurtain.fragment,
57794                 side: DoubleSide,
57795                 transparent: true,
57796                 uniforms: {
57797                     curtain: { value: 1.0 },
57798                     focal: { value: transform.focal },
57799                     k1: { value: transform.ck1 },
57800                     k2: { value: transform.ck2 },
57801                     opacity: { value: 1.0 },
57802                     projectorMat: { value: transform.basicRt },
57803                     projectorTex: { value: texture },
57804                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
57805                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
57806                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
57807                 },
57808                 vertexShader: Shaders.perspectiveCurtain.vertex,
57809             };
57810             return materialParameters;
57811         }
57812         _createDistortedCurtainPlaneMaterialParameters(transform, texture) {
57813             let materialParameters = {
57814                 depthWrite: false,
57815                 fragmentShader: Shaders.perspectiveDistortedCurtain.fragment,
57816                 side: DoubleSide,
57817                 transparent: true,
57818                 uniforms: {
57819                     curtain: { value: 1.0 },
57820                     opacity: { value: 1.0 },
57821                     projectorMat: { value: transform.projectorMatrix() },
57822                     projectorTex: { value: texture },
57823                 },
57824                 vertexShader: Shaders.perspectiveDistortedCurtain.vertex,
57825             };
57826             return materialParameters;
57827         }
57828         _createDistortedPlaneMaterialParameters(transform, texture) {
57829             let materialParameters = {
57830                 depthWrite: false,
57831                 fragmentShader: Shaders.perspectiveDistorted.fragment,
57832                 side: DoubleSide,
57833                 transparent: true,
57834                 uniforms: {
57835                     opacity: { value: 1.0 },
57836                     projectorMat: { value: transform.projectorMatrix() },
57837                     projectorTex: { value: texture },
57838                 },
57839                 vertexShader: Shaders.perspectiveDistorted.vertex,
57840             };
57841             return materialParameters;
57842         }
57843         _createTexture(image) {
57844             let texture = new Texture(image);
57845             texture.minFilter = LinearFilter;
57846             texture.needsUpdate = true;
57847             return texture;
57848         }
57849         _useMesh(transform, image) {
57850             return image.mesh.vertices.length && transform.hasValidScale;
57851         }
57852         _getImageSphereGeo(transform, image) {
57853             const t = transform.srtInverse;
57854             // push everything at least 5 meters in front of the camera
57855             let minZ = 5.0 * transform.scale;
57856             let maxZ = this._imageSphereRadius * transform.scale;
57857             let vertices = image.mesh.vertices;
57858             let numVertices = vertices.length / 3;
57859             let positions = new Float32Array(vertices.length);
57860             for (let i = 0; i < numVertices; ++i) {
57861                 let index = 3 * i;
57862                 let x = vertices[index + 0];
57863                 let y = vertices[index + 1];
57864                 let z = vertices[index + 2];
57865                 let l = Math.sqrt(x * x + y * y + z * z);
57866                 let boundedL = Math.max(minZ, Math.min(l, maxZ));
57867                 let factor = boundedL / l;
57868                 let p = new Vector3(x * factor, y * factor, z * factor);
57869                 p.applyMatrix4(t);
57870                 positions[index + 0] = p.x;
57871                 positions[index + 1] = p.y;
57872                 positions[index + 2] = p.z;
57873             }
57874             let faces = image.mesh.faces;
57875             let indices = new Uint16Array(faces.length);
57876             for (let i = 0; i < faces.length; ++i) {
57877                 indices[i] = faces[i];
57878             }
57879             let geometry = new BufferGeometry();
57880             geometry.setAttribute("position", new BufferAttribute(positions, 3));
57881             geometry.setIndex(new BufferAttribute(indices, 1));
57882             return geometry;
57883         }
57884         _getImagePlaneGeo(transform, image) {
57885             const undistortionMarginFactor = 3;
57886             const t = transform.srtInverse;
57887             // push everything at least 5 meters in front of the camera
57888             let minZ = 5.0 * transform.scale;
57889             let maxZ = this._imagePlaneDepth * transform.scale;
57890             let vertices = image.mesh.vertices;
57891             let numVertices = vertices.length / 3;
57892             let positions = new Float32Array(vertices.length);
57893             for (let i = 0; i < numVertices; ++i) {
57894                 let index = 3 * i;
57895                 let x = vertices[index + 0];
57896                 let y = vertices[index + 1];
57897                 let z = vertices[index + 2];
57898                 if (i < 4) {
57899                     x *= undistortionMarginFactor;
57900                     y *= undistortionMarginFactor;
57901                 }
57902                 let boundedZ = Math.max(minZ, Math.min(z, maxZ));
57903                 let factor = boundedZ / z;
57904                 let p = new Vector3(x * factor, y * factor, boundedZ);
57905                 p.applyMatrix4(t);
57906                 positions[index + 0] = p.x;
57907                 positions[index + 1] = p.y;
57908                 positions[index + 2] = p.z;
57909             }
57910             let faces = image.mesh.faces;
57911             let indices = new Uint16Array(faces.length);
57912             for (let i = 0; i < faces.length; ++i) {
57913                 indices[i] = faces[i];
57914             }
57915             let geometry = new BufferGeometry();
57916             geometry.setAttribute("position", new BufferAttribute(positions, 3));
57917             geometry.setIndex(new BufferAttribute(indices, 1));
57918             return geometry;
57919         }
57920         _getImagePlaneGeoFisheye(transform, image) {
57921             const t = transform.srtInverse;
57922             // push everything at least 5 meters in front of the camera
57923             let minZ = 5.0 * transform.scale;
57924             let maxZ = this._imagePlaneDepth * transform.scale;
57925             let vertices = image.mesh.vertices;
57926             let numVertices = vertices.length / 3;
57927             let positions = new Float32Array(vertices.length);
57928             for (let i = 0; i < numVertices; ++i) {
57929                 let index = 3 * i;
57930                 let x = vertices[index + 0];
57931                 let y = vertices[index + 1];
57932                 let z = vertices[index + 2];
57933                 let l = Math.sqrt(x * x + y * y + z * z);
57934                 let boundedL = Math.max(minZ, Math.min(l, maxZ));
57935                 let factor = boundedL / l;
57936                 let p = new Vector3(x * factor, y * factor, z * factor);
57937                 p.applyMatrix4(t);
57938                 positions[index + 0] = p.x;
57939                 positions[index + 1] = p.y;
57940                 positions[index + 2] = p.z;
57941             }
57942             let faces = image.mesh.faces;
57943             let indices = new Uint16Array(faces.length);
57944             for (let i = 0; i < faces.length; ++i) {
57945                 indices[i] = faces[i];
57946             }
57947             let geometry = new BufferGeometry();
57948             geometry.setAttribute("position", new BufferAttribute(positions, 3));
57949             geometry.setIndex(new BufferAttribute(indices, 1));
57950             return geometry;
57951         }
57952         _getFlatImageSphereGeo(transform) {
57953             const geometry = new SphereGeometry(this._imageSphereRadius, 20, 40);
57954             const t = transform.rt
57955                 .clone()
57956                 .invert();
57957             geometry.applyMatrix4(t);
57958             return geometry;
57959         }
57960         _getRegularFlatImagePlaneGeo(transform) {
57961             let width = transform.width;
57962             let height = transform.height;
57963             let size = Math.max(width, height);
57964             let dx = width / 2.0 / size;
57965             let dy = height / 2.0 / size;
57966             return this._getFlatImagePlaneGeo(transform, dx, dy);
57967         }
57968         _getFlatImagePlaneGeo(transform, dx, dy) {
57969             let vertices = [];
57970             vertices.push(transform.unprojectSfM([-dx, -dy], this._imagePlaneDepth));
57971             vertices.push(transform.unprojectSfM([dx, -dy], this._imagePlaneDepth));
57972             vertices.push(transform.unprojectSfM([dx, dy], this._imagePlaneDepth));
57973             vertices.push(transform.unprojectSfM([-dx, dy], this._imagePlaneDepth));
57974             return this._createFlatGeometry(vertices);
57975         }
57976         _getRegularFlatImagePlaneGeoFisheye(transform) {
57977             let width = transform.width;
57978             let height = transform.height;
57979             let size = Math.max(width, height);
57980             let dx = width / 2.0 / size;
57981             let dy = height / 2.0 / size;
57982             return this._getFlatImagePlaneGeoFisheye(transform, dx, dy);
57983         }
57984         _getFlatImagePlaneGeoFisheye(transform, dx, dy) {
57985             let vertices = [];
57986             vertices.push(transform.unprojectSfM([-dx, -dy], this._imagePlaneDepth));
57987             vertices.push(transform.unprojectSfM([dx, -dy], this._imagePlaneDepth));
57988             vertices.push(transform.unprojectSfM([dx, dy], this._imagePlaneDepth));
57989             vertices.push(transform.unprojectSfM([-dx, dy], this._imagePlaneDepth));
57990             return this._createFlatGeometry(vertices);
57991         }
57992         _getFlatImagePlaneGeoFromBasic(transform, basicX0, basicX1, basicY0, basicY1) {
57993             let vertices = [];
57994             vertices.push(transform.unprojectBasic([basicX0, basicY0], this._imagePlaneDepth));
57995             vertices.push(transform.unprojectBasic([basicX1, basicY0], this._imagePlaneDepth));
57996             vertices.push(transform.unprojectBasic([basicX1, basicY1], this._imagePlaneDepth));
57997             vertices.push(transform.unprojectBasic([basicX0, basicY1], this._imagePlaneDepth));
57998             return this._createFlatGeometry(vertices);
57999         }
58000         _createFlatGeometry(vertices) {
58001             let positions = new Float32Array(12);
58002             for (let i = 0; i < vertices.length; i++) {
58003                 let index = 3 * i;
58004                 positions[index + 0] = vertices[i][0];
58005                 positions[index + 1] = vertices[i][1];
58006                 positions[index + 2] = vertices[i][2];
58007             }
58008             let indices = new Uint16Array(6);
58009             indices[0] = 0;
58010             indices[1] = 1;
58011             indices[2] = 3;
58012             indices[3] = 1;
58013             indices[4] = 2;
58014             indices[5] = 3;
58015             let geometry = new BufferGeometry();
58016             geometry.setAttribute("position", new BufferAttribute(positions, 3));
58017             geometry.setIndex(new BufferAttribute(indices, 1));
58018             return geometry;
58019         }
58020     }
58021
58022     class MeshScene {
58023         constructor() {
58024             this._planes = {};
58025             this._planesOld = {};
58026             this._planesPeriphery = {};
58027             this._scene = new Scene();
58028             this._sceneOld = new Scene();
58029             this._scenePeriphery = new Scene();
58030         }
58031         get planes() {
58032             return this._planes;
58033         }
58034         get planesOld() {
58035             return this._planesOld;
58036         }
58037         get planesPeriphery() {
58038             return this._planesPeriphery;
58039         }
58040         get scene() {
58041             return this._scene;
58042         }
58043         get sceneOld() {
58044             return this._sceneOld;
58045         }
58046         get scenePeriphery() {
58047             return this._scenePeriphery;
58048         }
58049         updateImagePlanes(planes) {
58050             this._dispose(this._planesOld, this.sceneOld);
58051             for (const key in this._planes) {
58052                 if (!this._planes.hasOwnProperty(key)) {
58053                     continue;
58054                 }
58055                 const plane = this._planes[key];
58056                 this._scene.remove(plane);
58057                 this._sceneOld.add(plane);
58058             }
58059             for (const key in planes) {
58060                 if (!planes.hasOwnProperty(key)) {
58061                     continue;
58062                 }
58063                 this._scene.add(planes[key]);
58064             }
58065             this._planesOld = this._planes;
58066             this._planes = planes;
58067         }
58068         addImagePlanes(planes) {
58069             for (const key in planes) {
58070                 if (!planes.hasOwnProperty(key)) {
58071                     continue;
58072                 }
58073                 const plane = planes[key];
58074                 this._scene.add(plane);
58075                 this._planes[key] = plane;
58076             }
58077         }
58078         addImagePlanesOld(planes) {
58079             for (const key in planes) {
58080                 if (!planes.hasOwnProperty(key)) {
58081                     continue;
58082                 }
58083                 const plane = planes[key];
58084                 this._sceneOld.add(plane);
58085                 this._planesOld[key] = plane;
58086             }
58087         }
58088         setImagePlanes(planes) {
58089             this._clear();
58090             this.addImagePlanes(planes);
58091         }
58092         addPeripheryPlanes(planes) {
58093             for (const key in planes) {
58094                 if (!planes.hasOwnProperty(key)) {
58095                     continue;
58096                 }
58097                 const plane = planes[key];
58098                 this._scenePeriphery.add(plane);
58099                 this._planesPeriphery[key] = plane;
58100             }
58101         }
58102         setPeripheryPlanes(planes) {
58103             this._clearPeriphery();
58104             this.addPeripheryPlanes(planes);
58105         }
58106         setImagePlanesOld(planes) {
58107             this._clearOld();
58108             this.addImagePlanesOld(planes);
58109         }
58110         clear() {
58111             this._clear();
58112             this._clearOld();
58113         }
58114         _clear() {
58115             this._dispose(this._planes, this._scene);
58116             this._planes = {};
58117         }
58118         _clearOld() {
58119             this._dispose(this._planesOld, this._sceneOld);
58120             this._planesOld = {};
58121         }
58122         _clearPeriphery() {
58123             this._dispose(this._planesPeriphery, this._scenePeriphery);
58124             this._planesPeriphery = {};
58125         }
58126         _dispose(planes, scene) {
58127             for (const key in planes) {
58128                 if (!planes.hasOwnProperty(key)) {
58129                     continue;
58130                 }
58131                 const plane = planes[key];
58132                 scene.remove(plane);
58133                 plane.geometry.dispose();
58134                 plane.material.dispose();
58135                 let texture = plane.material.uniforms.projectorTex.value;
58136                 if (texture != null) {
58137                     texture.dispose();
58138                 }
58139             }
58140         }
58141     }
58142
58143     class ImageGLRenderer {
58144         constructor() {
58145             this._factory = new MeshFactory();
58146             this._scene = new MeshScene();
58147             this._alpha = 0;
58148             this._alphaOld = 0;
58149             this._fadeOutSpeed = 0.05;
58150             this._currentKey = null;
58151             this._previousKey = null;
58152             this._providerDisposers = {};
58153             this._frameId = 0;
58154             this._needsRender = false;
58155         }
58156         get frameId() {
58157             return this._frameId;
58158         }
58159         get needsRender() {
58160             return this._needsRender;
58161         }
58162         indicateNeedsRender() {
58163             this._needsRender = true;
58164         }
58165         addPeripheryPlane(image, transform) {
58166             const mesh = this._factory.createMesh(image, transform);
58167             const planes = {};
58168             planes[image.id] = mesh;
58169             this._scene.addPeripheryPlanes(planes);
58170             this._needsRender = true;
58171         }
58172         clearPeripheryPlanes() {
58173             this._scene.setPeripheryPlanes({});
58174             this._needsRender = true;
58175         }
58176         updateFrame(frame) {
58177             this._updateFrameId(frame.id);
58178             this._needsRender = this._updateAlpha(frame.state.alpha) || this._needsRender;
58179             this._needsRender = this._updateAlphaOld(frame.state.alpha) || this._needsRender;
58180             this._needsRender = this._updateImagePlanes(frame.state) || this._needsRender;
58181         }
58182         setTextureProvider(key, provider) {
58183             if (key !== this._currentKey) {
58184                 return;
58185             }
58186             let createdSubscription = provider.textureCreated$
58187                 .subscribe((texture) => {
58188                 this._updateTexture(texture);
58189             });
58190             let updatedSubscription = provider.textureUpdated$
58191                 .subscribe((updated) => {
58192                 this._needsRender = true;
58193             });
58194             let dispose = () => {
58195                 createdSubscription.unsubscribe();
58196                 updatedSubscription.unsubscribe();
58197                 provider.dispose();
58198             };
58199             if (key in this._providerDisposers) {
58200                 let disposeProvider = this._providerDisposers[key];
58201                 disposeProvider();
58202                 delete this._providerDisposers[key];
58203             }
58204             this._providerDisposers[key] = dispose;
58205         }
58206         updateTextureImage(imageElement, image) {
58207             this._needsRender = true;
58208             const planes = this._extend({}, this._scene.planes, this._scene.planesOld, this._scene.planesPeriphery);
58209             for (const key in planes) {
58210                 if (!planes.hasOwnProperty(key)) {
58211                     continue;
58212                 }
58213                 if (key !== image.id) {
58214                     continue;
58215                 }
58216                 const plane = planes[key];
58217                 let material = plane.material;
58218                 let texture = material.uniforms.projectorTex.value;
58219                 texture.image = imageElement;
58220                 texture.needsUpdate = true;
58221             }
58222         }
58223         render(perspectiveCamera, renderer) {
58224             const planes = this._scene.planes;
58225             const planesOld = this._scene.planesOld;
58226             const planesPeriphery = this._scene.planesPeriphery;
58227             const planeAlpha = Object.keys(planesOld).length ? 1 : this._alpha;
58228             const peripheryAlpha = Object.keys(planesOld).length ? 1 : Math.floor(this._alpha);
58229             for (const key in planes) {
58230                 if (!planes.hasOwnProperty(key)) {
58231                     continue;
58232                 }
58233                 const plane = planes[key];
58234                 plane.material.uniforms.opacity.value = planeAlpha;
58235             }
58236             for (const key in planesOld) {
58237                 if (!planesOld.hasOwnProperty(key)) {
58238                     continue;
58239                 }
58240                 const plane = planesOld[key];
58241                 plane.material.uniforms.opacity.value = this._alphaOld;
58242             }
58243             for (const key in planesPeriphery) {
58244                 if (!planesPeriphery.hasOwnProperty(key)) {
58245                     continue;
58246                 }
58247                 const plane = planesPeriphery[key];
58248                 plane.material.uniforms.opacity.value = peripheryAlpha;
58249             }
58250             renderer.render(this._scene.scenePeriphery, perspectiveCamera);
58251             renderer.render(this._scene.scene, perspectiveCamera);
58252             renderer.render(this._scene.sceneOld, perspectiveCamera);
58253             for (const key in planes) {
58254                 if (!planes.hasOwnProperty(key)) {
58255                     continue;
58256                 }
58257                 const plane = planes[key];
58258                 plane.material.uniforms.opacity.value = this._alpha;
58259             }
58260             renderer.render(this._scene.scene, perspectiveCamera);
58261         }
58262         clearNeedsRender() {
58263             this._needsRender = false;
58264         }
58265         dispose() {
58266             this._scene.clear();
58267         }
58268         _updateFrameId(frameId) {
58269             this._frameId = frameId;
58270         }
58271         _updateAlpha(alpha) {
58272             if (alpha === this._alpha) {
58273                 return false;
58274             }
58275             this._alpha = alpha;
58276             return true;
58277         }
58278         _updateAlphaOld(alpha) {
58279             if (alpha < 1 || this._alphaOld === 0) {
58280                 return false;
58281             }
58282             this._alphaOld = Math.max(0, this._alphaOld - this._fadeOutSpeed);
58283             return true;
58284         }
58285         _updateImagePlanes(state) {
58286             if (state.currentImage == null ||
58287                 state.currentImage.id === this._currentKey) {
58288                 return false;
58289             }
58290             let previousKey = state.previousImage != null ? state.previousImage.id : null;
58291             let currentKey = state.currentImage.id;
58292             if (this._previousKey !== previousKey &&
58293                 this._previousKey !== currentKey &&
58294                 this._previousKey in this._providerDisposers) {
58295                 let disposeProvider = this._providerDisposers[this._previousKey];
58296                 disposeProvider();
58297                 delete this._providerDisposers[this._previousKey];
58298             }
58299             if (previousKey != null) {
58300                 if (previousKey !== this._currentKey && previousKey !== this._previousKey) {
58301                     let previousMesh = this._factory.createMesh(state.previousImage, state.previousTransform);
58302                     const previousPlanes = {};
58303                     previousPlanes[previousKey] = previousMesh;
58304                     this._scene.updateImagePlanes(previousPlanes);
58305                 }
58306                 this._previousKey = previousKey;
58307             }
58308             this._currentKey = currentKey;
58309             let currentMesh = this._factory.createMesh(state.currentImage, state.currentTransform);
58310             const planes = {};
58311             planes[currentKey] = currentMesh;
58312             this._scene.updateImagePlanes(planes);
58313             this._alphaOld = 1;
58314             return true;
58315         }
58316         _updateTexture(texture) {
58317             this._needsRender = true;
58318             const planes = this._scene.planes;
58319             for (const key in planes) {
58320                 if (!planes.hasOwnProperty(key)) {
58321                     continue;
58322                 }
58323                 const plane = planes[key];
58324                 let material = plane.material;
58325                 let oldTexture = material.uniforms.projectorTex.value;
58326                 material.uniforms.projectorTex.value = null;
58327                 oldTexture.dispose();
58328                 material.uniforms.projectorTex.value = texture;
58329             }
58330         }
58331         _extend(dest, ...sources) {
58332             for (const src of sources) {
58333                 for (const k in src) {
58334                     if (!src.hasOwnProperty(k)) {
58335                         continue;
58336                     }
58337                     dest[k] = src[k];
58338                 }
58339             }
58340             return dest;
58341         }
58342     }
58343
58344     var RenderPass;
58345     (function (RenderPass) {
58346         RenderPass[RenderPass["Background"] = 0] = "Background";
58347         RenderPass[RenderPass["Opaque"] = 1] = "Opaque";
58348     })(RenderPass || (RenderPass = {}));
58349
58350     /**
58351      * @class ImageTileLoader
58352      *
58353      * @classdesc Represents a loader of image tiles.
58354      */
58355     class TileLoader {
58356         /**
58357          * Create a new image image tile loader instance.
58358          *
58359          * @param {APIWrapper} _api - API wrapper.
58360          */
58361         constructor(_api) {
58362             this._api = _api;
58363             this._urls$ = new Map();
58364         }
58365         /**
58366          * Retrieve an image tile.
58367          *
58368          * @param {string} url - URL to the image tile resource
58369          */
58370         getImage$(url) {
58371             let aborter;
58372             const abort = new Promise((_, reject) => {
58373                 aborter = reject;
58374             });
58375             return [Observable.create((subscriber) => {
58376                     this._api.data
58377                         .getImageBuffer(url, abort)
58378                         .then((buffer) => {
58379                         aborter = null;
58380                         const image = new Image();
58381                         image.crossOrigin = "Anonymous";
58382                         image.onload = () => {
58383                             window.URL.revokeObjectURL(image.src);
58384                             subscriber.next(image);
58385                             subscriber.complete();
58386                         };
58387                         image.onerror = () => {
58388                             aborter = null;
58389                             window.URL.revokeObjectURL(image.src);
58390                             subscriber.error(new Error(`Failed to load image tile`));
58391                         };
58392                         const blob = new Blob([buffer]);
58393                         image.src = window.URL.createObjectURL(blob);
58394                     }, (error) => {
58395                         aborter = null;
58396                         subscriber.error(error);
58397                     });
58398                 }),
58399                 () => {
58400                     if (!!aborter) {
58401                         aborter();
58402                     }
58403                 }];
58404         }
58405         getURLs$(imageId, level) {
58406             const uniqueId = this._inventId(imageId, level);
58407             if (this._urls$.has(uniqueId)) {
58408                 return this._urls$.get(uniqueId);
58409             }
58410             const request = { imageId, z: level };
58411             const urls$ = this._api
58412                 .getImageTiles$(request)
58413                 .pipe(map(contract => contract.node), finalize(() => {
58414                 this._urls$.delete(uniqueId);
58415             }), publish(), refCount());
58416             this._urls$.set(uniqueId, urls$);
58417             return urls$;
58418         }
58419         _inventId(imageId, level) {
58420             return `${imageId}-${level}`;
58421         }
58422     }
58423
58424     /**
58425      * @class ImageTileStore
58426      *
58427      * @classdesc Represents a store for image tiles.
58428      */
58429     class TileStore {
58430         /**
58431          * Create a new image image tile store instance.
58432          */
58433         constructor() {
58434             this._tiles = new Map();
58435             this._urlLevels = new Set();
58436             this._urls = new Map();
58437         }
58438         /**
58439          * Add an image tile to the store.
58440          *
58441          * @param {string} id - The identifier for the image tile.
58442          * @param {HTMLImageElement} image - The image tile.
58443          */
58444         add(id, image) {
58445             if (this._tiles.has(id)) {
58446                 throw new Error(`Image tile already stored (${id})`);
58447             }
58448             this._tiles.set(id, image);
58449         }
58450         addURLs(level, ents) {
58451             const urls = this._urls;
58452             for (const ent of ents) {
58453                 const id = this.inventId(ent);
58454                 if (this._urls.has(id)) {
58455                     throw new Error(`URL already stored (${id})`);
58456                 }
58457                 urls.set(id, ent.url);
58458             }
58459             this._urlLevels.add(level);
58460         }
58461         /**
58462          * Dispose the store.
58463          *
58464          * @description Disposes all cached assets.
58465          */
58466         dispose() {
58467             this._tiles
58468                 .forEach(image => window.URL.revokeObjectURL(image.src));
58469             this._tiles.clear();
58470             this._urls.clear();
58471             this._urlLevels.clear();
58472         }
58473         /**
58474          * Get an image tile from the store.
58475          *
58476          * @param {string} id - The identifier for the tile.
58477          * @param {number} level - The level of the tile.
58478          */
58479         get(id) {
58480             return this._tiles.get(id);
58481         }
58482         getURL(id) {
58483             return this._urls.get(id);
58484         }
58485         /**
58486          * Check if an image tile exist in the store.
58487          *
58488          * @param {string} id - The identifier for the tile.
58489          * @param {number} level - The level of the tile.
58490          */
58491         has(id) {
58492             return this._tiles.has(id);
58493         }
58494         hasURL(id) {
58495             return this._urls.has(id);
58496         }
58497         hasURLLevel(level) {
58498             return this._urlLevels.has(level);
58499         }
58500         /**
58501          * Create a unique tile id from a tile.
58502          *
58503          * @description Tile ids are used as a hash for
58504          * storing the tile in a dictionary.
58505          *
58506          * @param {ImageTileEnt} tile - The tile.
58507          * @returns {string} Unique id.
58508          */
58509         inventId(tile) {
58510             return `${tile.z}-${tile.x}-${tile.y}`;
58511         }
58512     }
58513
58514     /**
58515      * @class RegionOfInterestCalculator
58516      *
58517      * @classdesc Represents a calculator for regions of interest.
58518      */
58519     class RegionOfInterestCalculator {
58520         constructor() {
58521             this._viewportCoords = new ViewportCoords();
58522         }
58523         /**
58524          * Compute a region of interest based on the current render camera
58525          * and the viewport size.
58526          *
58527          * @param {RenderCamera} renderCamera - Render camera used for unprojections.
58528          * @param {ViewportSize} size - Viewport size in pixels.
58529          * @param {Transform} transform - Transform used for projections.
58530          *
58531          * @returns {TileRegionOfInterest} A region of interest.
58532          */
58533         computeRegionOfInterest(renderCamera, size, transform) {
58534             const viewportBoundaryPoints = this._viewportBoundaryPoints(4);
58535             const bbox = this._viewportPointsBoundingBox(viewportBoundaryPoints, renderCamera, transform);
58536             this._clipBoundingBox(bbox);
58537             const viewportPixelWidth = 2 / size.width;
58538             const viewportPixelHeight = 2 / size.height;
58539             const centralViewportPixel = [
58540                 [-0.5 * viewportPixelWidth, 0.5 * viewportPixelHeight],
58541                 [0.5 * viewportPixelWidth, 0.5 * viewportPixelHeight],
58542                 [0.5 * viewportPixelWidth, -0.5 * viewportPixelHeight],
58543                 [-0.5 * viewportPixelWidth, -0.5 * viewportPixelHeight],
58544             ];
58545             const cpbox = this._viewportPointsBoundingBox(centralViewportPixel, renderCamera, transform);
58546             const inverted = cpbox.minX < cpbox.maxX;
58547             return {
58548                 bbox: bbox,
58549                 pixelHeight: cpbox.maxY - cpbox.minY,
58550                 pixelWidth: cpbox.maxX - cpbox.minX + (inverted ? 0 : 1),
58551             };
58552         }
58553         _viewportBoundaryPoints(pointsPerSide) {
58554             const points = [];
58555             const os = [[-1, 1], [1, 1], [1, -1], [-1, -1]];
58556             const ds = [[2, 0], [0, -2], [-2, 0], [0, 2]];
58557             for (let side = 0; side < 4; ++side) {
58558                 const o = os[side];
58559                 const d = ds[side];
58560                 for (let i = 0; i < pointsPerSide; ++i) {
58561                     points.push([o[0] + d[0] * i / pointsPerSide,
58562                         o[1] + d[1] * i / pointsPerSide]);
58563                 }
58564             }
58565             return points;
58566         }
58567         _viewportPointsBoundingBox(viewportPoints, renderCamera, transform) {
58568             const basicPoints = viewportPoints
58569                 .map((point) => {
58570                 return this._viewportCoords
58571                     .viewportToBasic(point[0], point[1], transform, renderCamera.perspective);
58572             });
58573             if (isSpherical(transform.cameraType)) {
58574                 return this._boundingBoxSpherical(basicPoints);
58575             }
58576             else {
58577                 return this._boundingBox(basicPoints);
58578             }
58579         }
58580         _boundingBox(points) {
58581             const bbox = {
58582                 maxX: Number.NEGATIVE_INFINITY,
58583                 maxY: Number.NEGATIVE_INFINITY,
58584                 minX: Number.POSITIVE_INFINITY,
58585                 minY: Number.POSITIVE_INFINITY,
58586             };
58587             for (let i = 0; i < points.length; ++i) {
58588                 bbox.minX = Math.min(bbox.minX, points[i][0]);
58589                 bbox.maxX = Math.max(bbox.maxX, points[i][0]);
58590                 bbox.minY = Math.min(bbox.minY, points[i][1]);
58591                 bbox.maxY = Math.max(bbox.maxY, points[i][1]);
58592             }
58593             return bbox;
58594         }
58595         _boundingBoxSpherical(points) {
58596             const xs = [];
58597             const ys = [];
58598             for (let i = 0; i < points.length; ++i) {
58599                 xs.push(points[i][0]);
58600                 ys.push(points[i][1]);
58601             }
58602             xs.sort((a, b) => { return this._sign(a - b); });
58603             ys.sort((a, b) => { return this._sign(a - b); });
58604             const intervalX = this._intervalSpherical(xs);
58605             return {
58606                 maxX: intervalX[1],
58607                 maxY: ys[ys.length - 1],
58608                 minX: intervalX[0],
58609                 minY: ys[0],
58610             };
58611         }
58612         /**
58613          * Find the max interval between consecutive numbers.
58614          * Assumes numbers are between 0 and 1, sorted and that
58615          * x is equivalent to x + 1.
58616          */
58617         _intervalSpherical(xs) {
58618             let maxdx = 0;
58619             let maxi = -1;
58620             for (let i = 0; i < xs.length - 1; ++i) {
58621                 const dx = xs[i + 1] - xs[i];
58622                 if (dx > maxdx) {
58623                     maxdx = dx;
58624                     maxi = i;
58625                 }
58626             }
58627             const loopdx = xs[0] + 1 - xs[xs.length - 1];
58628             if (loopdx > maxdx) {
58629                 return [xs[0], xs[xs.length - 1]];
58630             }
58631             else {
58632                 return [xs[maxi + 1], xs[maxi]];
58633             }
58634         }
58635         _clipBoundingBox(bbox) {
58636             bbox.minX = Math.max(0, Math.min(1, bbox.minX));
58637             bbox.maxX = Math.max(0, Math.min(1, bbox.maxX));
58638             bbox.minY = Math.max(0, Math.min(1, bbox.minY));
58639             bbox.maxY = Math.max(0, Math.min(1, bbox.maxY));
58640         }
58641         _sign(n) {
58642             return n > 0 ? 1 : n < 0 ? -1 : 0;
58643         }
58644     }
58645
58646     const TILE_MIN_REQUEST_LEVEL = 11;
58647     const TILE_SIZE = 1024;
58648
58649     function clamp(value, min, max) {
58650         return Math.max(min, Math.min(max, value));
58651     }
58652     function levelTilePixelSize(level) {
58653         return TILE_SIZE / levelScale(level);
58654     }
58655     function levelScale(level) {
58656         return Math.pow(2, level.z - level.max);
58657     }
58658     function rawImageLevel(size) {
58659         const s = Math.max(size.w, size.h);
58660         return Math.log(s) / Math.log(2);
58661     }
58662     function baseImageLevel(size) {
58663         return Math.ceil(rawImageLevel(size));
58664     }
58665     function clampedImageLevel(size, min, max) {
58666         return Math.max(min, Math.min(max, baseImageLevel(size)));
58667     }
58668     function basicToTileCoords2D(basic, size, level) {
58669         const tilePixelSize = levelTilePixelSize(level);
58670         const w = size.w;
58671         const h = size.h;
58672         const maxX = Math.ceil(w / tilePixelSize) - 1;
58673         const maxY = Math.ceil(h / tilePixelSize) - 1;
58674         const x = clamp(Math.floor(w * basic[0] / tilePixelSize), 0, maxX);
58675         const y = clamp(Math.floor(h * basic[1] / tilePixelSize), 0, maxY);
58676         return { x, y };
58677     }
58678     function tileToPixelCoords2D(tile, size, level) {
58679         const scale = 1 / levelScale(level);
58680         const scaledTS = scale * TILE_SIZE;
58681         const x = scaledTS * tile.x;
58682         const y = scaledTS * tile.y;
58683         const w = Math.min(scaledTS, size.w - x);
58684         const h = Math.min(scaledTS, size.h - y);
58685         return { h, x, y, w };
58686     }
58687     function hasOverlap1D(low, base, scale) {
58688         return (scale * low <= base &&
58689             base < scale * (low + 1));
58690     }
58691     function hasOverlap2D(tile1, tile2) {
58692         if (tile1.z === tile2.z) {
58693             return tile1.x === tile2.x && tile1.y === tile2.y;
58694         }
58695         const low = tile1.z < tile2.z ? tile1 : tile2;
58696         const base = tile1.z < tile2.z ? tile2 : tile1;
58697         const scale = 1 / levelScale({ max: base.z, z: low.z });
58698         const overlapX = hasOverlap1D(low.x, base.x, scale);
58699         const overlapY = hasOverlap1D(low.y, base.y, scale);
58700         return overlapX && overlapY;
58701     }
58702     function cornersToTilesCoords2D(topLeft, bottomRight, size, level) {
58703         const xs = [];
58704         if (topLeft.x > bottomRight.x) {
58705             const tilePixelSize = levelTilePixelSize(level);
58706             const maxX = Math.ceil(size.w / tilePixelSize) - 1;
58707             for (let x = topLeft.x; x <= maxX; x++) {
58708                 xs.push(x);
58709             }
58710             for (let x = 0; x <= bottomRight.x; x++) {
58711                 xs.push(x);
58712             }
58713         }
58714         else {
58715             for (let x = topLeft.x; x <= bottomRight.x; x++) {
58716                 xs.push(x);
58717             }
58718         }
58719         const tiles = [];
58720         for (const x of xs) {
58721             for (let y = topLeft.y; y <= bottomRight.y; y++) {
58722                 tiles.push({ x, y });
58723             }
58724         }
58725         return tiles;
58726     }
58727     function verifySize(size) {
58728         return size.w > 0 && size.h > 0;
58729     }
58730
58731     /**
58732      * @class TextureProvider
58733      *
58734      * @classdesc Represents a provider of textures.
58735      */
58736     class TextureProvider {
58737         /**
58738          * Create a new image texture provider instance.
58739          *
58740          * @param {string} imageId - The identifier of the image for which to request tiles.
58741          * @param {number} width - The full width of the original image.
58742          * @param {number} height - The full height of the original image.
58743          * @param {HTMLImageElement} background - Image to use as background.
58744          * @param {TileLoader} loader - Loader for retrieving tiles.
58745          * @param {TileStore} store - Store for saving tiles.
58746          * @param {THREE.WebGLRenderer} renderer - Renderer used for rendering tiles to texture.
58747          */
58748         constructor(imageId, width, height, background, loader, store, renderer) {
58749             const size = { h: height, w: width };
58750             if (!verifySize(size)) {
58751                 console.warn(`Original image size (${width}, ${height}) ` +
58752                     `is invalid (${imageId}). Tiles will not be loaded.`);
58753             }
58754             this._imageId = imageId;
58755             this._size = size;
58756             this._level = {
58757                 max: baseImageLevel(this._size),
58758                 z: -1,
58759             };
58760             this._holder = new SubscriptionHolder();
58761             this._updated$ = new Subject();
58762             this._createdSubject$ = new Subject();
58763             this._created$ = this._createdSubject$
58764                 .pipe(publishReplay(1), refCount());
58765             this._holder.push(this._created$.subscribe(() => { }));
58766             this._hasSubject$ = new Subject();
58767             this._has$ = this._hasSubject$
58768                 .pipe(startWith(false), publishReplay(1), refCount());
58769             this._holder.push(this._has$.subscribe(() => { }));
58770             this._renderedLevel = new Set();
58771             this._rendered = new Map();
58772             this._subscriptions = new Map();
58773             this._urlSubscriptions = new Map();
58774             this._loader = loader;
58775             this._store = store;
58776             this._background = background;
58777             this._renderer = renderer;
58778             this._aborts = [];
58779             this._render = null;
58780             this._disposed = false;
58781         }
58782         /**
58783          * Get disposed.
58784          *
58785          * @returns {boolean} Value indicating whether provider has
58786          * been disposed.
58787          */
58788         get disposed() {
58789             return this._disposed;
58790         }
58791         /**
58792          * Get hasTexture$.
58793          *
58794          * @returns {Observable<boolean>} Observable emitting
58795          * values indicating when the existance of a texture
58796          * changes.
58797          */
58798         get hasTexture$() {
58799             return this._has$;
58800         }
58801         /**
58802          * Get id.
58803          *
58804          * @returns {boolean} The identifier of the image for
58805          * which to render textures.
58806          */
58807         get id() {
58808             return this._imageId;
58809         }
58810         /**
58811          * Get textureUpdated$.
58812          *
58813          * @returns {Observable<boolean>} Observable emitting
58814          * values when an existing texture has been updated.
58815          */
58816         get textureUpdated$() {
58817             return this._updated$;
58818         }
58819         /**
58820          * Get textureCreated$.
58821          *
58822          * @returns {Observable<boolean>} Observable emitting
58823          * values when a new texture has been created.
58824          */
58825         get textureCreated$() {
58826             return this._created$;
58827         }
58828         /**
58829          * Abort all outstanding image tile requests.
58830          */
58831         abort() {
58832             this._subscriptions.forEach(sub => sub.unsubscribe());
58833             this._subscriptions.clear();
58834             for (const abort of this._aborts) {
58835                 abort();
58836             }
58837             this._aborts = [];
58838         }
58839         /**
58840          * Dispose the provider.
58841          *
58842          * @description Disposes all cached assets and
58843          * aborts all outstanding image tile requests.
58844          */
58845         dispose() {
58846             if (this._disposed) {
58847                 console.warn(`Texture already disposed (${this._imageId})`);
58848                 return;
58849             }
58850             this._urlSubscriptions.forEach(sub => sub.unsubscribe());
58851             this._urlSubscriptions.clear();
58852             this.abort();
58853             if (this._render != null) {
58854                 this._render.target.dispose();
58855                 this._render.target = null;
58856                 this._render.camera = null;
58857                 this._render = null;
58858             }
58859             this._store.dispose();
58860             this._holder.unsubscribe();
58861             this._renderedLevel.clear();
58862             this._background = null;
58863             this._renderer = null;
58864             this._disposed = true;
58865         }
58866         /**
58867          * Set the region of interest.
58868          *
58869          * @description When the region of interest is set the
58870          * the tile level is determined and tiles for the region
58871          * are fetched from the store or the loader and renderedLevel
58872          * to the texture.
58873          *
58874          * @param {TileRegionOfInterest} roi - Spatial edges to cache.
58875          */
58876         setRegionOfInterest(roi) {
58877             if (!verifySize(this._size)) {
58878                 return;
58879             }
58880             const virtualWidth = 1 / roi.pixelWidth;
58881             const virtualHeight = 1 / roi.pixelHeight;
58882             const level = clampedImageLevel({ h: virtualHeight, w: virtualWidth }, TILE_MIN_REQUEST_LEVEL, this._level.max);
58883             if (level !== this._level.z) {
58884                 this.abort();
58885                 this._level.z = level;
58886                 this._renderedLevel.clear();
58887                 this._rendered
58888                     .forEach((tile, id) => {
58889                     if (tile.z !== level) {
58890                         return;
58891                     }
58892                     this._renderedLevel.add(id);
58893                 });
58894             }
58895             if (this._render == null) {
58896                 this._initRender();
58897             }
58898             const topLeft = basicToTileCoords2D([roi.bbox.minX, roi.bbox.minY], this._size, this._level);
58899             const bottomRight = basicToTileCoords2D([roi.bbox.maxX, roi.bbox.maxY], this._size, this._level);
58900             const tiles = cornersToTilesCoords2D(topLeft, bottomRight, this._size, this._level);
58901             this._fetchTiles(level, tiles);
58902         }
58903         /**
58904          * Retrieve an image tile.
58905          *
58906          * @description Retrieve an image tile and render it to the
58907          * texture. Add the tile to the store and emit to the updated
58908          * observable.
58909          *
58910          * @param {ImageTileEnt} tile - The tile ent.
58911          */
58912         _fetchTile(tile) {
58913             const getTile = this._loader.getImage$(tile.url);
58914             const tile$ = getTile[0];
58915             const abort = getTile[1];
58916             this._aborts.push(abort);
58917             const tileId = this._store.inventId(tile);
58918             const subscription = tile$.subscribe((image) => {
58919                 const pixels = tileToPixelCoords2D(tile, this._size, this._level);
58920                 this._renderToTarget(pixels, image);
58921                 this._subscriptions.delete(tileId);
58922                 this._removeFromArray(abort, this._aborts);
58923                 this._markRendered(tile);
58924                 this._store.add(tileId, image);
58925                 this._updated$.next(true);
58926             }, (error) => {
58927                 this._subscriptions.delete(tileId);
58928                 this._removeFromArray(abort, this._aborts);
58929                 console.error(error);
58930             });
58931             if (!subscription.closed) {
58932                 this._subscriptions.set(tileId, subscription);
58933             }
58934         }
58935         /**
58936          * Fetch image tiles.
58937          *
58938          * @description Retrieve a image tiles and render them to the
58939          * texture. Retrieve from store if it exists, otherwise retrieve
58940          * from loader.
58941          *
58942          * @param {Array<TileCoords2D>} tiles - Array of tile coordinates to
58943          * retrieve.
58944          */
58945         _fetchTiles(level, tiles) {
58946             const urls$ = this._store.hasURLLevel(level) ?
58947                 of(undefined) :
58948                 this._loader
58949                     .getURLs$(this._imageId, level)
58950                     .pipe(tap(ents => {
58951                     if (!this._store.hasURLLevel(level)) {
58952                         this._store.addURLs(level, ents);
58953                     }
58954                 }));
58955             const subscription = urls$.subscribe(() => {
58956                 if (level !== this._level.z) {
58957                     return;
58958                 }
58959                 for (const tile of tiles) {
58960                     const ent = {
58961                         x: tile.x,
58962                         y: tile.y,
58963                         z: level,
58964                         url: null,
58965                     };
58966                     const id = this._store.inventId(ent);
58967                     if (this._renderedLevel.has(id) ||
58968                         this._subscriptions.has(id)) {
58969                         continue;
58970                     }
58971                     if (this._store.has(id)) {
58972                         const pixels = tileToPixelCoords2D(tile, this._size, this._level);
58973                         this._renderToTarget(pixels, this._store.get(id));
58974                         this._markRendered(ent);
58975                         this._updated$.next(true);
58976                         continue;
58977                     }
58978                     ent.url = this._store.getURL(id);
58979                     this._fetchTile(ent);
58980                 }
58981                 this._urlSubscriptions.delete(level);
58982             }, (error) => {
58983                 this._urlSubscriptions.delete(level);
58984                 console.error(error);
58985             });
58986             if (!subscription.closed) {
58987                 this._urlSubscriptions.set(level, subscription);
58988             }
58989         }
58990         _initRender() {
58991             const dx = this._size.w / 2;
58992             const dy = this._size.h / 2;
58993             const near = -1;
58994             const far = 1;
58995             const camera = new OrthographicCamera(-dx, dx, dy, -dy, near, far);
58996             camera.position.z = 1;
58997             const gl = this._renderer.getContext();
58998             const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
58999             const backgroundSize = Math.max(this._size.w, this._size.h);
59000             const scale = maxTextureSize > backgroundSize ?
59001                 1 : maxTextureSize / backgroundSize;
59002             const targetWidth = Math.floor(scale * this._size.w);
59003             const targetHeight = Math.floor(scale * this._size.h);
59004             const target = new WebGLRenderTarget(targetWidth, targetHeight, {
59005                 depthBuffer: false,
59006                 format: RGBFormat,
59007                 magFilter: LinearFilter,
59008                 minFilter: LinearFilter,
59009                 stencilBuffer: false,
59010             });
59011             this._render = { camera, target };
59012             const pixels = tileToPixelCoords2D({ x: 0, y: 0 }, this._size, { max: this._level.max, z: 0 });
59013             this._renderToTarget(pixels, this._background);
59014             this._createdSubject$.next(target.texture);
59015             this._hasSubject$.next(true);
59016         }
59017         /**
59018          * Mark a tile as rendered.
59019          *
59020          * @description Clears tiles marked as rendered in other
59021          * levels of the tile pyramid if they overlap the
59022          * newly rendered tile.
59023          *
59024          * @param {Arrary<number>} tile - The tile ent.
59025          */
59026         _markRendered(tile) {
59027             const others = Array.from(this._rendered.entries())
59028                 .filter(([_, t]) => {
59029                 return t.z !== tile.z;
59030             });
59031             for (const [otherId, other] of others) {
59032                 if (hasOverlap2D(tile, other)) {
59033                     this._rendered.delete(otherId);
59034                 }
59035             }
59036             const id = this._store.inventId(tile);
59037             this._rendered.set(id, tile);
59038             this._renderedLevel.add(id);
59039         }
59040         /**
59041          * Remove an item from an array if it exists in array.
59042          *
59043          * @param {T} item - Item to remove.
59044          * @param {Array<T>} array - Array from which item should be removed.
59045          */
59046         _removeFromArray(item, array) {
59047             const index = array.indexOf(item);
59048             if (index !== -1) {
59049                 array.splice(index, 1);
59050             }
59051         }
59052         /**
59053          * Render an image tile to the target texture.
59054          *
59055          * @param {ImageTileEnt} tile - Tile ent.
59056          * @param {HTMLImageElement} image - The image tile to render.
59057          */
59058         _renderToTarget(pixel, image) {
59059             const texture = new Texture(image);
59060             texture.minFilter = LinearFilter;
59061             texture.needsUpdate = true;
59062             const geometry = new PlaneGeometry(pixel.w, pixel.h);
59063             const material = new MeshBasicMaterial({
59064                 map: texture,
59065                 side: FrontSide,
59066             });
59067             const mesh = new Mesh(geometry, material);
59068             mesh.position.x = -this._size.w / 2 + pixel.x + pixel.w / 2;
59069             mesh.position.y = this._size.h / 2 - pixel.y - pixel.h / 2;
59070             const scene = new Scene();
59071             scene.add(mesh);
59072             const target = this._renderer.getRenderTarget();
59073             this._renderer.resetState();
59074             this._renderer.setRenderTarget(this._render.target);
59075             this._renderer.render(scene, this._render.camera);
59076             this._renderer.setRenderTarget(target);
59077             scene.remove(mesh);
59078             geometry.dispose();
59079             material.dispose();
59080             texture.dispose();
59081         }
59082     }
59083
59084     var State;
59085     (function (State) {
59086         State[State["Custom"] = 0] = "Custom";
59087         State[State["Earth"] = 1] = "Earth";
59088         State[State["Traversing"] = 2] = "Traversing";
59089         State[State["Waiting"] = 3] = "Waiting";
59090         State[State["WaitingInteractively"] = 4] = "WaitingInteractively";
59091     })(State || (State = {}));
59092
59093     class ImageComponent extends Component {
59094         constructor(name, container, navigator) {
59095             super(name, container, navigator);
59096             this._imageTileLoader = new TileLoader(navigator.api);
59097             this._roiCalculator = new RegionOfInterestCalculator();
59098             this._rendererOperation$ = new Subject();
59099             this._rendererCreator$ = new Subject();
59100             this._rendererDisposer$ = new Subject();
59101             this._renderer$ = this._rendererOperation$.pipe(scan((renderer, operation) => {
59102                 return operation(renderer);
59103             }, null), filter((renderer) => {
59104                 return renderer != null;
59105             }), distinctUntilChanged(undefined, (renderer) => {
59106                 return renderer.frameId;
59107             }));
59108             this._rendererCreator$.pipe(map(() => {
59109                 return (renderer) => {
59110                     if (renderer != null) {
59111                         throw new Error("Multiple image plane states can not be created at the same time");
59112                     }
59113                     return new ImageGLRenderer();
59114                 };
59115             }))
59116                 .subscribe(this._rendererOperation$);
59117             this._rendererDisposer$.pipe(map(() => {
59118                 return (renderer) => {
59119                     renderer.dispose();
59120                     return null;
59121                 };
59122             }))
59123                 .subscribe(this._rendererOperation$);
59124         }
59125         _activate() {
59126             const subs = this._subscriptions;
59127             subs.push(this._renderer$.pipe(map((renderer) => {
59128                 const renderHash = {
59129                     name: this._name,
59130                     renderer: {
59131                         frameId: renderer.frameId,
59132                         needsRender: renderer.needsRender,
59133                         render: renderer.render.bind(renderer),
59134                         pass: RenderPass.Background,
59135                     },
59136                 };
59137                 renderer.clearNeedsRender();
59138                 return renderHash;
59139             }))
59140                 .subscribe(this._container.glRenderer.render$));
59141             this._rendererCreator$.next(null);
59142             subs.push(this._navigator.stateService.currentState$.pipe(map((frame) => {
59143                 return (renderer) => {
59144                     renderer.updateFrame(frame);
59145                     return renderer;
59146                 };
59147             }))
59148                 .subscribe(this._rendererOperation$));
59149             const textureProvider$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59150                 return active ?
59151                     this._navigator.stateService.currentState$ :
59152                     new Subject();
59153             }), distinctUntilChanged(undefined, (frame) => {
59154                 return frame.state.currentImage.id;
59155             }), withLatestFrom(this._container.glRenderer.webGLRenderer$), map(([frame, renderer]) => {
59156                 const state = frame.state;
59157                 const currentNode = state.currentImage;
59158                 const currentTransform = state.currentTransform;
59159                 return new TextureProvider(currentNode.id, currentTransform.basicWidth, currentTransform.basicHeight, currentNode.image, this._imageTileLoader, new TileStore(), renderer);
59160             }), publishReplay(1), refCount());
59161             subs.push(textureProvider$.subscribe(() => { }));
59162             subs.push(textureProvider$.pipe(map((provider) => {
59163                 return (renderer) => {
59164                     renderer.setTextureProvider(provider.id, provider);
59165                     return renderer;
59166                 };
59167             }))
59168                 .subscribe(this._rendererOperation$));
59169             subs.push(textureProvider$.pipe(pairwise())
59170                 .subscribe((pair) => {
59171                 const previous = pair[0];
59172                 previous.abort();
59173             }));
59174             const roiTrigger$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59175                 return active ?
59176                     combineLatest(this._navigator.stateService.state$, this._navigator.stateService.inTranslation$) :
59177                     new Subject();
59178             }), switchMap(([state, inTranslation]) => {
59179                 const streetState = state === State.Traversing ||
59180                     state === State.Waiting ||
59181                     state === State.WaitingInteractively;
59182                 const active = streetState && !inTranslation;
59183                 return active ?
59184                     this._container.renderService.renderCameraFrame$ :
59185                     empty();
59186             }), map((camera) => {
59187                 return {
59188                     camera,
59189                     height: camera.size.height.valueOf(),
59190                     lookat: camera.camera.lookat.clone(),
59191                     width: camera.size.width.valueOf(),
59192                     zoom: camera.zoom.valueOf(),
59193                 };
59194             }), pairwise(), map(([pl0, pl1]) => {
59195                 const stalled = pl0.width === pl1.width &&
59196                     pl0.height === pl1.height &&
59197                     pl0.zoom === pl1.zoom &&
59198                     pl0.lookat.equals(pl1.lookat);
59199                 return { camera: pl1.camera, stalled };
59200             }), distinctUntilChanged((x, y) => {
59201                 return x.stalled === y.stalled;
59202             }), filter((camera) => {
59203                 return camera.stalled;
59204             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
59205             subs.push(textureProvider$.pipe(switchMap((provider) => {
59206                 return roiTrigger$.pipe(map(([stalled, size, transform]) => {
59207                     const camera = stalled.camera;
59208                     const basic = new ViewportCoords()
59209                         .viewportToBasic(0, 0, transform, camera.perspective);
59210                     if (basic[0] < 0 ||
59211                         basic[1] < 0 ||
59212                         basic[0] > 1 ||
59213                         basic[1] > 1) {
59214                         return undefined;
59215                     }
59216                     return [
59217                         this._roiCalculator
59218                             .computeRegionOfInterest(camera, size, transform),
59219                         provider,
59220                     ];
59221                 }), filter((args) => {
59222                     return !!args;
59223                 }));
59224             }), filter((args) => {
59225                 return !args[1].disposed;
59226             }))
59227                 .subscribe(([roi, provider]) => {
59228                 provider.setRegionOfInterest(roi);
59229             }));
59230             const hasTexture$ = textureProvider$
59231                 .pipe(switchMap((provider) => {
59232                 return provider.hasTexture$;
59233             }), startWith(false), publishReplay(1), refCount());
59234             subs.push(hasTexture$.subscribe(() => { }));
59235             subs.push(this._navigator.panService.panImages$.pipe(filter((panNodes) => {
59236                 return panNodes.length === 0;
59237             }), map(() => {
59238                 return (renderer) => {
59239                     renderer.clearPeripheryPlanes();
59240                     return renderer;
59241                 };
59242             }))
59243                 .subscribe(this._rendererOperation$));
59244             const cachedPanNodes$ = this._navigator.panService.panImages$.pipe(switchMap((nts) => {
59245                 return from(nts).pipe(mergeMap(([n, t]) => {
59246                     return combineLatest(this._navigator.graphService.cacheImage$(n.id).pipe(catchError((error) => {
59247                         console.error(`Failed to cache periphery image (${n.id})`, error);
59248                         return empty();
59249                     })), of(t));
59250                 }));
59251             }), share());
59252             subs.push(cachedPanNodes$.pipe(map(([n, t]) => {
59253                 return (renderer) => {
59254                     renderer.addPeripheryPlane(n, t);
59255                     return renderer;
59256                 };
59257             }))
59258                 .subscribe(this._rendererOperation$));
59259             subs.push(cachedPanNodes$.pipe(mergeMap(([n]) => {
59260                 return n.cacheImage$().pipe(catchError(() => {
59261                     return empty();
59262                 }));
59263             }), map((n) => {
59264                 return (renderer) => {
59265                     renderer.updateTextureImage(n.image, n);
59266                     return renderer;
59267                 };
59268             }))
59269                 .subscribe(this._rendererOperation$));
59270             const inTransition$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
59271                 return frame.state.alpha < 1;
59272             }), distinctUntilChanged());
59273             const panTrigger$ = combineLatest(this._container.mouseService.active$, this._container.touchService.active$, this._navigator.stateService.inMotion$, inTransition$).pipe(map(([mouseActive, touchActive, inMotion, inTransition]) => {
59274                 return !(mouseActive || touchActive || inMotion || inTransition);
59275             }), filter((trigger) => {
59276                 return trigger;
59277             }));
59278             subs.push(this._navigator.stateService.state$
59279                 .pipe(switchMap(state => {
59280                 return state === State.Traversing ?
59281                     this._navigator.panService.panImages$ :
59282                     empty();
59283             }), switchMap((nts) => {
59284                 return panTrigger$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentImage$, this._navigator.stateService.currentTransform$), mergeMap(([, renderCamera, currentNode, currentTransform]) => {
59285                     return of([
59286                         renderCamera,
59287                         currentNode,
59288                         currentTransform,
59289                         nts,
59290                     ]);
59291                 }));
59292             }), switchMap(([camera, cn, ct, nts]) => {
59293                 const direction = camera.camera.lookat.clone().sub(camera.camera.position);
59294                 const cd = new Spatial().viewingDirection(cn.rotation);
59295                 const ca = cd.angleTo(direction);
59296                 const closest = [ca, undefined];
59297                 const basic = new ViewportCoords().viewportToBasic(0, 0, ct, camera.perspective);
59298                 if (basic[0] >= 0 && basic[0] <= 1 && basic[1] >= 0 && basic[1] <= 1) {
59299                     closest[0] = Number.NEGATIVE_INFINITY;
59300                 }
59301                 for (const [n] of nts) {
59302                     const d = new Spatial().viewingDirection(n.rotation);
59303                     const a = d.angleTo(direction);
59304                     if (a < closest[0]) {
59305                         closest[0] = a;
59306                         closest[1] = n.id;
59307                     }
59308                 }
59309                 if (!closest[1]) {
59310                     return empty();
59311                 }
59312                 return this._navigator.moveTo$(closest[1]).pipe(catchError(() => {
59313                     return empty();
59314                 }));
59315             }))
59316                 .subscribe());
59317         }
59318         _deactivate() {
59319             this._rendererDisposer$.next(null);
59320             this._subscriptions.unsubscribe();
59321         }
59322         _getDefaultConfiguration() {
59323             return {};
59324         }
59325     }
59326     ImageComponent.componentName = "image";
59327
59328     class HandlerBase {
59329         /** @ignore */
59330         constructor(component, container, navigator) {
59331             this._component = component;
59332             this._container = container;
59333             this._navigator = navigator;
59334             this._enabled = false;
59335         }
59336         /**
59337          * Returns a Boolean indicating whether the interaction is enabled.
59338          *
59339          * @returns {boolean} `true` if the interaction is enabled.
59340          */
59341         get isEnabled() {
59342             return this._enabled;
59343         }
59344         /**
59345          * Enables the interaction.
59346          *
59347          * @example
59348          * ```js
59349          * <component-name>.<handler-name>.enable();
59350          * ```
59351          */
59352         enable() {
59353             if (this._enabled || !this._component.activated) {
59354                 return;
59355             }
59356             this._enable();
59357             this._enabled = true;
59358             this._component.configure(this._getConfiguration(true));
59359         }
59360         /**
59361          * Disables the interaction.
59362          *
59363          * @example
59364          * ```js
59365          * <component-name>.<handler-name>.disable();
59366          * ```
59367          */
59368         disable() {
59369             if (!this._enabled) {
59370                 return;
59371             }
59372             this._disable();
59373             this._enabled = false;
59374             if (this._component.activated) {
59375                 this._component.configure(this._getConfiguration(false));
59376             }
59377         }
59378     }
59379
59380     /**
59381      * The `KeySequenceNavigationHandler` allows the user to navigate through a sequence using the
59382      * following key commands:
59383      *
59384      * `ALT` + `Up Arrow`: Navigate to next image in the sequence.
59385      * `ALT` + `Down Arrow`: Navigate to previous image in sequence.
59386      *
59387      * @example
59388      * ```js
59389      * var keyboardComponent = viewer.getComponent("keyboard");
59390      *
59391      * keyboardComponent.keySequenceNavigation.disable();
59392      * keyboardComponent.keySequenceNavigation.enable();
59393      *
59394      * var isEnabled = keyboardComponent.keySequenceNavigation.isEnabled;
59395      * ```
59396      */
59397     class KeySequenceNavigationHandler extends HandlerBase {
59398         _enable() {
59399             const sequenceEdges$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
59400                 return image.sequenceEdges$;
59401             }));
59402             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(sequenceEdges$))
59403                 .subscribe(([event, edgeStatus]) => {
59404                 let direction = null;
59405                 switch (event.keyCode) {
59406                     case 38: // up
59407                         direction = exports.NavigationDirection.Next;
59408                         break;
59409                     case 40: // down
59410                         direction = exports.NavigationDirection.Prev;
59411                         break;
59412                     default:
59413                         return;
59414                 }
59415                 event.preventDefault();
59416                 if (!event.altKey || event.shiftKey || !edgeStatus.cached) {
59417                     return;
59418                 }
59419                 for (const edge of edgeStatus.edges) {
59420                     if (edge.data.direction === direction) {
59421                         this._navigator.moveTo$(edge.target)
59422                             .subscribe(undefined, (error) => {
59423                             if (!(error instanceof CancelMapillaryError)) {
59424                                 console.error(error);
59425                             }
59426                         });
59427                         return;
59428                     }
59429                 }
59430             });
59431         }
59432         _disable() {
59433             this._keyDownSubscription.unsubscribe();
59434         }
59435         _getConfiguration(enable) {
59436             return { keySequenceNavigation: enable };
59437         }
59438     }
59439
59440     /**
59441      * The `KeySpatialNavigationHandler` allows the user to navigate through a sequence using the
59442      * following key commands:
59443      *
59444      * `Up Arrow`: Step forward.
59445      * `Down Arrow`: Step backward.
59446      * `Left Arrow`: Step to the left.
59447      * `Rigth Arrow`: Step to the right.
59448      * `SHIFT` + `Down Arrow`: Turn around.
59449      * `SHIFT` + `Left Arrow`: Turn to the left.
59450      * `SHIFT` + `Rigth Arrow`: Turn to the right.
59451      *
59452      * @example
59453      * ```js
59454      * var keyboardComponent = viewer.getComponent("keyboard");
59455      *
59456      * keyboardComponent.keySpatialNavigation.disable();
59457      * keyboardComponent.keySpatialNavigation.enable();
59458      *
59459      * var isEnabled = keyboardComponent.keySpatialNavigation.isEnabled;
59460      * ```
59461      */
59462     class KeySpatialNavigationHandler extends HandlerBase {
59463         /** @ignore */
59464         constructor(component, container, navigator, spatial) {
59465             super(component, container, navigator);
59466             this._spatial = spatial;
59467         }
59468         _enable() {
59469             const spatialEdges$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
59470                 return image.spatialEdges$;
59471             }));
59472             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(spatialEdges$, this._navigator.stateService.currentState$))
59473                 .subscribe(([event, edgeStatus, frame]) => {
59474                 let spherical = isSpherical(frame.state.currentImage.cameraType);
59475                 let direction = null;
59476                 switch (event.keyCode) {
59477                     case 37: // left
59478                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnLeft : exports.NavigationDirection.StepLeft;
59479                         break;
59480                     case 38: // up
59481                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.Spherical : exports.NavigationDirection.StepForward;
59482                         break;
59483                     case 39: // right
59484                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnRight : exports.NavigationDirection.StepRight;
59485                         break;
59486                     case 40: // down
59487                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnU : exports.NavigationDirection.StepBackward;
59488                         break;
59489                     default:
59490                         return;
59491                 }
59492                 event.preventDefault();
59493                 if (event.altKey || !edgeStatus.cached ||
59494                     (event.shiftKey && spherical)) {
59495                     return;
59496                 }
59497                 if (!spherical) {
59498                     this._moveDir(direction, edgeStatus);
59499                 }
59500                 else {
59501                     const shifts = {};
59502                     shifts[exports.NavigationDirection.StepBackward] = Math.PI;
59503                     shifts[exports.NavigationDirection.StepForward] = 0;
59504                     shifts[exports.NavigationDirection.StepLeft] = Math.PI / 2;
59505                     shifts[exports.NavigationDirection.StepRight] = -Math.PI / 2;
59506                     const phi = this._rotationFromCamera(frame.state.camera).phi;
59507                     const navigationAngle = this._spatial.wrapAngle(phi + shifts[direction]);
59508                     const threshold = Math.PI / 4;
59509                     const edges = edgeStatus.edges.filter((e) => {
59510                         return e.data.direction === exports.NavigationDirection.Spherical || e.data.direction === direction;
59511                     });
59512                     let smallestAngle = Number.MAX_VALUE;
59513                     let toKey = null;
59514                     for (const edge of edges) {
59515                         const angle = Math.abs(this._spatial.wrapAngle(edge.data.worldMotionAzimuth - navigationAngle));
59516                         if (angle < Math.min(smallestAngle, threshold)) {
59517                             smallestAngle = angle;
59518                             toKey = edge.target;
59519                         }
59520                     }
59521                     if (toKey == null) {
59522                         return;
59523                     }
59524                     this._moveTo(toKey);
59525                 }
59526             });
59527         }
59528         _disable() {
59529             this._keyDownSubscription.unsubscribe();
59530         }
59531         _getConfiguration(enable) {
59532             return { keySpatialNavigation: enable };
59533         }
59534         _moveDir(direction, edgeStatus) {
59535             for (const edge of edgeStatus.edges) {
59536                 if (edge.data.direction === direction) {
59537                     this._moveTo(edge.target);
59538                     return;
59539                 }
59540             }
59541         }
59542         _moveTo(id) {
59543             this._navigator.moveTo$(id)
59544                 .subscribe(undefined, (error) => {
59545                 if (!(error instanceof CancelMapillaryError)) {
59546                     console.error(error);
59547                 }
59548             });
59549         }
59550         _rotationFromCamera(camera) {
59551             let direction = camera.lookat.clone().sub(camera.position);
59552             let upProjection = direction.clone().dot(camera.up);
59553             let planeProjection = direction.clone().sub(camera.up.clone().multiplyScalar(upProjection));
59554             let phi = Math.atan2(planeProjection.y, planeProjection.x);
59555             let theta = Math.PI / 2 - this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
59556             return { phi: phi, theta: theta };
59557         }
59558     }
59559
59560     /**
59561      * The `KeyZoomHandler` allows the user to zoom in and out using the
59562      * following key commands:
59563      *
59564      * `+`: Zoom in.
59565      * `-`: Zoom out.
59566      *
59567      * @example
59568      * ```js
59569      * var keyboardComponent = viewer.getComponent("keyboard");
59570      *
59571      * keyboardComponent.keyZoom.disable();
59572      * keyboardComponent.keyZoom.enable();
59573      *
59574      * var isEnabled = keyboardComponent.keyZoom.isEnabled;
59575      * ```
59576      */
59577     class KeyZoomHandler extends HandlerBase {
59578         /** @ignore */
59579         constructor(component, container, navigator, viewportCoords) {
59580             super(component, container, navigator);
59581             this._viewportCoords = viewportCoords;
59582         }
59583         _enable() {
59584             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
59585                 .subscribe(([event, render, transform]) => {
59586                 if (event.altKey || event.ctrlKey || event.metaKey) {
59587                     return;
59588                 }
59589                 let delta = 0;
59590                 switch (event.key) {
59591                     case "+":
59592                         delta = 1;
59593                         break;
59594                     case "-":
59595                         delta = -1;
59596                         break;
59597                     default:
59598                         return;
59599                 }
59600                 event.preventDefault();
59601                 const unprojected = this._viewportCoords.unprojectFromViewport(0, 0, render.perspective);
59602                 const reference = transform.projectBasic(unprojected.toArray());
59603                 this._navigator.stateService.zoomIn(delta, reference);
59604             });
59605         }
59606         _disable() {
59607             this._keyDownSubscription.unsubscribe();
59608         }
59609         _getConfiguration(enable) {
59610             return { keyZoom: enable };
59611         }
59612     }
59613
59614     /**
59615      * The `KeyPlayHandler` allows the user to control the play behavior
59616      * using the following key commands:
59617      *
59618      * `Spacebar`: Start or stop playing.
59619      * `SHIFT` + `D`: Switch direction.
59620      * `<`: Decrease speed.
59621      * `>`: Increase speed.
59622      *
59623      * @example
59624      * ```js
59625      * var keyboardComponent = viewer.getComponent("keyboard");
59626      *
59627      * keyboardComponent.keyPlay.disable();
59628      * keyboardComponent.keyPlay.enable();
59629      *
59630      * var isEnabled = keyboardComponent.keyPlay.isEnabled;
59631      * ```
59632      */
59633     class KeyPlayHandler extends HandlerBase {
59634         _enable() {
59635             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(this._navigator.playService.playing$, this._navigator.playService.direction$, this._navigator.playService.speed$, this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
59636                 return image.sequenceEdges$;
59637             })), this._navigator.stateService.state$.pipe(map((state) => {
59638                 return state === State.Earth;
59639             }), distinctUntilChanged())))
59640                 .subscribe(([event, playing, direction, speed, status, earth]) => {
59641                 if (event.altKey || event.ctrlKey || event.metaKey) {
59642                     return;
59643                 }
59644                 switch (event.key) {
59645                     case "D":
59646                         if (!event.shiftKey) {
59647                             return;
59648                         }
59649                         const newDirection = playing ?
59650                             null : direction === exports.NavigationDirection.Next ?
59651                             exports.NavigationDirection.Prev : direction === exports.NavigationDirection.Prev ?
59652                             exports.NavigationDirection.Next : null;
59653                         if (newDirection != null) {
59654                             this._navigator.playService.setDirection(newDirection);
59655                         }
59656                         break;
59657                     case " ":
59658                         if (event.shiftKey) {
59659                             return;
59660                         }
59661                         if (!earth) {
59662                             if (playing) {
59663                                 this._navigator.playService.stop();
59664                             }
59665                             else {
59666                                 for (let edge of status.edges) {
59667                                     if (edge.data.direction === direction) {
59668                                         this._navigator.playService.play();
59669                                     }
59670                                 }
59671                             }
59672                         }
59673                         break;
59674                     case "<":
59675                         this._navigator.playService.setSpeed(speed - 0.05);
59676                         break;
59677                     case ">":
59678                         this._navigator.playService.setSpeed(speed + 0.05);
59679                         break;
59680                     default:
59681                         return;
59682                 }
59683                 event.preventDefault();
59684             });
59685         }
59686         _disable() {
59687             this._keyDownSubscription.unsubscribe();
59688         }
59689         _getConfiguration(enable) {
59690             return { keyPlay: enable };
59691         }
59692     }
59693
59694     /**
59695      * @class KeyboardComponent
59696      *
59697      * @classdesc Component for keyboard event handling.
59698      *
59699      * To retrive and use the keyboard component
59700      *
59701      * @example
59702      * ```js
59703      * var viewer = new Viewer({ ... });
59704      *
59705      * var keyboardComponent = viewer.getComponent("keyboard");
59706      * ```
59707      */
59708     class KeyboardComponent extends Component {
59709         /** @ignore */
59710         constructor(name, container, navigator) {
59711             super(name, container, navigator);
59712             this._keyPlayHandler =
59713                 new KeyPlayHandler(this, container, navigator);
59714             this._keySequenceNavigationHandler =
59715                 new KeySequenceNavigationHandler(this, container, navigator);
59716             this._keySpatialNavigationHandler =
59717                 new KeySpatialNavigationHandler(this, container, navigator, new Spatial());
59718             this._keyZoomHandler =
59719                 new KeyZoomHandler(this, container, navigator, new ViewportCoords());
59720         }
59721         /**
59722          * Get key play.
59723          *
59724          * @returns {KeyPlayHandler} The key play handler.
59725          */
59726         get keyPlay() {
59727             return this._keyPlayHandler;
59728         }
59729         /**
59730          * Get key sequence navigation.
59731          *
59732          * @returns {KeySequenceNavigationHandler} The key sequence navigation handler.
59733          */
59734         get keySequenceNavigation() {
59735             return this._keySequenceNavigationHandler;
59736         }
59737         /**
59738          * Get spatial.
59739          *
59740          * @returns {KeySpatialNavigationHandler} The spatial handler.
59741          */
59742         get keySpatialNavigation() {
59743             return this._keySpatialNavigationHandler;
59744         }
59745         /**
59746          * Get key zoom.
59747          *
59748          * @returns {KeyZoomHandler} The key zoom handler.
59749          */
59750         get keyZoom() {
59751             return this._keyZoomHandler;
59752         }
59753         _activate() {
59754             this._subscriptions.push(this._configuration$
59755                 .subscribe((configuration) => {
59756                 if (configuration.keyPlay) {
59757                     this._keyPlayHandler.enable();
59758                 }
59759                 else {
59760                     this._keyPlayHandler.disable();
59761                 }
59762                 if (configuration.keySequenceNavigation) {
59763                     this._keySequenceNavigationHandler.enable();
59764                 }
59765                 else {
59766                     this._keySequenceNavigationHandler.disable();
59767                 }
59768                 if (configuration.keySpatialNavigation) {
59769                     this._keySpatialNavigationHandler.enable();
59770                 }
59771                 else {
59772                     this._keySpatialNavigationHandler.disable();
59773                 }
59774                 if (configuration.keyZoom) {
59775                     this._keyZoomHandler.enable();
59776                 }
59777                 else {
59778                     this._keyZoomHandler.disable();
59779                 }
59780             }));
59781         }
59782         _deactivate() {
59783             this._subscriptions.unsubscribe();
59784             this._keyPlayHandler.disable();
59785             this._keySequenceNavigationHandler.disable();
59786             this._keySpatialNavigationHandler.disable();
59787             this._keyZoomHandler.disable();
59788         }
59789         _getDefaultConfiguration() {
59790             return { keyPlay: true, keySequenceNavigation: true, keySpatialNavigation: true, keyZoom: true };
59791         }
59792     }
59793     KeyboardComponent.componentName = "keyboard";
59794
59795     class MarkerScene {
59796         constructor(scene, raycaster) {
59797             this._needsRender = false;
59798             this._interactiveObjects = [];
59799             this._markers = {};
59800             this._objectMarkers = {};
59801             this._raycaster = !!raycaster ? raycaster : new Raycaster();
59802             this._scene = !!scene ? scene : new Scene();
59803         }
59804         get markers() {
59805             return this._markers;
59806         }
59807         get needsRender() {
59808             return this._needsRender;
59809         }
59810         add(marker, position) {
59811             if (marker.id in this._markers) {
59812                 this._dispose(marker.id);
59813             }
59814             marker.createGeometry(position);
59815             this._scene.add(marker.geometry);
59816             this._markers[marker.id] = marker;
59817             for (let interactiveObject of marker.getInteractiveObjects()) {
59818                 this._interactiveObjects.push(interactiveObject);
59819                 this._objectMarkers[interactiveObject.uuid] = marker.id;
59820             }
59821             this._needsRender = true;
59822         }
59823         clear() {
59824             for (const id in this._markers) {
59825                 if (!this._markers.hasOwnProperty) {
59826                     continue;
59827                 }
59828                 this._dispose(id);
59829             }
59830             this._needsRender = true;
59831         }
59832         get(id) {
59833             return this._markers[id];
59834         }
59835         getAll() {
59836             return Object
59837                 .keys(this._markers)
59838                 .map((id) => { return this._markers[id]; });
59839         }
59840         has(id) {
59841             return id in this._markers;
59842         }
59843         intersectObjects([viewportX, viewportY], camera) {
59844             this._raycaster.setFromCamera(new Vector2(viewportX, viewportY), camera);
59845             const intersects = this._raycaster.intersectObjects(this._interactiveObjects);
59846             for (const intersect of intersects) {
59847                 if (intersect.object.uuid in this._objectMarkers) {
59848                     return this._objectMarkers[intersect.object.uuid];
59849                 }
59850             }
59851             return null;
59852         }
59853         lerpAltitude(id, alt, alpha) {
59854             if (!(id in this._markers)) {
59855                 return;
59856             }
59857             this._markers[id].lerpAltitude(alt, alpha);
59858             this._needsRender = true;
59859         }
59860         remove(id) {
59861             if (!(id in this._markers)) {
59862                 return;
59863             }
59864             this._dispose(id);
59865             this._needsRender = true;
59866         }
59867         render(perspectiveCamera, renderer) {
59868             renderer.render(this._scene, perspectiveCamera);
59869             this._needsRender = false;
59870         }
59871         update(id, position, lngLat) {
59872             if (!(id in this._markers)) {
59873                 return;
59874             }
59875             const marker = this._markers[id];
59876             marker.updatePosition(position, lngLat);
59877             this._needsRender = true;
59878         }
59879         _dispose(id) {
59880             const marker = this._markers[id];
59881             this._scene.remove(marker.geometry);
59882             for (let interactiveObject of marker.getInteractiveObjects()) {
59883                 const index = this._interactiveObjects.indexOf(interactiveObject);
59884                 if (index !== -1) {
59885                     this._interactiveObjects.splice(index, 1);
59886                 }
59887                 else {
59888                     console.warn(`Object does not exist (${interactiveObject.id}) for ${id}`);
59889                 }
59890                 delete this._objectMarkers[interactiveObject.uuid];
59891             }
59892             marker.disposeGeometry();
59893             delete this._markers[id];
59894         }
59895     }
59896
59897     /**
59898      * @class MarkerComponent
59899      *
59900      * @classdesc Component for showing and editing 3D marker objects.
59901      *
59902      * The `add` method is used for adding new markers or replacing
59903      * markers already in the set.
59904      *
59905      * If a marker already in the set has the same
59906      * id as one of the markers added, the old marker will be removed and
59907      * the added marker will take its place.
59908      *
59909      * It is not possible to update markers in the set by updating any properties
59910      * directly on the marker object. Markers need to be replaced by
59911      * re-adding them for updates to geographic position or configuration
59912      * to be reflected.
59913      *
59914      * Markers added to the marker component can be either interactive
59915      * or non-interactive. Different marker types define their behavior.
59916      * Markers with interaction support can be configured with options
59917      * to respond to dragging inside the viewer and be detected when
59918      * retrieving markers from pixel points with the `getMarkerIdAt` method.
59919      *
59920      * To retrive and use the marker component
59921      *
59922      * @example
59923      * ```js
59924      * var viewer = new Viewer({ component: { marker: true }, ... });
59925      *
59926      * var markerComponent = viewer.getComponent("marker");
59927      * ```
59928      */
59929     class MarkerComponent extends Component {
59930         /** @ignore */
59931         constructor(name, container, navigator) {
59932             super(name, container, navigator);
59933             this._graphCalculator = new GraphCalculator();
59934             this._markerScene = new MarkerScene();
59935             this._markerSet = new MarkerSet();
59936             this._viewportCoords = new ViewportCoords();
59937             this._relativeGroundAltitude = -2;
59938         }
59939         /**
59940          * Add markers to the marker set or replace markers in the marker set.
59941          *
59942          * @description If a marker already in the set has the same
59943          * id as one of the markers added, the old marker will be removed
59944          * the added marker will take its place.
59945          *
59946          * Any marker inside the visible bounding bbox
59947          * will be initialized and placed in the viewer.
59948          *
59949          * @param {Array<Marker>} markers - Markers to add.
59950          *
59951          * @example
59952          * ```js
59953          * markerComponent.add([marker1, marker2]);
59954          * ```
59955          */
59956         add(markers) {
59957             this._markerSet.add(markers);
59958         }
59959         fire(type, event) {
59960             super.fire(type, event);
59961         }
59962         /**
59963          * Returns the marker in the marker set with the specified id, or
59964          * undefined if the id matches no marker.
59965          *
59966          * @param {string} markerId - Id of the marker.
59967          *
59968          * @example
59969          * ```js
59970          * var marker = markerComponent.get("markerId");
59971          * ```
59972          *
59973          */
59974         get(markerId) {
59975             return this._markerSet.get(markerId);
59976         }
59977         /**
59978          * Returns an array of all markers.
59979          *
59980          * @example
59981          * ```js
59982          * var markers = markerComponent.getAll();
59983          * ```
59984          */
59985         getAll() {
59986             return this._markerSet.getAll();
59987         }
59988         /**
59989          * Returns the id of the interactive marker closest to the current camera
59990          * position at the specified point.
59991          *
59992          * @description Notice that the pixelPoint argument requires x, y
59993          * coordinates from pixel space.
59994          *
59995          * With this function, you can use the coordinates provided by mouse
59996          * events to get information out of the marker component.
59997          *
59998          * If no interactive geometry of an interactive marker exist at the pixel
59999          * point, `null` will be returned.
60000          *
60001          * @param {Array<number>} pixelPoint - Pixel coordinates on the viewer element.
60002          * @returns {string} Id of the interactive marker closest to the camera. If no
60003          * interactive marker exist at the pixel point, `null` will be returned.
60004          *
60005          * @example
60006          * ```js
60007          * markerComponent.getMarkerIdAt([100, 100])
60008          *     .then((markerId) => { console.log(markerId); });
60009          * ```
60010          */
60011         getMarkerIdAt(pixelPoint) {
60012             return new Promise((resolve, reject) => {
60013                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
60014                     const viewport = this._viewportCoords
60015                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
60016                     const id = this._markerScene.intersectObjects(viewport, render.perspective);
60017                     return id;
60018                 }))
60019                     .subscribe((id) => {
60020                     resolve(id);
60021                 }, (error) => {
60022                     reject(error);
60023                 });
60024             });
60025         }
60026         /**
60027          * Check if a marker exist in the marker set.
60028          *
60029          * @param {string} markerId - Id of the marker.
60030          *
60031          * @example
60032          * ```js
60033          * var markerExists = markerComponent.has("markerId");
60034          * ```
60035          */
60036         has(markerId) {
60037             return this._markerSet.has(markerId);
60038         }
60039         off(type, handler) {
60040             super.off(type, handler);
60041         }
60042         on(type, handler) {
60043             super.on(type, handler);
60044         }
60045         /**
60046          * Remove markers with the specified ids from the marker set.
60047          *
60048          * @param {Array<string>} markerIds - Ids for markers to remove.
60049          *
60050          * @example
60051          * ```js
60052          * markerComponent.remove(["id-1", "id-2"]);
60053          * ```
60054          */
60055         remove(markerIds) {
60056             this._markerSet.remove(markerIds);
60057         }
60058         /**
60059          * Remove all markers from the marker set.
60060          *
60061          * @example
60062          * ```js
60063          * markerComponent.removeAll();
60064          * ```
60065          */
60066         removeAll() {
60067             this._markerSet.removeAll();
60068         }
60069         _activate() {
60070             const groundAltitude$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
60071                 return frame.state.camera.position.z + this._relativeGroundAltitude;
60072             }), distinctUntilChanged((a1, a2) => {
60073                 return Math.abs(a1 - a2) < 0.01;
60074             }), publishReplay(1), refCount());
60075             const geoInitiated$ = combineLatest(groundAltitude$, this._navigator.stateService.reference$).pipe(first(), map(() => { }), publishReplay(1), refCount());
60076             const clampedConfiguration$ = this._configuration$.pipe(map((configuration) => {
60077                 return { visibleBBoxSize: Math.max(1, Math.min(200, configuration.visibleBBoxSize)) };
60078             }));
60079             const currentLngLat$ = this._navigator.stateService.currentImage$.pipe(map((image) => { return image.lngLat; }), publishReplay(1), refCount());
60080             const visibleBBox$ = combineLatest(clampedConfiguration$, currentLngLat$).pipe(map(([configuration, lngLat]) => {
60081                 return this._graphCalculator
60082                     .boundingBoxCorners(lngLat, configuration.visibleBBoxSize / 2);
60083             }), publishReplay(1), refCount());
60084             const visibleMarkers$ = combineLatest(concat(of(this._markerSet), this._markerSet.changed$), visibleBBox$).pipe(map(([set, bbox]) => {
60085                 return set.search(bbox);
60086             }));
60087             const subs = this._subscriptions;
60088             subs.push(geoInitiated$.pipe(switchMap(() => {
60089                 return visibleMarkers$.pipe(withLatestFrom(this._navigator.stateService.reference$, groundAltitude$));
60090             }))
60091                 .subscribe(([markers, reference, alt]) => {
60092                 const markerScene = this._markerScene;
60093                 const sceneMarkers = markerScene.markers;
60094                 const markersToRemove = Object.assign({}, sceneMarkers);
60095                 for (const marker of markers) {
60096                     if (marker.id in sceneMarkers) {
60097                         delete markersToRemove[marker.id];
60098                     }
60099                     else {
60100                         const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
60101                         markerScene.add(marker, point3d);
60102                     }
60103                 }
60104                 for (const id in markersToRemove) {
60105                     if (!markersToRemove.hasOwnProperty(id)) {
60106                         continue;
60107                     }
60108                     markerScene.remove(id);
60109                 }
60110             }));
60111             subs.push(geoInitiated$.pipe(switchMap(() => {
60112                 return this._markerSet.updated$.pipe(withLatestFrom(visibleBBox$, this._navigator.stateService.reference$, groundAltitude$));
60113             }))
60114                 .subscribe(([markers, [sw, ne], reference, alt]) => {
60115                 const markerScene = this._markerScene;
60116                 for (const marker of markers) {
60117                     const exists = markerScene.has(marker.id);
60118                     const visible = marker.lngLat.lat > sw.lat &&
60119                         marker.lngLat.lat < ne.lat &&
60120                         marker.lngLat.lng > sw.lng &&
60121                         marker.lngLat.lng < ne.lng;
60122                     if (visible) {
60123                         const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
60124                         markerScene.add(marker, point3d);
60125                     }
60126                     else if (!visible && exists) {
60127                         markerScene.remove(marker.id);
60128                     }
60129                 }
60130             }));
60131             subs.push(this._navigator.stateService.reference$.pipe(skip(1), withLatestFrom(groundAltitude$))
60132                 .subscribe(([reference, alt]) => {
60133                 const markerScene = this._markerScene;
60134                 for (const marker of markerScene.getAll()) {
60135                     const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
60136                     markerScene.update(marker.id, point3d);
60137                 }
60138             }));
60139             subs.push(groundAltitude$.pipe(skip(1), withLatestFrom(this._navigator.stateService.reference$, currentLngLat$))
60140                 .subscribe(([alt, reference, lngLat]) => {
60141                 const markerScene = this._markerScene;
60142                 const position = geodeticToEnu(lngLat.lng, lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
60143                 for (const marker of markerScene.getAll()) {
60144                     const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
60145                     const distanceX = point3d[0] - position[0];
60146                     const distanceY = point3d[1] - position[1];
60147                     const groundDistance = Math
60148                         .sqrt(distanceX * distanceX + distanceY * distanceY);
60149                     if (groundDistance > 50) {
60150                         continue;
60151                     }
60152                     markerScene.lerpAltitude(marker.id, alt, Math.min(1, Math.max(0, 1.2 - 1.2 * groundDistance / 50)));
60153                 }
60154             }));
60155             subs.push(this._navigator.stateService.currentState$
60156                 .pipe(map((frame) => {
60157                 const scene = this._markerScene;
60158                 return {
60159                     name: this._name,
60160                     renderer: {
60161                         frameId: frame.id,
60162                         needsRender: scene.needsRender,
60163                         render: scene.render.bind(scene),
60164                         pass: RenderPass.Opaque,
60165                     },
60166                 };
60167             }))
60168                 .subscribe(this._container.glRenderer.render$));
60169             const hoveredMarkerId$ = combineLatest(this._container.renderService.renderCamera$, this._container.mouseService.mouseMove$)
60170                 .pipe(map(([render, event]) => {
60171                 const element = this._container.container;
60172                 const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
60173                 const viewport = this._viewportCoords
60174                     .canvasToViewport(canvasX, canvasY, element);
60175                 const markerId = this._markerScene.intersectObjects(viewport, render.perspective);
60176                 return markerId;
60177             }), publishReplay(1), refCount());
60178             const draggingStarted$ = this._container.mouseService
60179                 .filtered$(this._name, this._container.mouseService.mouseDragStart$).pipe(map(() => {
60180                 return true;
60181             }));
60182             const draggingStopped$ = this._container.mouseService
60183                 .filtered$(this._name, this._container.mouseService.mouseDragEnd$).pipe(map(() => {
60184                 return false;
60185             }));
60186             const filteredDragging$ = merge(draggingStarted$, draggingStopped$)
60187                 .pipe(startWith(false));
60188             subs.push(merge(draggingStarted$.pipe(withLatestFrom(hoveredMarkerId$)), combineLatest(draggingStopped$, of(null))).pipe(startWith([false, null]), pairwise())
60189                 .subscribe(([previous, current]) => {
60190                 const dragging = current[0];
60191                 const type = dragging ?
60192                     "markerdragstart" :
60193                     "markerdragend";
60194                 const id = dragging ? current[1] : previous[1];
60195                 const marker = this._markerScene.get(id);
60196                 const event = {
60197                     marker,
60198                     target: this,
60199                     type,
60200                 };
60201                 this.fire(type, event);
60202             }));
60203             const mouseDown$ = merge(this._container.mouseService.mouseDown$.pipe(map(() => { return true; })), this._container.mouseService.documentMouseUp$.pipe(map(() => { return false; }))).pipe(startWith(false));
60204             subs.push(combineLatest(this._container.mouseService.active$, hoveredMarkerId$.pipe(distinctUntilChanged()), mouseDown$, filteredDragging$)
60205                 .pipe(map(([active, markerId, mouseDown, filteredDragging]) => {
60206                 return (!active && markerId != null && mouseDown) ||
60207                     filteredDragging;
60208             }), distinctUntilChanged())
60209                 .subscribe((claim) => {
60210                 if (claim) {
60211                     this._container.mouseService.claimMouse(this._name, 1);
60212                     this._container.mouseService.claimWheel(this._name, 1);
60213                 }
60214                 else {
60215                     this._container.mouseService.unclaimMouse(this._name);
60216                     this._container.mouseService.unclaimWheel(this._name);
60217                 }
60218             }));
60219             const offset$ = this._container.mouseService
60220                 .filtered$(this._name, this._container.mouseService.mouseDragStart$).pipe(withLatestFrom(hoveredMarkerId$, this._container.renderService.renderCamera$), map(([e, id, r]) => {
60221                 const marker = this._markerScene.get(id);
60222                 const element = this._container.container;
60223                 const [groundCanvasX, groundCanvasY] = this._viewportCoords
60224                     .projectToCanvas(marker.geometry.position
60225                     .toArray(), element, r.perspective);
60226                 const [canvasX, canvasY] = this._viewportCoords
60227                     .canvasPosition(e, element);
60228                 const offset = [canvasX - groundCanvasX, canvasY - groundCanvasY];
60229                 return [marker, offset, r];
60230             }), publishReplay(1), refCount());
60231             subs.push(this._container.mouseService
60232                 .filtered$(this._name, this._container.mouseService.mouseDrag$)
60233                 .pipe(withLatestFrom(offset$, this._navigator.stateService.reference$, clampedConfiguration$))
60234                 .subscribe(([event, [marker, offset, render], reference, configuration]) => {
60235                 if (!this._markerScene.has(marker.id)) {
60236                     return;
60237                 }
60238                 const element = this._container.container;
60239                 const [canvasX, canvasY] = this._viewportCoords
60240                     .canvasPosition(event, element);
60241                 const groundX = canvasX - offset[0];
60242                 const groundY = canvasY - offset[1];
60243                 const [viewportX, viewportY] = this._viewportCoords
60244                     .canvasToViewport(groundX, groundY, element);
60245                 const direction = new Vector3(viewportX, viewportY, 1)
60246                     .unproject(render.perspective)
60247                     .sub(render.perspective.position)
60248                     .normalize();
60249                 const distance = Math.min(this._relativeGroundAltitude / direction.z, configuration.visibleBBoxSize / 2 - 0.1);
60250                 if (distance < 0) {
60251                     return;
60252                 }
60253                 const intersection = direction
60254                     .clone()
60255                     .multiplyScalar(distance)
60256                     .add(render.perspective.position);
60257                 intersection.z =
60258                     render.perspective.position.z
60259                         + this._relativeGroundAltitude;
60260                 const [lng, lat] = enuToGeodetic(intersection.x, intersection.y, intersection.z, reference.lng, reference.lat, reference.alt);
60261                 this._markerScene
60262                     .update(marker.id, intersection.toArray(), { lat, lng });
60263                 this._markerSet.update(marker);
60264                 const type = "markerposition";
60265                 const markerEvent = {
60266                     marker,
60267                     target: this,
60268                     type,
60269                 };
60270                 this.fire(type, markerEvent);
60271             }));
60272         }
60273         _deactivate() {
60274             this._subscriptions.unsubscribe();
60275             this._markerScene.clear();
60276         }
60277         _getDefaultConfiguration() {
60278             return { visibleBBoxSize: 100 };
60279         }
60280     }
60281     MarkerComponent.componentName = "marker";
60282
60283     function sign$1(n) {
60284         return n > 0 ? 1 : n < 0 ? -1 : 0;
60285     }
60286     function colinearPointOnSegment(p, s) {
60287         return p.x <= Math.max(s.p1.x, s.p2.x) &&
60288             p.x >= Math.min(s.p1.x, s.p2.x) &&
60289             p.y >= Math.max(s.p1.y, s.p2.y) &&
60290             p.y >= Math.min(s.p1.y, s.p2.y);
60291     }
60292     function parallel(s1, s2) {
60293         const ux = s1.p2.x - s1.p1.x;
60294         const uy = s1.p2.y - s1.p1.y;
60295         const vx = s2.p2.x - s2.p1.x;
60296         const vy = s2.p2.y - s2.p1.y;
60297         const cross = ux * vy - uy * vx;
60298         const u2 = ux * ux + uy * uy;
60299         const v2 = vx * vx + vy * vy;
60300         const epsilon2 = 1e-10;
60301         return cross * cross < epsilon2 * u2 * v2;
60302     }
60303     function tripletOrientation(p1, p2, p3) {
60304         const orientation = (p2.y - p1.y) * (p3.x - p2.x) -
60305             (p3.y - p2.y) * (p2.x - p1.x);
60306         return sign$1(orientation);
60307     }
60308     function segmentsIntersect(s1, s2) {
60309         if (parallel(s1, s2)) {
60310             return false;
60311         }
60312         const o1 = tripletOrientation(s1.p1, s1.p2, s2.p1);
60313         const o2 = tripletOrientation(s1.p1, s1.p2, s2.p2);
60314         const o3 = tripletOrientation(s2.p1, s2.p2, s1.p1);
60315         const o4 = tripletOrientation(s2.p1, s2.p2, s1.p2);
60316         if (o1 !== o2 && o3 !== o4) {
60317             return true;
60318         }
60319         if (o1 === 0 && colinearPointOnSegment(s2.p1, s1)) {
60320             return true;
60321         }
60322         if (o2 === 0 && colinearPointOnSegment(s2.p2, s1)) {
60323             return true;
60324         }
60325         if (o3 === 0 && colinearPointOnSegment(s1.p1, s2)) {
60326             return true;
60327         }
60328         if (o4 === 0 && colinearPointOnSegment(s1.p2, s2)) {
60329             return true;
60330         }
60331         return false;
60332     }
60333     function segmentIntersection(s1, s2) {
60334         if (parallel(s1, s2)) {
60335             return undefined;
60336         }
60337         const x1 = s1.p1.x;
60338         const x2 = s1.p2.x;
60339         const y1 = s1.p1.y;
60340         const y2 = s1.p2.y;
60341         const x3 = s2.p1.x;
60342         const x4 = s2.p2.x;
60343         const y3 = s2.p1.y;
60344         const y4 = s2.p2.y;
60345         const den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
60346         const xNum = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
60347         const yNum = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
60348         return { x: xNum / den, y: yNum / den };
60349     }
60350
60351     function basicBoundaryPoints(pointsPerSide) {
60352         let points = [];
60353         let os = [[0, 0], [1, 0], [1, 1], [0, 1]];
60354         let ds = [[1, 0], [0, 1], [-1, 0], [0, -1]];
60355         for (let side = 0; side < 4; ++side) {
60356             let o = os[side];
60357             let d = ds[side];
60358             for (let i = 0; i < pointsPerSide; ++i) {
60359                 points.push([o[0] + d[0] * i / pointsPerSide,
60360                     o[1] + d[1] * i / pointsPerSide]);
60361             }
60362         }
60363         return points;
60364     }
60365     function insideViewport(x, y) {
60366         return x >= -1 && x <= 1 && y >= -1 && y <= 1;
60367     }
60368     function insideBasic(x, y) {
60369         return x >= 0 && x <= 1 && y >= 0 && y <= 1;
60370     }
60371     function viewportDistances(transform, perspective, viewportCoords) {
60372         const boundaryPointsBasic = basicBoundaryPoints(100);
60373         const boundaryPointsViewport = boundaryPointsBasic
60374             .map((basic) => {
60375             return viewportCoords.basicToViewportSafe(basic[0], basic[1], transform, perspective);
60376         });
60377         const visibleBoundaryPoints = [];
60378         const viewportSides = [
60379             { x: -1, y: 1 },
60380             { x: 1, y: 1 },
60381             { x: 1, y: -1 },
60382             { x: -1, y: -1 }
60383         ];
60384         const intersections = [false, false, false, false];
60385         for (let i = 0; i < boundaryPointsViewport.length; i++) {
60386             const p1 = boundaryPointsViewport[i];
60387             const p2 = boundaryPointsViewport[(i + 1) % boundaryPointsViewport.length];
60388             if (p1 === null) {
60389                 continue;
60390             }
60391             if (p2 === null) {
60392                 if (insideViewport(p1[0], p1[1])) {
60393                     visibleBoundaryPoints.push(p1);
60394                 }
60395                 continue;
60396             }
60397             const [x1, y1] = p1;
60398             const [x2, y2] = p2;
60399             if (insideViewport(x1, y1)) {
60400                 if (insideViewport(x2, y2)) {
60401                     visibleBoundaryPoints.push(p1);
60402                 }
60403                 else {
60404                     for (let side = 0; side < 4; side++) {
60405                         const s1 = { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } };
60406                         const s2 = { p1: viewportSides[side], p2: viewportSides[(side + 1) % 4] };
60407                         const intersecting = segmentsIntersect(s1, s2);
60408                         if (intersecting) {
60409                             const intersection = segmentIntersection(s1, s2);
60410                             visibleBoundaryPoints.push(p1, [intersection.x, intersection.y]);
60411                             intersections[side] = true;
60412                         }
60413                     }
60414                 }
60415             }
60416         }
60417         const [topLeftBasicX, topLeftBasicY] = viewportCoords.viewportToBasic(-1, 1, transform, perspective);
60418         const [topRightBasicX, topRightBasicY] = viewportCoords.viewportToBasic(1, 1, transform, perspective);
60419         const [bottomRightBasicX, bottomRightBasicY] = viewportCoords.viewportToBasic(1, -1, transform, perspective);
60420         const [bottomLeftBasicX, bottomLeftBasicY] = viewportCoords.viewportToBasic(-1, -1, transform, perspective);
60421         if (insideBasic(topLeftBasicX, topLeftBasicY)) {
60422             intersections[3] = intersections[0] = true;
60423         }
60424         if (insideBasic(topRightBasicX, topRightBasicY)) {
60425             intersections[0] = intersections[1] = true;
60426         }
60427         if (insideBasic(bottomRightBasicX, bottomRightBasicY)) {
60428             intersections[1] = intersections[2] = true;
60429         }
60430         if (insideBasic(bottomLeftBasicX, bottomLeftBasicY)) {
60431             intersections[2] = intersections[3] = true;
60432         }
60433         const maximums = [-1, -1, 1, 1];
60434         for (let visibleBoundaryPoint of visibleBoundaryPoints) {
60435             const x = visibleBoundaryPoint[0];
60436             const y = visibleBoundaryPoint[1];
60437             if (x > maximums[1]) {
60438                 maximums[1] = x;
60439             }
60440             if (x < maximums[3]) {
60441                 maximums[3] = x;
60442             }
60443             if (y > maximums[0]) {
60444                 maximums[0] = y;
60445             }
60446             if (y < maximums[2]) {
60447                 maximums[2] = y;
60448             }
60449         }
60450         const boundary = [1, 1, -1, -1];
60451         const distances = [];
60452         for (let side = 0; side < 4; side++) {
60453             if (intersections[side]) {
60454                 distances.push(0);
60455                 continue;
60456             }
60457             distances.push(Math.abs(boundary[side] - maximums[side]));
60458         }
60459         return distances;
60460     }
60461
60462     /**
60463      * The `BounceHandler` ensures that the viewer bounces back to the image
60464      * when drag panning outside of the image edge.
60465      */
60466     class BounceHandler extends HandlerBase {
60467         constructor(component, container, navigator, viewportCoords, spatial) {
60468             super(component, container, navigator);
60469             this._spatial = spatial;
60470             this._viewportCoords = viewportCoords;
60471         }
60472         _enable() {
60473             const inTransition$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
60474                 return frame.state.alpha < 1;
60475             }), distinctUntilChanged());
60476             this._bounceSubscription = combineLatest(inTransition$, this._navigator.stateService.inTranslation$, this._container.mouseService.active$, this._container.touchService.active$).pipe(map((noForce) => {
60477                 return noForce[0] || noForce[1] || noForce[2] || noForce[3];
60478             }), distinctUntilChanged(), switchMap((noForce) => {
60479                 return noForce ?
60480                     empty() :
60481                     combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$.pipe(first()));
60482             }), withLatestFrom(this._navigator.panService.panImages$))
60483                 .subscribe(([[render, transform], nts]) => {
60484                 if (!transform.hasValidScale && render.camera.focal < 0.1) {
60485                     return;
60486                 }
60487                 if (render.perspective.aspect === 0 || render.perspective.aspect === Number.POSITIVE_INFINITY) {
60488                     return;
60489                 }
60490                 const distances = viewportDistances(transform, render.perspective, this._viewportCoords);
60491                 const basic = this._viewportCoords.viewportToBasic(0, 0, transform, render.perspective);
60492                 if ((basic[0] < 0 || basic[0] > 1) && nts.length > 0) {
60493                     distances[0] = distances[2] = 0;
60494                 }
60495                 for (const [, t] of nts) {
60496                     const d = viewportDistances(t, render.perspective, this._viewportCoords);
60497                     for (let i = 1; i < distances.length; i += 2) {
60498                         if (d[i] < distances[i]) {
60499                             distances[i] = d[i];
60500                         }
60501                     }
60502                 }
60503                 if (Math.max(...distances) < 0.01) {
60504                     return;
60505                 }
60506                 const horizontalDistance = distances[1] - distances[3];
60507                 const verticalDistance = distances[0] - distances[2];
60508                 const currentDirection = this._viewportCoords
60509                     .unprojectFromViewport(0, 0, render.perspective)
60510                     .sub(render.perspective.position);
60511                 const directionPhi = this._viewportCoords
60512                     .unprojectFromViewport(horizontalDistance, 0, render.perspective)
60513                     .sub(render.perspective.position);
60514                 const directionTheta = this._viewportCoords
60515                     .unprojectFromViewport(0, verticalDistance, render.perspective)
60516                     .sub(render.perspective.position);
60517                 let phi = (horizontalDistance > 0 ? 1 : -1) * directionPhi.angleTo(currentDirection);
60518                 let theta = (verticalDistance > 0 ? 1 : -1) * directionTheta.angleTo(currentDirection);
60519                 const threshold = Math.PI / 60;
60520                 const coeff = 1e-1;
60521                 phi = this._spatial.clamp(coeff * phi, -threshold, threshold);
60522                 theta = this._spatial.clamp(coeff * theta, -threshold, threshold);
60523                 this._navigator.stateService.rotateUnbounded({ phi: phi, theta: theta });
60524             });
60525         }
60526         _disable() {
60527             this._bounceSubscription.unsubscribe();
60528         }
60529         _getConfiguration() {
60530             return {};
60531         }
60532     }
60533
60534     class MouseOperator {
60535         static filteredPairwiseMouseDrag$(name, mouseService) {
60536             return this._filteredPairwiseMouseDrag$(name, mouseService, mouseService.mouseDragStart$, mouseService.mouseDrag$, mouseService.mouseDragEnd$);
60537         }
60538         static filteredPairwiseMouseRightDrag$(name, mouseService) {
60539             return this._filteredPairwiseMouseDrag$(name, mouseService, mouseService.mouseRightDragStart$, mouseService.mouseRightDrag$, mouseService.mouseRightDragEnd$);
60540         }
60541         static _filteredPairwiseMouseDrag$(name, mouseService, mouseDragStart$, mouseDrag$, mouseDragEnd$) {
60542             return mouseService
60543                 .filtered$(name, mouseDragStart$).pipe(switchMap((mouseDragStart) => {
60544                 const dragging$ = concat(of(mouseDragStart), mouseService
60545                     .filtered$(name, mouseDrag$));
60546                 const dragEnd$ = mouseService
60547                     .filtered$(name, mouseDragEnd$).pipe(map(() => {
60548                     return null;
60549                 }));
60550                 return merge(dragging$, dragEnd$).pipe(takeWhile((e) => {
60551                     return !!e;
60552                 }), startWith(null));
60553             }), pairwise(), filter((pair) => {
60554                 return pair[0] != null && pair[1] != null;
60555             }));
60556         }
60557     }
60558
60559     /**
60560      * The `DragPanHandler` allows the user to pan the viewer image by clicking and dragging the cursor.
60561      *
60562      * @example
60563      * ```js
60564      * var pointerComponent = viewer.getComponent("pointer");
60565      *
60566      * pointerComponent.dragPan.disable();
60567      * pointerComponent.dragPan.enable();
60568      *
60569      * var isEnabled = pointerComponent.dragPan.isEnabled;
60570      * ```
60571      */
60572     class DragPanHandler extends HandlerBase {
60573         /** @ignore */
60574         constructor(component, container, navigator, viewportCoords, spatial) {
60575             super(component, container, navigator);
60576             this._spatial = spatial;
60577             this._viewportCoords = viewportCoords;
60578         }
60579         _enable() {
60580             let draggingStarted$ = this._container.mouseService
60581                 .filtered$(this._component.name, this._container.mouseService.mouseDragStart$).pipe(map(() => {
60582                 return true;
60583             }), share());
60584             let draggingStopped$ = this._container.mouseService
60585                 .filtered$(this._component.name, this._container.mouseService.mouseDragEnd$).pipe(map(() => {
60586                 return false;
60587             }), share());
60588             this._activeMouseSubscription = merge(draggingStarted$, draggingStopped$)
60589                 .subscribe(this._container.mouseService.activate$);
60590             const documentMouseMove$ = merge(draggingStarted$, draggingStopped$).pipe(switchMap((dragging) => {
60591                 return dragging ?
60592                     this._container.mouseService.documentMouseMove$ :
60593                     empty();
60594             }));
60595             this._preventDefaultSubscription = merge(documentMouseMove$, this._container.touchService.touchMove$)
60596                 .subscribe((event) => {
60597                 event.preventDefault(); // prevent selection of content outside the viewer
60598             });
60599             let touchMovingStarted$ = this._container.touchService.singleTouchDragStart$.pipe(map(() => {
60600                 return true;
60601             }));
60602             let touchMovingStopped$ = this._container.touchService.singleTouchDragEnd$.pipe(map(() => {
60603                 return false;
60604             }));
60605             this._activeTouchSubscription = merge(touchMovingStarted$, touchMovingStopped$)
60606                 .subscribe(this._container.touchService.activate$);
60607             const rotation$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
60608                 return isSpherical(frame.state.currentImage.cameraType) ||
60609                     frame.state.imagesAhead < 1;
60610             }), distinctUntilChanged(), switchMap((enable) => {
60611                 if (!enable) {
60612                     return empty();
60613                 }
60614                 const mouseDrag$ = MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService);
60615                 const singleTouchDrag$ = merge(this._container.touchService.singleTouchDragStart$, this._container.touchService.singleTouchDrag$, this._container.touchService.singleTouchDragEnd$.pipe(map(() => { return null; }))).pipe(map((event) => {
60616                     return event != null && event.touches.length > 0 ?
60617                         event.touches[0] : null;
60618                 }), pairwise(), filter((pair) => {
60619                     return pair[0] != null && pair[1] != null;
60620                 }));
60621                 return merge(mouseDrag$, singleTouchDrag$);
60622             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$, this._navigator.panService.panImages$), map(([events, render, transform, nts]) => {
60623                 let previousEvent = events[0];
60624                 let event = events[1];
60625                 let movementX = event.clientX - previousEvent.clientX;
60626                 let movementY = event.clientY - previousEvent.clientY;
60627                 let element = this._container.container;
60628                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
60629                 let currentDirection = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective)
60630                     .sub(render.perspective.position);
60631                 let directionX = this._viewportCoords.unprojectFromCanvas(canvasX - movementX, canvasY, element, render.perspective)
60632                     .sub(render.perspective.position);
60633                 let directionY = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY - movementY, element, render.perspective)
60634                     .sub(render.perspective.position);
60635                 let phi = (movementX > 0 ? 1 : -1) * directionX.angleTo(currentDirection);
60636                 let theta = (movementY > 0 ? -1 : 1) * directionY.angleTo(currentDirection);
60637                 const distances = viewportDistances(transform, render.perspective, this._viewportCoords);
60638                 for (const [, t] of nts) {
60639                     const d = viewportDistances(t, render.perspective, this._viewportCoords);
60640                     for (let i = 0; i < distances.length; i++) {
60641                         if (d[i] < distances[i]) {
60642                             distances[i] = d[i];
60643                         }
60644                     }
60645                 }
60646                 if (distances[0] > 0 && theta < 0) {
60647                     theta /= Math.max(1, 2e2 * distances[0]);
60648                 }
60649                 if (distances[2] > 0 && theta > 0) {
60650                     theta /= Math.max(1, 2e2 * distances[2]);
60651                 }
60652                 if (distances[1] > 0 && phi < 0) {
60653                     phi /= Math.max(1, 2e2 * distances[1]);
60654                 }
60655                 if (distances[3] > 0 && phi > 0) {
60656                     phi /= Math.max(1, 2e2 * distances[3]);
60657                 }
60658                 return { phi: phi, theta: theta };
60659             }), share());
60660             this._rotateWithoutInertiaSubscription = rotation$
60661                 .subscribe((rotation) => {
60662                 this._navigator.stateService.rotateWithoutInertia(rotation);
60663             });
60664             this._rotateSubscription = rotation$.pipe(scan((rotationBuffer, rotation) => {
60665                 this._drainBuffer(rotationBuffer);
60666                 rotationBuffer.push([Date.now(), rotation]);
60667                 return rotationBuffer;
60668             }, []), sample(merge(this._container.mouseService.filtered$(this._component.name, this._container.mouseService.mouseDragEnd$), this._container.touchService.singleTouchDragEnd$)), map((rotationBuffer) => {
60669                 const drainedBuffer = this._drainBuffer(rotationBuffer.slice());
60670                 const rotation = { phi: 0, theta: 0 };
60671                 for (const bufferedRotation of drainedBuffer) {
60672                     rotation.phi += bufferedRotation[1].phi;
60673                     rotation.theta += bufferedRotation[1].theta;
60674                 }
60675                 const count = drainedBuffer.length;
60676                 if (count > 0) {
60677                     rotation.phi /= count;
60678                     rotation.theta /= count;
60679                 }
60680                 const threshold = Math.PI / 18;
60681                 rotation.phi = this._spatial.clamp(rotation.phi, -threshold, threshold);
60682                 rotation.theta = this._spatial.clamp(rotation.theta, -threshold, threshold);
60683                 return rotation;
60684             }))
60685                 .subscribe((rotation) => {
60686                 this._navigator.stateService.rotate(rotation);
60687             });
60688         }
60689         _disable() {
60690             this._activeMouseSubscription.unsubscribe();
60691             this._activeTouchSubscription.unsubscribe();
60692             this._preventDefaultSubscription.unsubscribe();
60693             this._rotateSubscription.unsubscribe();
60694             this._rotateWithoutInertiaSubscription.unsubscribe();
60695             this._activeMouseSubscription = null;
60696             this._activeTouchSubscription = null;
60697             this._preventDefaultSubscription = null;
60698             this._rotateSubscription = null;
60699         }
60700         _getConfiguration(enable) {
60701             return { dragPan: enable };
60702         }
60703         _drainBuffer(buffer) {
60704             const cutoff = 50;
60705             const now = Date.now();
60706             while (buffer.length > 0 && now - buffer[0][0] > cutoff) {
60707                 buffer.shift();
60708             }
60709             return buffer;
60710         }
60711     }
60712
60713     class EarthControlHandler extends HandlerBase {
60714         /** @ignore */
60715         constructor(component, container, navigator, viewportCoords, spatial) {
60716             super(component, container, navigator);
60717             this._spatial = spatial;
60718             this._viewportCoords = viewportCoords;
60719             this._subscriptions = new SubscriptionHolder();
60720         }
60721         _enable() {
60722             const earth$ = this._navigator.stateService.state$.pipe(map((state) => {
60723                 return state === State.Earth;
60724             }), publishReplay(1), refCount());
60725             const subs = this._subscriptions;
60726             subs.push(earth$.pipe(switchMap((earth) => {
60727                 return earth ?
60728                     this._container.mouseService.mouseWheel$ :
60729                     empty();
60730             }))
60731                 .subscribe((event) => {
60732                 event.preventDefault();
60733             }));
60734             subs.push(earth$.pipe(switchMap((earth) => {
60735                 if (!earth) {
60736                     return empty();
60737                 }
60738                 return MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
60739                     return !(e1.ctrlKey && e2.ctrlKey);
60740                 }));
60741             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$), map(([[previous, current], render, transform]) => {
60742                 const planeNormal = [0, 0, 1];
60743                 const planePoint = [0, 0, -2];
60744                 const currentIntersection = this._planeIntersection(current, planeNormal, planePoint, render.perspective, this._container.container);
60745                 const previousIntersection = this._planeIntersection(previous, planeNormal, planePoint, render.perspective, this._container.container);
60746                 if (!currentIntersection || !previousIntersection) {
60747                     return null;
60748                 }
60749                 const direction = new Vector3()
60750                     .subVectors(currentIntersection, previousIntersection)
60751                     .multiplyScalar(-1)
60752                     .toArray();
60753                 return direction;
60754             }), filter((direction) => {
60755                 return !!direction;
60756             }))
60757                 .subscribe((direction) => {
60758                 this._navigator.stateService.truck(direction);
60759             }));
60760             subs.push(earth$.pipe(switchMap((earth) => {
60761                 if (!earth) {
60762                     return empty();
60763                 }
60764                 return MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
60765                     return e1.ctrlKey && e2.ctrlKey;
60766                 }));
60767             }), map(([previous, current]) => {
60768                 return this._mousePairToRotation(previous, current);
60769             }))
60770                 .subscribe((rotation) => {
60771                 this._navigator.stateService.orbit(rotation);
60772             }));
60773             subs.push(earth$.pipe(switchMap((earth) => {
60774                 if (!earth) {
60775                     return empty();
60776                 }
60777                 return MouseOperator.filteredPairwiseMouseRightDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
60778                     return !e1.ctrlKey && !e2.ctrlKey;
60779                 }));
60780             }), map(([previous, current]) => {
60781                 return this._mousePairToRotation(previous, current);
60782             }))
60783                 .subscribe((rotation) => {
60784                 this._navigator.stateService.orbit(rotation);
60785             }));
60786             subs.push(earth$.pipe(switchMap((earth) => {
60787                 if (!earth) {
60788                     return empty();
60789                 }
60790                 return this._container.mouseService
60791                     .filteredWheel$(this._component.name, this._container.mouseService.mouseWheel$);
60792             }), map((event) => {
60793                 let delta = event.deltaY;
60794                 if (event.deltaMode === 1) {
60795                     delta = 40 * delta;
60796                 }
60797                 else if (event.deltaMode === 2) {
60798                     delta = 800 * delta;
60799                 }
60800                 const canvasSize = this._viewportCoords.containerToCanvas(this._container.container);
60801                 return -delta / canvasSize[1];
60802             }))
60803                 .subscribe((delta) => {
60804                 this._navigator.stateService.dolly(delta);
60805             }));
60806         }
60807         _disable() {
60808             this._subscriptions.unsubscribe();
60809         }
60810         _getConfiguration() {
60811             return {};
60812         }
60813         _eventToViewport(event, element) {
60814             const previousCanvas = this._viewportCoords.canvasPosition(event, element);
60815             return this._viewportCoords.canvasToViewport(previousCanvas[0], previousCanvas[1], element);
60816         }
60817         _mousePairToRotation(previous, current) {
60818             const [currentX, currentY] = this._eventToViewport(current, this._container.container);
60819             const [previousX, previousY] = this._eventToViewport(previous, this._container.container);
60820             const phi = (previousX - currentX) * Math.PI;
60821             const theta = (currentY - previousY) * Math.PI / 2;
60822             return { phi: phi, theta: theta };
60823         }
60824         _planeIntersection(event, planeNormal, planePoint, camera, element) {
60825             const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
60826             const direction = this._viewportCoords
60827                 .unprojectFromCanvas(canvasX, canvasY, element, camera)
60828                 .sub(camera.position)
60829                 .normalize();
60830             if (Math.abs(this._spatial.angleToPlane(direction.toArray(), planeNormal)) < Math.PI / 90) {
60831                 return null;
60832             }
60833             const l0 = camera.position.clone();
60834             const n = new Vector3().fromArray(planeNormal);
60835             const p0 = new Vector3().fromArray(planePoint);
60836             const d = new Vector3().subVectors(p0, l0).dot(n) / direction.clone().dot(n);
60837             const intersection = new Vector3().addVectors(l0, direction.multiplyScalar(d));
60838             if (this._viewportCoords.worldToCamera(intersection.toArray(), camera)[2] > 0) {
60839                 return null;
60840             }
60841             return intersection;
60842         }
60843     }
60844
60845     /**
60846      * The `ScrollZoomHandler` allows the user to zoom the viewer image by scrolling.
60847      *
60848      * @example
60849      * ```js
60850      * var pointerComponent = viewer.getComponent("pointer");
60851      *
60852      * pointerComponent.scrollZoom.disable();
60853      * pointerComponent.scrollZoom.enable();
60854      *
60855      * var isEnabled = pointerComponent.scrollZoom.isEnabled;
60856      * ```
60857      */
60858     class ScrollZoomHandler extends HandlerBase {
60859         /** @ignore */
60860         constructor(component, container, navigator, viewportCoords) {
60861             super(component, container, navigator);
60862             this._viewportCoords = viewportCoords;
60863         }
60864         _enable() {
60865             this._container.mouseService.claimWheel(this._component.name, 0);
60866             this._preventDefaultSubscription = this._container.mouseService.mouseWheel$
60867                 .subscribe((event) => {
60868                 event.preventDefault();
60869             });
60870             this._zoomSubscription = this._container.mouseService
60871                 .filteredWheel$(this._component.name, this._container.mouseService.mouseWheel$).pipe(withLatestFrom(this._navigator.stateService.currentState$, (w, f) => {
60872                 return [w, f];
60873             }), filter((args) => {
60874                 let state = args[1].state;
60875                 return isSpherical(state.currentImage.cameraType) ||
60876                     state.imagesAhead < 1;
60877             }), map((args) => {
60878                 return args[0];
60879             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$, (w, r, t) => {
60880                 return [w, r, t];
60881             }))
60882                 .subscribe((args) => {
60883                 let event = args[0];
60884                 let render = args[1];
60885                 let transform = args[2];
60886                 let element = this._container.container;
60887                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
60888                 let unprojected = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective);
60889                 let reference = transform.projectBasic(unprojected.toArray());
60890                 let deltaY = event.deltaY;
60891                 if (event.deltaMode === 1) {
60892                     deltaY = 40 * deltaY;
60893                 }
60894                 else if (event.deltaMode === 2) {
60895                     deltaY = 800 * deltaY;
60896                 }
60897                 const canvasSize = this._viewportCoords.containerToCanvas(element);
60898                 let zoom = -3 * deltaY / canvasSize[1];
60899                 this._navigator.stateService.zoomIn(zoom, reference);
60900             });
60901         }
60902         _disable() {
60903             this._container.mouseService.unclaimWheel(this._component.name);
60904             this._preventDefaultSubscription.unsubscribe();
60905             this._zoomSubscription.unsubscribe();
60906             this._preventDefaultSubscription = null;
60907             this._zoomSubscription = null;
60908         }
60909         _getConfiguration(enable) {
60910             return { scrollZoom: enable };
60911         }
60912     }
60913
60914     /**
60915      * The `TouchZoomHandler` allows the user to zoom the viewer image by pinching on a touchscreen.
60916      *
60917      * @example
60918      * ```js
60919      * var pointerComponent = viewer.getComponent("pointer");
60920      *
60921      * pointerComponent.touchZoom.disable();
60922      * pointerComponent.touchZoom.enable();
60923      *
60924      * var isEnabled = pointerComponent.touchZoom.isEnabled;
60925      * ```
60926      */
60927     class TouchZoomHandler extends HandlerBase {
60928         /** @ignore */
60929         constructor(component, container, navigator, viewportCoords) {
60930             super(component, container, navigator);
60931             this._viewportCoords = viewportCoords;
60932         }
60933         _enable() {
60934             this._preventDefaultSubscription = this._container.touchService.pinch$
60935                 .subscribe((pinch) => {
60936                 pinch.originalEvent.preventDefault();
60937             });
60938             let pinchStarted$ = this._container.touchService.pinchStart$.pipe(map((event) => {
60939                 return true;
60940             }));
60941             let pinchStopped$ = this._container.touchService.pinchEnd$.pipe(map((event) => {
60942                 return false;
60943             }));
60944             this._activeSubscription = merge(pinchStarted$, pinchStopped$)
60945                 .subscribe(this._container.touchService.activate$);
60946             this._zoomSubscription = this._container.touchService.pinch$.pipe(withLatestFrom(this._navigator.stateService.currentState$), filter((args) => {
60947                 let state = args[1].state;
60948                 return isSpherical(state.currentImage.cameraType) ||
60949                     state.imagesAhead < 1;
60950             }), map((args) => {
60951                 return args[0];
60952             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
60953                 .subscribe(([pinch, render, transform]) => {
60954                 let element = this._container.container;
60955                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(pinch, element);
60956                 let unprojected = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective);
60957                 let reference = transform.projectBasic(unprojected.toArray());
60958                 const [canvasWidth, canvasHeight] = this._viewportCoords.containerToCanvas(element);
60959                 let zoom = 3 * pinch.distanceChange / Math.min(canvasWidth, canvasHeight);
60960                 this._navigator.stateService.zoomIn(zoom, reference);
60961             });
60962         }
60963         _disable() {
60964             this._activeSubscription.unsubscribe();
60965             this._preventDefaultSubscription.unsubscribe();
60966             this._zoomSubscription.unsubscribe();
60967             this._preventDefaultSubscription = null;
60968             this._zoomSubscription = null;
60969         }
60970         _getConfiguration(enable) {
60971             return { touchZoom: enable };
60972         }
60973     }
60974
60975     /**
60976      * @class PointerComponent
60977      *
60978      * @classdesc Component handling mouse, pen, and touch events for camera movement.
60979      *
60980      * To retrive and use the mouse component
60981      *
60982      * @example
60983      * ```js
60984      * var viewer = new Viewer({ ... });
60985      *
60986      * var pointerComponent = viewer.getComponent("pointer");
60987      * ```
60988      */
60989     class PointerComponent extends Component {
60990         /** @ignore */
60991         constructor(name, container, navigator) {
60992             super(name, container, navigator);
60993             const spatial = new Spatial();
60994             const viewportCoords = new ViewportCoords();
60995             this._bounceHandler =
60996                 new BounceHandler(this, container, navigator, viewportCoords, spatial);
60997             this._dragPanHandler =
60998                 new DragPanHandler(this, container, navigator, viewportCoords, spatial);
60999             this._earthControlHandler =
61000                 new EarthControlHandler(this, container, navigator, viewportCoords, spatial);
61001             this._scrollZoomHandler =
61002                 new ScrollZoomHandler(this, container, navigator, viewportCoords);
61003             this._touchZoomHandler =
61004                 new TouchZoomHandler(this, container, navigator, viewportCoords);
61005         }
61006         /**
61007          * Get drag pan.
61008          *
61009          * @returns {DragPanHandler} The drag pan handler.
61010          */
61011         get dragPan() {
61012             return this._dragPanHandler;
61013         }
61014         /**
61015          * Get earth control.
61016          *
61017          * @returns {EarthControlHandler} The earth control handler.
61018          */
61019         get earthControl() {
61020             return this._earthControlHandler;
61021         }
61022         /**
61023          * Get scroll zoom.
61024          *
61025          * @returns {ScrollZoomHandler} The scroll zoom handler.
61026          */
61027         get scrollZoom() {
61028             return this._scrollZoomHandler;
61029         }
61030         /**
61031          * Get touch zoom.
61032          *
61033          * @returns {TouchZoomHandler} The touch zoom handler.
61034          */
61035         get touchZoom() {
61036             return this._touchZoomHandler;
61037         }
61038         _activate() {
61039             this._bounceHandler.enable();
61040             this._subscriptions.push(this._configuration$
61041                 .subscribe((configuration) => {
61042                 if (configuration.dragPan) {
61043                     this._dragPanHandler.enable();
61044                 }
61045                 else {
61046                     this._dragPanHandler.disable();
61047                 }
61048                 if (configuration.earthControl) {
61049                     this._earthControlHandler.enable();
61050                 }
61051                 else {
61052                     this._earthControlHandler.disable();
61053                 }
61054                 if (configuration.scrollZoom) {
61055                     this._scrollZoomHandler.enable();
61056                 }
61057                 else {
61058                     this._scrollZoomHandler.disable();
61059                 }
61060                 if (configuration.touchZoom) {
61061                     this._touchZoomHandler.enable();
61062                 }
61063                 else {
61064                     this._touchZoomHandler.disable();
61065                 }
61066             }));
61067             this._container.mouseService.claimMouse(this._name, 0);
61068         }
61069         _deactivate() {
61070             this._container.mouseService.unclaimMouse(this._name);
61071             this._subscriptions.unsubscribe();
61072             this._bounceHandler.disable();
61073             this._dragPanHandler.disable();
61074             this._earthControlHandler.disable();
61075             this._scrollZoomHandler.disable();
61076             this._touchZoomHandler.disable();
61077         }
61078         _getDefaultConfiguration() {
61079             return {
61080                 dragPan: true,
61081                 earthControl: true,
61082                 scrollZoom: true,
61083                 touchZoom: true,
61084             };
61085         }
61086     }
61087     /** @inheritdoc */
61088     PointerComponent.componentName = "pointer";
61089
61090     class DOM {
61091         constructor(doc) {
61092             this._document = !!doc ? doc : document;
61093         }
61094         get document() {
61095             return this._document;
61096         }
61097         createElement(tagName, className, container) {
61098             const element = this._document.createElement(tagName);
61099             if (!!className) {
61100                 element.className = className;
61101             }
61102             if (!!container) {
61103                 container.appendChild(element);
61104             }
61105             return element;
61106         }
61107     }
61108
61109     /**
61110      * @class PopupComponent
61111      *
61112      * @classdesc Component for showing HTML popup objects.
61113      *
61114      * The `add` method is used for adding new popups. Popups are removed by reference.
61115      *
61116      * It is not possible to update popups in the set by updating any properties
61117      * directly on the popup object. Popups need to be replaced by
61118      * removing them and creating new ones with relevant changed properties and
61119      * adding those instead.
61120      *
61121      * Popups are only relevant to a single image because they are based on
61122      * 2D basic image coordinates. Popups related to a certain image should
61123      * be removed when the viewer is moved to another image.
61124      *
61125      * To retrive and use the popup component
61126      *
61127      * @example
61128      * ```js
61129      * var viewer = new Viewer({ component: { popup: true }, ... });
61130      *
61131      * var popupComponent = viewer.getComponent("popup");
61132      * ```
61133      */
61134     class PopupComponent extends Component {
61135         /** @ignore */
61136         constructor(name, container, navigator, dom) {
61137             super(name, container, navigator);
61138             this._dom = !!dom ? dom : new DOM();
61139             this._popups = [];
61140             this._added$ = new Subject();
61141             this._popups$ = new Subject();
61142         }
61143         /**
61144          * Add popups to the popups set.
61145          *
61146          * @description Adding a new popup never replaces an old one
61147          * because they are stored by reference. Adding an already
61148          * existing popup has no effect.
61149          *
61150          * @param {Array<Popup>} popups - Popups to add.
61151          *
61152          * @example
61153          * ```js
61154          * popupComponent.add([popup1, popup2]);
61155          * ```
61156          */
61157         add(popups) {
61158             for (const popup of popups) {
61159                 if (this._popups.indexOf(popup) !== -1) {
61160                     continue;
61161                 }
61162                 this._popups.push(popup);
61163                 if (this._activated) {
61164                     popup.setParentContainer(this._popupContainer);
61165                 }
61166             }
61167             this._added$.next(popups);
61168             this._popups$.next(this._popups);
61169         }
61170         /**
61171          * Returns an array of all popups.
61172          *
61173          * @example
61174          * ```js
61175          * var popups = popupComponent.getAll();
61176          * ```
61177          */
61178         getAll() {
61179             return this._popups.slice();
61180         }
61181         /**
61182          * Remove popups based on reference from the popup set.
61183          *
61184          * @param {Array<Popup>} popups - Popups to remove.
61185          *
61186          * @example
61187          * ```js
61188          * popupComponent.remove([popup1, popup2]);
61189          * ```
61190          */
61191         remove(popups) {
61192             for (const popup of popups) {
61193                 this._remove(popup);
61194             }
61195             this._popups$.next(this._popups);
61196         }
61197         /**
61198          * Remove all popups from the popup set.
61199          *
61200          * @example
61201          * ```js
61202          * popupComponent.removeAll();
61203          * ```
61204          */
61205         removeAll() {
61206             for (const popup of this._popups.slice()) {
61207                 this._remove(popup);
61208             }
61209             this._popups$.next(this._popups);
61210         }
61211         _activate() {
61212             this._popupContainer = this._dom.createElement("div", "mapillary-popup-container", this._container.container);
61213             for (const popup of this._popups) {
61214                 popup.setParentContainer(this._popupContainer);
61215             }
61216             const subs = this._subscriptions;
61217             subs.push(combineLatest(this._container.renderService.renderCamera$, this._container.renderService.size$, this._navigator.stateService.currentTransform$)
61218                 .subscribe(([renderCamera, size, transform]) => {
61219                 for (const popup of this._popups) {
61220                     popup.update(renderCamera, size, transform);
61221                 }
61222             }));
61223             const changed$ = this._popups$.pipe(startWith(this._popups), switchMap((popups) => {
61224                 return from(popups).pipe(mergeMap((popup) => {
61225                     return popup.changed$;
61226                 }));
61227             }), map((popup) => {
61228                 return [popup];
61229             }));
61230             subs.push(merge(this._added$, changed$).pipe(withLatestFrom(this._container.renderService.renderCamera$, this._container.renderService.size$, this._navigator.stateService.currentTransform$))
61231                 .subscribe(([popups, renderCamera, size, transform]) => {
61232                 for (const popup of popups) {
61233                     popup.update(renderCamera, size, transform);
61234                 }
61235             }));
61236         }
61237         _deactivate() {
61238             this._subscriptions.unsubscribe();
61239             for (const popup of this._popups) {
61240                 popup.remove();
61241             }
61242             this._container.container.removeChild(this._popupContainer);
61243             delete this._popupContainer;
61244         }
61245         _getDefaultConfiguration() {
61246             return {};
61247         }
61248         _remove(popup) {
61249             const index = this._popups.indexOf(popup);
61250             if (index === -1) {
61251                 return;
61252             }
61253             const removed = this._popups.splice(index, 1)[0];
61254             if (this._activated) {
61255                 removed.remove();
61256             }
61257         }
61258     }
61259     PopupComponent.componentName = "popup";
61260
61261     /**
61262      * Enumeration for graph modes.
61263      * @enum {number}
61264      * @readonly
61265      * @description Modes for the retrieval and caching performed
61266      * by the graph service on the graph.
61267      */
61268     var GraphMode;
61269     (function (GraphMode) {
61270         /**
61271          * Caching is performed on sequences only and sequence edges are
61272          * calculated. Spatial tiles
61273          * are not retrieved and spatial edges are not calculated when
61274          * caching nodes. Complete sequences are being cached for requested
61275          * nodes within the graph.
61276          */
61277         GraphMode[GraphMode["Sequence"] = 0] = "Sequence";
61278         /**
61279          * Caching is performed with emphasis on spatial data. Sequence edges
61280          * as well as spatial edges are cached. Sequence data
61281          * is still requested but complete sequences are not being cached
61282          * for requested nodes.
61283          *
61284          * This is the initial mode of the graph service.
61285          */
61286         GraphMode[GraphMode["Spatial"] = 1] = "Spatial";
61287     })(GraphMode || (GraphMode = {}));
61288
61289     var SequenceMode;
61290     (function (SequenceMode) {
61291         SequenceMode[SequenceMode["Default"] = 0] = "Default";
61292         SequenceMode[SequenceMode["Playback"] = 1] = "Playback";
61293         SequenceMode[SequenceMode["Timeline"] = 2] = "Timeline";
61294     })(SequenceMode || (SequenceMode = {}));
61295
61296     class SequenceDOMRenderer {
61297         constructor(container) {
61298             this._container = container;
61299             this._minThresholdWidth = 320;
61300             this._maxThresholdWidth = 1480;
61301             this._minThresholdHeight = 240;
61302             this._maxThresholdHeight = 820;
61303             this._stepperDefaultWidth = 108;
61304             this._controlsDefaultWidth = 88;
61305             this._defaultHeight = 30;
61306             this._expandControls = false;
61307             this._mode = SequenceMode.Default;
61308             this._speed = 0.5;
61309             this._changingSpeed = false;
61310             this._index = null;
61311             this._changingPosition = false;
61312             this._mouseEnterDirection$ = new Subject();
61313             this._mouseLeaveDirection$ = new Subject();
61314             this._notifyChanged$ = new Subject();
61315             this._notifyChangingPositionChanged$ = new Subject();
61316             this._notifySpeedChanged$ = new Subject();
61317             this._notifyIndexChanged$ = new Subject();
61318         }
61319         get changed$() {
61320             return this._notifyChanged$;
61321         }
61322         get changingPositionChanged$() {
61323             return this._notifyChangingPositionChanged$;
61324         }
61325         get speed$() {
61326             return this._notifySpeedChanged$;
61327         }
61328         get index$() {
61329             return this._notifyIndexChanged$;
61330         }
61331         get mouseEnterDirection$() {
61332             return this._mouseEnterDirection$;
61333         }
61334         get mouseLeaveDirection$() {
61335             return this._mouseLeaveDirection$;
61336         }
61337         activate() {
61338             if (!!this._changingSubscription) {
61339                 return;
61340             }
61341             this._changingSubscription = merge(this._container.mouseService.documentMouseUp$, this._container.touchService.touchEnd$.pipe(filter((touchEvent) => {
61342                 return touchEvent.touches.length === 0;
61343             })))
61344                 .subscribe(() => {
61345                 if (this._changingSpeed) {
61346                     this._changingSpeed = false;
61347                 }
61348                 if (this._changingPosition) {
61349                     this._setChangingPosition(false);
61350                 }
61351             });
61352         }
61353         deactivate() {
61354             if (!this._changingSubscription) {
61355                 return;
61356             }
61357             this._changingSpeed = false;
61358             this._changingPosition = false;
61359             this._expandControls = false;
61360             this._mode = SequenceMode.Default;
61361             this._changingSubscription.unsubscribe();
61362             this._changingSubscription = null;
61363         }
61364         render(edgeStatus, configuration, containerWidth, speed, index, max, playEnabled, component, navigator) {
61365             if (configuration.visible === false) {
61366                 return virtualDom.h("div.mapillary-sequence-container", {}, []);
61367             }
61368             const stepper = this._createStepper(edgeStatus, configuration, playEnabled, containerWidth, component, navigator);
61369             const controls = this._createSequenceControls(containerWidth);
61370             const playback = this._createPlaybackControls(containerWidth, speed, component, configuration);
61371             const timeline = this._createTimelineControls(containerWidth, index, max);
61372             return virtualDom.h("div.mapillary-sequence-container", [stepper, controls, playback, timeline]);
61373         }
61374         getContainerWidth(size, configuration) {
61375             let minWidth = configuration.minWidth;
61376             let maxWidth = configuration.maxWidth;
61377             if (maxWidth < minWidth) {
61378                 maxWidth = minWidth;
61379             }
61380             let relativeWidth = (size.width - this._minThresholdWidth) / (this._maxThresholdWidth - this._minThresholdWidth);
61381             let relativeHeight = (size.height - this._minThresholdHeight) / (this._maxThresholdHeight - this._minThresholdHeight);
61382             let coeff = Math.max(0, Math.min(1, Math.min(relativeWidth, relativeHeight)));
61383             return minWidth + coeff * (maxWidth - minWidth);
61384         }
61385         _createPositionInput(index, max) {
61386             this._index = index;
61387             const onPosition = (e) => {
61388                 this._index = Number(e.target.value);
61389                 this._notifyIndexChanged$.next(this._index);
61390             };
61391             const boundingRect = this._container.domContainer.getBoundingClientRect();
61392             const width = Math.max(276, Math.min(410, 5 + 0.8 * boundingRect.width)) - 65;
61393             const onStart = (e) => {
61394                 e.stopPropagation();
61395                 this._setChangingPosition(true);
61396             };
61397             const onMove = (e) => {
61398                 if (this._changingPosition === true) {
61399                     e.stopPropagation();
61400                 }
61401             };
61402             const onKeyDown = (e) => {
61403                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
61404                     e.key === "ArrowRight" || e.key === "ArrowUp") {
61405                     e.preventDefault();
61406                 }
61407             };
61408             const positionInputProperties = {
61409                 max: max != null ? max : 1,
61410                 min: 0,
61411                 onchange: onPosition,
61412                 oninput: onPosition,
61413                 onkeydown: onKeyDown,
61414                 onpointerdown: onStart,
61415                 onpointermove: onMove,
61416                 ontouchmove: onMove,
61417                 ontouchstart: onStart,
61418                 style: {
61419                     width: `${width}px`,
61420                 },
61421                 type: "range",
61422                 value: index != null ? index : 0,
61423             };
61424             const disabled = index == null || max == null || max <= 1;
61425             if (disabled) {
61426                 positionInputProperties.disabled = "true";
61427             }
61428             const positionInput = virtualDom.h("input.mapillary-sequence-position", positionInputProperties, []);
61429             const positionContainerClass = disabled ? ".mapillary-sequence-position-container-inactive" : ".mapillary-sequence-position-container";
61430             return virtualDom.h("div" + positionContainerClass, [positionInput]);
61431         }
61432         _createSpeedInput(speed) {
61433             this._speed = speed;
61434             const onSpeed = (e) => {
61435                 this._speed = Number(e.target.value) / 1000;
61436                 this._notifySpeedChanged$.next(this._speed);
61437             };
61438             const boundingRect = this._container.domContainer.getBoundingClientRect();
61439             const width = Math.max(276, Math.min(410, 5 + 0.8 * boundingRect.width)) - 160;
61440             const onStart = (e) => {
61441                 this._changingSpeed = true;
61442                 e.stopPropagation();
61443             };
61444             const onMove = (e) => {
61445                 if (this._changingSpeed === true) {
61446                     e.stopPropagation();
61447                 }
61448             };
61449             const onKeyDown = (e) => {
61450                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
61451                     e.key === "ArrowRight" || e.key === "ArrowUp") {
61452                     e.preventDefault();
61453                 }
61454             };
61455             const speedInput = virtualDom.h("input.mapillary-sequence-speed", {
61456                 max: 1000,
61457                 min: 0,
61458                 onchange: onSpeed,
61459                 oninput: onSpeed,
61460                 onkeydown: onKeyDown,
61461                 onpointerdown: onStart,
61462                 onpointermove: onMove,
61463                 ontouchmove: onMove,
61464                 ontouchstart: onStart,
61465                 style: {
61466                     width: `${width}px`,
61467                 },
61468                 type: "range",
61469                 value: 1000 * speed,
61470             }, []);
61471             return virtualDom.h("div.mapillary-sequence-speed-container", [speedInput]);
61472         }
61473         _createPlaybackControls(containerWidth, speed, component, configuration) {
61474             if (this._mode !== SequenceMode.Playback) {
61475                 return virtualDom.h("div.mapillary-sequence-playback", []);
61476             }
61477             const switchIcon = virtualDom.h("div.mapillary-sequence-switch-icon.mapillary-sequence-icon-visible", []);
61478             const direction = configuration.direction === exports.NavigationDirection.Next ?
61479                 exports.NavigationDirection.Prev : exports.NavigationDirection.Next;
61480             const playing = configuration.playing;
61481             const switchButtonProperties = {
61482                 onclick: () => {
61483                     if (!playing) {
61484                         component.configure({ direction });
61485                     }
61486                 },
61487             };
61488             const switchButtonClassName = configuration.playing ? ".mapillary-sequence-switch-button-inactive" : ".mapillary-sequence-switch-button";
61489             const switchButton = virtualDom.h("div" + switchButtonClassName, switchButtonProperties, [switchIcon]);
61490             const slowIcon = virtualDom.h("div.mapillary-sequence-slow-icon.mapillary-sequence-icon-visible", []);
61491             const slowContainer = virtualDom.h("div.mapillary-sequence-slow-container", [slowIcon]);
61492             const fastIcon = virtualDom.h("div.mapillary-sequence-fast-icon.mapillary-sequence-icon-visible", []);
61493             const fastContainer = virtualDom.h("div.mapillary-sequence-fast-container", [fastIcon]);
61494             const closeIcon = virtualDom.h("div.mapillary-sequence-close-icon.mapillary-sequence-icon-visible", []);
61495             const closeButtonProperties = {
61496                 onclick: () => {
61497                     this._mode = SequenceMode.Default;
61498                     this._notifyChanged$.next(this);
61499                 },
61500             };
61501             const closeButton = virtualDom.h("div.mapillary-sequence-close-button", closeButtonProperties, [closeIcon]);
61502             const speedInput = this._createSpeedInput(speed);
61503             const playbackChildren = [switchButton, slowContainer, speedInput, fastContainer, closeButton];
61504             const top = Math.round(containerWidth / this._stepperDefaultWidth * this._defaultHeight + 10);
61505             const playbackProperties = { style: { top: `${top}px` } };
61506             return virtualDom.h("div.mapillary-sequence-playback", playbackProperties, playbackChildren);
61507         }
61508         _createPlayingButton(nextId, prevId, playEnabled, configuration, component) {
61509             let canPlay = (configuration.direction === exports.NavigationDirection.Next && nextId != null) ||
61510                 (configuration.direction === exports.NavigationDirection.Prev && prevId != null);
61511             canPlay = canPlay && playEnabled;
61512             let onclick = configuration.playing ?
61513                 () => { component.stop(); } :
61514                 canPlay ? () => { component.play(); } : null;
61515             let buttonProperties = { onclick: onclick };
61516             let iconProperties = {};
61517             if (configuration.direction === exports.NavigationDirection.Prev) {
61518                 iconProperties.style = {
61519                     transform: "rotate(180deg) translate(50%, 50%)",
61520                 };
61521             }
61522             let icon = virtualDom.h("div.mapillary-sequence-icon", iconProperties, []);
61523             let buttonClass = configuration.playing ?
61524                 "mapillary-sequence-stop" :
61525                 canPlay ?
61526                     "mapillary-sequence-play" :
61527                     "mapillary-sequence-play-inactive";
61528             return virtualDom.h("div." + buttonClass, buttonProperties, [icon]);
61529         }
61530         _createSequenceControls(containerWidth) {
61531             const borderRadius = Math.round(8 / this._stepperDefaultWidth * containerWidth);
61532             const expanderProperties = {
61533                 onclick: () => {
61534                     this._expandControls = !this._expandControls;
61535                     this._mode = SequenceMode.Default;
61536                     this._notifyChanged$.next(this);
61537                 },
61538                 style: {
61539                     "border-bottom-right-radius": `${borderRadius}px`,
61540                     "border-top-right-radius": `${borderRadius}px`,
61541                 },
61542             };
61543             const expanderBar = virtualDom.h("div.mapillary-sequence-expander-bar", []);
61544             const expander = virtualDom.h("div.mapillary-sequence-expander-button", expanderProperties, [expanderBar]);
61545             const fastIconClassName = this._mode === SequenceMode.Playback ?
61546                 ".mapillary-sequence-fast-icon-gray.mapillary-sequence-icon-visible" : ".mapillary-sequence-fast-icon";
61547             const fastIcon = virtualDom.h("div" + fastIconClassName, []);
61548             const playbackProperties = {
61549                 onclick: () => {
61550                     this._mode = this._mode === SequenceMode.Playback ?
61551                         SequenceMode.Default :
61552                         SequenceMode.Playback;
61553                     this._notifyChanged$.next(this);
61554                 },
61555             };
61556             const playback = virtualDom.h("div.mapillary-sequence-playback-button", playbackProperties, [fastIcon]);
61557             const timelineIconClassName = this._mode === SequenceMode.Timeline ?
61558                 ".mapillary-sequence-timeline-icon-gray.mapillary-sequence-icon-visible" : ".mapillary-sequence-timeline-icon";
61559             const timelineIcon = virtualDom.h("div" + timelineIconClassName, []);
61560             const timelineProperties = {
61561                 onclick: () => {
61562                     this._mode = this._mode === SequenceMode.Timeline ?
61563                         SequenceMode.Default :
61564                         SequenceMode.Timeline;
61565                     this._notifyChanged$.next(this);
61566                 },
61567             };
61568             const timeline = virtualDom.h("div.mapillary-sequence-timeline-button", timelineProperties, [timelineIcon]);
61569             const properties = {
61570                 style: {
61571                     height: (this._defaultHeight / this._stepperDefaultWidth * containerWidth) + "px",
61572                     transform: `translate(${containerWidth / 2 + 2}px, 0)`,
61573                     width: (this._controlsDefaultWidth / this._stepperDefaultWidth * containerWidth) + "px",
61574                 },
61575             };
61576             const className = ".mapillary-sequence-controls" +
61577                 (this._expandControls ? ".mapillary-sequence-controls-expanded" : "");
61578             return virtualDom.h("div" + className, properties, [playback, timeline, expander]);
61579         }
61580         _createSequenceArrows(nextId, prevId, containerWidth, configuration, navigator) {
61581             let nextProperties = {
61582                 onclick: nextId != null ?
61583                     () => {
61584                         navigator.moveDir$(exports.NavigationDirection.Next)
61585                             .subscribe(undefined, (error) => {
61586                             if (!(error instanceof CancelMapillaryError)) {
61587                                 console.error(error);
61588                             }
61589                         });
61590                     } :
61591                     null,
61592                 onpointerenter: () => { this._mouseEnterDirection$.next(exports.NavigationDirection.Next); },
61593                 onpointerleave: () => { this._mouseLeaveDirection$.next(exports.NavigationDirection.Next); },
61594             };
61595             const borderRadius = Math.round(8 / this._stepperDefaultWidth * containerWidth);
61596             let prevProperties = {
61597                 onclick: prevId != null ?
61598                     () => {
61599                         navigator.moveDir$(exports.NavigationDirection.Prev)
61600                             .subscribe(undefined, (error) => {
61601                             if (!(error instanceof CancelMapillaryError)) {
61602                                 console.error(error);
61603                             }
61604                         });
61605                     } :
61606                     null,
61607                 onpointerenter: () => { this._mouseEnterDirection$.next(exports.NavigationDirection.Prev); },
61608                 onpointerleave: () => { this._mouseLeaveDirection$.next(exports.NavigationDirection.Prev); },
61609                 style: {
61610                     "border-bottom-left-radius": `${borderRadius}px`,
61611                     "border-top-left-radius": `${borderRadius}px`,
61612                 },
61613             };
61614             let nextClass = this._getStepClassName(exports.NavigationDirection.Next, nextId, configuration.highlightId);
61615             let prevClass = this._getStepClassName(exports.NavigationDirection.Prev, prevId, configuration.highlightId);
61616             let nextIcon = virtualDom.h("div.mapillary-sequence-icon", []);
61617             let prevIcon = virtualDom.h("div.mapillary-sequence-icon", []);
61618             return [
61619                 virtualDom.h("div." + prevClass, prevProperties, [prevIcon]),
61620                 virtualDom.h("div." + nextClass, nextProperties, [nextIcon]),
61621             ];
61622         }
61623         _createStepper(edgeStatus, configuration, playEnabled, containerWidth, component, navigator) {
61624             let nextId = null;
61625             let prevId = null;
61626             for (let edge of edgeStatus.edges) {
61627                 if (edge.data.direction === exports.NavigationDirection.Next) {
61628                     nextId = edge.target;
61629                 }
61630                 if (edge.data.direction === exports.NavigationDirection.Prev) {
61631                     prevId = edge.target;
61632                 }
61633             }
61634             const playingButton = this._createPlayingButton(nextId, prevId, playEnabled, configuration, component);
61635             const buttons = this._createSequenceArrows(nextId, prevId, containerWidth, configuration, navigator);
61636             buttons.splice(1, 0, playingButton);
61637             const containerProperties = {
61638                 oncontextmenu: (event) => { event.preventDefault(); },
61639                 style: {
61640                     height: (this._defaultHeight / this._stepperDefaultWidth * containerWidth) + "px",
61641                     width: containerWidth + "px",
61642                 },
61643             };
61644             return virtualDom.h("div.mapillary-sequence-stepper", containerProperties, buttons);
61645         }
61646         _createTimelineControls(containerWidth, index, max) {
61647             if (this._mode !== SequenceMode.Timeline) {
61648                 return virtualDom.h("div.mapillary-sequence-timeline", []);
61649             }
61650             const positionInput = this._createPositionInput(index, max);
61651             const closeIcon = virtualDom.h("div.mapillary-sequence-close-icon.mapillary-sequence-icon-visible", []);
61652             const closeButtonProperties = {
61653                 onclick: () => {
61654                     this._mode = SequenceMode.Default;
61655                     this._notifyChanged$.next(this);
61656                 },
61657             };
61658             const closeButton = virtualDom.h("div.mapillary-sequence-close-button", closeButtonProperties, [closeIcon]);
61659             const top = Math.round(containerWidth / this._stepperDefaultWidth * this._defaultHeight + 10);
61660             const playbackProperties = { style: { top: `${top}px` } };
61661             return virtualDom.h("div.mapillary-sequence-timeline", playbackProperties, [positionInput, closeButton]);
61662         }
61663         _getStepClassName(direction, imageId, highlightId) {
61664             let className = direction === exports.NavigationDirection.Next ?
61665                 "mapillary-sequence-step-next" :
61666                 "mapillary-sequence-step-prev";
61667             if (imageId == null) {
61668                 className += "-inactive";
61669             }
61670             else {
61671                 if (highlightId === imageId) {
61672                     className += "-highlight";
61673                 }
61674             }
61675             return className;
61676         }
61677         _setChangingPosition(value) {
61678             this._changingPosition = value;
61679             this._notifyChangingPositionChanged$.next(value);
61680         }
61681     }
61682
61683     /**
61684      * @class SequenceComponent
61685      * @classdesc Component showing navigation arrows for sequence directions
61686      * as well as playing button. Exposes an API to start and stop play.
61687      */
61688     class SequenceComponent extends Component {
61689         constructor(name, container, navigator, renderer, scheduler) {
61690             super(name, container, navigator);
61691             this._sequenceDOMRenderer = !!renderer ? renderer : new SequenceDOMRenderer(container);
61692             this._scheduler = scheduler;
61693             this._containerWidth$ = new Subject();
61694             this._hoveredIdSubject$ = new Subject();
61695             this._hoveredId$ = this._hoveredIdSubject$.pipe(share());
61696             this._navigator.playService.playing$.pipe(skip(1), withLatestFrom(this._configuration$))
61697                 .subscribe(([playing, configuration]) => {
61698                 const type = "playing";
61699                 const event = {
61700                     playing,
61701                     target: this,
61702                     type,
61703                 };
61704                 this.fire(type, event);
61705                 if (playing === configuration.playing) {
61706                     return;
61707                 }
61708                 if (playing) {
61709                     this.play();
61710                 }
61711                 else {
61712                     this.stop();
61713                 }
61714             });
61715             this._navigator.playService.direction$.pipe(skip(1), withLatestFrom(this._configuration$))
61716                 .subscribe(([direction, configuration]) => {
61717                 if (direction !== configuration.direction) {
61718                     this.configure({ direction });
61719                 }
61720             });
61721         }
61722         fire(type, event) {
61723             super.fire(type, event);
61724         }
61725         off(type, handler) {
61726             super.off(type, handler);
61727         }
61728         on(type, handler) {
61729             super.on(type, handler);
61730         }
61731         /**
61732          * Start playing.
61733          *
61734          * @fires playing
61735          */
61736         play() { this.configure({ playing: true }); }
61737         /**
61738          * Stop playing.
61739          *
61740          * @fires playing
61741          */
61742         stop() { this.configure({ playing: false }); }
61743         _activate() {
61744             this._sequenceDOMRenderer.activate();
61745             const edgeStatus$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
61746                 return image.sequenceEdges$;
61747             }), publishReplay(1), refCount());
61748             const sequence$ = this._navigator.stateService.currentImage$.pipe(distinctUntilChanged(undefined, (image) => {
61749                 return image.sequenceId;
61750             }), switchMap((image) => {
61751                 return concat(of(null), this._navigator.graphService.cacheSequence$(image.sequenceId).pipe(retry(3), catchError((e) => {
61752                     console.error("Failed to cache sequence", e);
61753                     return of(null);
61754                 })));
61755             }), startWith(null), publishReplay(1), refCount());
61756             const subs = this._subscriptions;
61757             subs.push(sequence$.subscribe());
61758             const rendererId$ = this._sequenceDOMRenderer.index$.pipe(withLatestFrom(sequence$), map(([index, sequence]) => {
61759                 return sequence != null ? sequence.imageIds[index] : null;
61760             }), filter((id) => {
61761                 return !!id;
61762             }), distinctUntilChanged(), publish(), refCount());
61763             subs.push(merge(rendererId$.pipe(debounceTime(100, this._scheduler)), rendererId$.pipe(auditTime(400, this._scheduler))).pipe(distinctUntilChanged(), switchMap((id) => {
61764                 return this._navigator.moveTo$(id).pipe(catchError(() => {
61765                     return empty();
61766                 }));
61767             }))
61768                 .subscribe());
61769             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
61770                 return changing;
61771             }))
61772                 .subscribe(() => {
61773                 this._navigator.graphService.setGraphMode(GraphMode.Sequence);
61774             }));
61775             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
61776                 return !changing;
61777             }))
61778                 .subscribe(() => {
61779                 this._navigator.graphService.setGraphMode(GraphMode.Spatial);
61780             }));
61781             this._navigator.graphService.graphMode$.pipe(switchMap((mode) => {
61782                 return mode === GraphMode.Spatial ?
61783                     this._navigator.stateService.currentImage$.pipe(take(2)) :
61784                     empty();
61785             }), filter((image) => {
61786                 return !image.spatialEdges.cached;
61787             }), switchMap((image) => {
61788                 return this._navigator.graphService.cacheImage$(image.id).pipe(catchError(() => {
61789                     return empty();
61790                 }));
61791             }))
61792                 .subscribe();
61793             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
61794                 return changing;
61795             }))
61796                 .subscribe(() => {
61797                 this._navigator.playService.stop();
61798             }));
61799             subs.push(combineLatest(this._navigator.graphService.graphMode$, this._sequenceDOMRenderer.changingPositionChanged$.pipe(startWith(false), distinctUntilChanged())).pipe(withLatestFrom(this._navigator.stateService.currentImage$), switchMap(([[mode, changing], image]) => {
61800                 return changing && mode === GraphMode.Sequence ?
61801                     this._navigator.graphService.cacheSequenceImages$(image.sequenceId, image.id).pipe(retry(3), catchError((error) => {
61802                         console.error("Failed to cache sequence images.", error);
61803                         return empty();
61804                     })) :
61805                     empty();
61806             }))
61807                 .subscribe());
61808             const position$ = sequence$.pipe(switchMap((sequence) => {
61809                 if (!sequence) {
61810                     return of({ index: null, max: null });
61811                 }
61812                 let firstCurrentId = true;
61813                 return this._sequenceDOMRenderer.changingPositionChanged$.pipe(startWith(false), distinctUntilChanged(), switchMap((changingPosition) => {
61814                     const skipCount = !changingPosition &&
61815                         firstCurrentId ?
61816                         0 : 1;
61817                     firstCurrentId = false;
61818                     return changingPosition ?
61819                         rendererId$ :
61820                         this._navigator.stateService.currentImage$.pipe(map((image) => {
61821                             return image.id;
61822                         }), distinctUntilChanged(), skip(skipCount));
61823                 }), map((imageId) => {
61824                     const index = sequence.imageIds.indexOf(imageId);
61825                     if (index === -1) {
61826                         return { index: null, max: null };
61827                     }
61828                     return { index: index, max: sequence.imageIds.length - 1 };
61829                 }));
61830             }));
61831             const earth$ = this._navigator.stateService.state$.pipe(map((state) => {
61832                 return state === State.Earth;
61833             }), distinctUntilChanged());
61834             subs.push(combineLatest(edgeStatus$, this._configuration$, this._containerWidth$, this._sequenceDOMRenderer.changed$.pipe(startWith(this._sequenceDOMRenderer)), this._navigator.playService.speed$, position$, earth$).pipe(map(([edgeStatus, configuration, containerWidth, , speed, position, earth]) => {
61835                 const vNode = this._sequenceDOMRenderer
61836                     .render(edgeStatus, configuration, containerWidth, speed, position.index, position.max, !earth, this, this._navigator);
61837                 return { name: this._name, vNode: vNode };
61838             }))
61839                 .subscribe(this._container.domRenderer.render$));
61840             subs.push(this._sequenceDOMRenderer.speed$
61841                 .subscribe((speed) => {
61842                 this._navigator.playService.setSpeed(speed);
61843             }));
61844             subs.push(this._configuration$.pipe(map((configuration) => {
61845                 return configuration.direction;
61846             }), distinctUntilChanged())
61847                 .subscribe((direction) => {
61848                 this._navigator.playService.setDirection(direction);
61849             }));
61850             subs.push(combineLatest(this._container.renderService.size$, this._configuration$.pipe(distinctUntilChanged((value1, value2) => {
61851                 return value1[0] === value2[0] && value1[1] === value2[1];
61852             }, (configuration) => {
61853                 return [configuration.minWidth, configuration.maxWidth];
61854             }))).pipe(map(([size, configuration]) => {
61855                 return this._sequenceDOMRenderer.getContainerWidth(size, configuration);
61856             }))
61857                 .subscribe(this._containerWidth$));
61858             subs.push(this._configuration$.pipe(map((configuration) => {
61859                 return configuration.playing;
61860             }), distinctUntilChanged())
61861                 .subscribe((playing) => {
61862                 if (playing) {
61863                     this._navigator.playService.play();
61864                 }
61865                 else {
61866                     this._navigator.playService.stop();
61867                 }
61868             }));
61869             subs.push(this._sequenceDOMRenderer.mouseEnterDirection$.pipe(switchMap((direction) => {
61870                 const edgeTo$ = edgeStatus$.pipe(map((edgeStatus) => {
61871                     for (let edge of edgeStatus.edges) {
61872                         if (edge.data.direction === direction) {
61873                             return edge.target;
61874                         }
61875                     }
61876                     return null;
61877                 }), takeUntil(this._sequenceDOMRenderer.mouseLeaveDirection$));
61878                 return concat(edgeTo$, of(null));
61879             }), distinctUntilChanged())
61880                 .subscribe(this._hoveredIdSubject$));
61881             subs.push(this._hoveredId$
61882                 .subscribe((id) => {
61883                 const type = "hover";
61884                 const event = {
61885                     id,
61886                     target: this,
61887                     type,
61888                 };
61889                 this.fire(type, event);
61890             }));
61891         }
61892         _deactivate() {
61893             this._subscriptions.unsubscribe();
61894             this._sequenceDOMRenderer.deactivate();
61895         }
61896         _getDefaultConfiguration() {
61897             return {
61898                 direction: exports.NavigationDirection.Next,
61899                 maxWidth: 108,
61900                 minWidth: 70,
61901                 playing: false,
61902                 visible: true,
61903             };
61904         }
61905     }
61906     /** @inheritdoc */
61907     SequenceComponent.componentName = "sequence";
61908
61909     /**
61910      * Enumeration for slider mode.
61911      *
61912      * @enum {number}
61913      * @readonly
61914      *
61915      * @description Modes for specifying how transitions
61916      * between images are performed in slider mode. Only
61917      * applicable when the slider component determines
61918      * that transitions with motion is possilble. When it
61919      * is not, the stationary mode will be applied.
61920      */
61921     exports.SliderConfigurationMode = void 0;
61922     (function (SliderConfigurationMode) {
61923         /**
61924          * Transitions with motion.
61925          *
61926          * @description The slider component moves the
61927          * camera between the image origins.
61928          *
61929          * In this mode it is not possible to zoom or pan.
61930          *
61931          * The slider component falls back to stationary
61932          * mode when it determines that the pair of images
61933          * does not have a strong enough relation.
61934          */
61935         SliderConfigurationMode[SliderConfigurationMode["Motion"] = 0] = "Motion";
61936         /**
61937          * Stationary transitions.
61938          *
61939          * @description The camera is stationary.
61940          *
61941          * In this mode it is possible to zoom and pan.
61942          */
61943         SliderConfigurationMode[SliderConfigurationMode["Stationary"] = 1] = "Stationary";
61944     })(exports.SliderConfigurationMode || (exports.SliderConfigurationMode = {}));
61945
61946     class SliderGLRenderer {
61947         constructor() {
61948             this._factory = new MeshFactory();
61949             this._scene = new MeshScene();
61950             this._spatial = new Spatial();
61951             this._currentKey = null;
61952             this._previousKey = null;
61953             this._disabled = false;
61954             this._curtain = 1;
61955             this._frameId = 0;
61956             this._needsRender = false;
61957             this._mode = null;
61958             this._currentProviderDisposers = {};
61959             this._previousProviderDisposers = {};
61960         }
61961         get disabled() {
61962             return this._disabled;
61963         }
61964         get frameId() {
61965             return this._frameId;
61966         }
61967         get needsRender() {
61968             return this._needsRender;
61969         }
61970         setTextureProvider(key, provider) {
61971             this._setTextureProvider(key, this._currentKey, provider, this._currentProviderDisposers, this._updateTexture.bind(this));
61972         }
61973         setTextureProviderPrev(key, provider) {
61974             this._setTextureProvider(key, this._previousKey, provider, this._previousProviderDisposers, this._updateTexturePrev.bind(this));
61975         }
61976         update(frame, mode) {
61977             this._updateFrameId(frame.id);
61978             this._updateImagePlanes(frame.state, mode);
61979         }
61980         updateCurtain(curtain) {
61981             if (this._curtain === curtain) {
61982                 return;
61983             }
61984             this._curtain = curtain;
61985             this._updateCurtain();
61986             this._needsRender = true;
61987         }
61988         updateTexture(imageElement, image) {
61989             const planes = image.id === this._currentKey ?
61990                 this._scene.planes :
61991                 image.id === this._previousKey ?
61992                     this._scene.planesOld :
61993                     {};
61994             if (Object.keys(planes).length === 0) {
61995                 return;
61996             }
61997             this._needsRender = true;
61998             for (const key in planes) {
61999                 if (!planes.hasOwnProperty(key)) {
62000                     continue;
62001                 }
62002                 const plane = planes[key];
62003                 let material = plane.material;
62004                 let texture = material.uniforms.projectorTex.value;
62005                 texture.image = imageElement;
62006                 texture.needsUpdate = true;
62007             }
62008         }
62009         updateTextureImage(imageElement, image) {
62010             if (this._currentKey !== image.id) {
62011                 return;
62012             }
62013             this._needsRender = true;
62014             const planes = this._scene.planes;
62015             for (const key in planes) {
62016                 if (!planes.hasOwnProperty(key)) {
62017                     continue;
62018                 }
62019                 const plane = planes[key];
62020                 let material = plane.material;
62021                 let texture = material.uniforms.projectorTex.value;
62022                 texture.image = imageElement;
62023                 texture.needsUpdate = true;
62024             }
62025         }
62026         render(perspectiveCamera, renderer) {
62027             if (!this.disabled) {
62028                 renderer.render(this._scene.sceneOld, perspectiveCamera);
62029             }
62030             renderer.render(this._scene.scene, perspectiveCamera);
62031             this._needsRender = false;
62032         }
62033         dispose() {
62034             this._scene.clear();
62035             for (const key in this._currentProviderDisposers) {
62036                 if (!this._currentProviderDisposers.hasOwnProperty(key)) {
62037                     continue;
62038                 }
62039                 this._currentProviderDisposers[key]();
62040             }
62041             for (const key in this._previousProviderDisposers) {
62042                 if (!this._previousProviderDisposers.hasOwnProperty(key)) {
62043                     continue;
62044                 }
62045                 this._previousProviderDisposers[key]();
62046             }
62047             this._currentProviderDisposers = {};
62048             this._previousProviderDisposers = {};
62049         }
62050         _getBasicCorners(currentAspect, previousAspect) {
62051             let offsetX;
62052             let offsetY;
62053             if (currentAspect > previousAspect) {
62054                 offsetX = 0.5;
62055                 offsetY = 0.5 * currentAspect / previousAspect;
62056             }
62057             else {
62058                 offsetX = 0.5 * previousAspect / currentAspect;
62059                 offsetY = 0.5;
62060             }
62061             return [[0.5 - offsetX, 0.5 - offsetY], [0.5 + offsetX, 0.5 + offsetY]];
62062         }
62063         _setDisabled(state) {
62064             this._disabled = state.currentImage == null ||
62065                 state.previousImage == null ||
62066                 (isSpherical(state.currentImage.cameraType) &&
62067                     !isSpherical(state.previousImage.cameraType));
62068         }
62069         _setTextureProvider(key, originalKey, provider, providerDisposers, updateTexture) {
62070             if (key !== originalKey) {
62071                 return;
62072             }
62073             let createdSubscription = provider.textureCreated$
62074                 .subscribe(updateTexture);
62075             let updatedSubscription = provider.textureUpdated$
62076                 .subscribe((updated) => {
62077                 this._needsRender = true;
62078             });
62079             let dispose = () => {
62080                 createdSubscription.unsubscribe();
62081                 updatedSubscription.unsubscribe();
62082                 provider.dispose();
62083             };
62084             if (key in providerDisposers) {
62085                 let disposeProvider = providerDisposers[key];
62086                 disposeProvider();
62087                 delete providerDisposers[key];
62088             }
62089             providerDisposers[key] = dispose;
62090         }
62091         _updateCurtain() {
62092             const planes = this._scene.planes;
62093             for (const key in planes) {
62094                 if (!planes.hasOwnProperty(key)) {
62095                     continue;
62096                 }
62097                 const plane = planes[key];
62098                 let shaderMaterial = plane.material;
62099                 if (!!shaderMaterial.uniforms.curtain) {
62100                     shaderMaterial.uniforms.curtain.value = this._curtain;
62101                 }
62102             }
62103         }
62104         _updateFrameId(frameId) {
62105             this._frameId = frameId;
62106         }
62107         _updateImagePlanes(state, mode) {
62108             const currentChanged = state.currentImage != null && this._currentKey !== state.currentImage.id;
62109             const previousChanged = state.previousImage != null && this._previousKey !== state.previousImage.id;
62110             const modeChanged = this._mode !== mode;
62111             if (!(currentChanged || previousChanged || modeChanged)) {
62112                 return;
62113             }
62114             this._setDisabled(state);
62115             this._needsRender = true;
62116             this._mode = mode;
62117             const motionless = state.motionless ||
62118                 mode === exports.SliderConfigurationMode.Stationary ||
62119                 isSpherical(state.currentImage.cameraType);
62120             if (this.disabled || previousChanged) {
62121                 if (this._previousKey in this._previousProviderDisposers) {
62122                     this._previousProviderDisposers[this._previousKey]();
62123                     delete this._previousProviderDisposers[this._previousKey];
62124                 }
62125             }
62126             if (this.disabled) {
62127                 this._scene.setImagePlanesOld({});
62128             }
62129             else {
62130                 if (previousChanged || modeChanged) {
62131                     const previousNode = state.previousImage;
62132                     this._previousKey = previousNode.id;
62133                     const elements = state.currentTransform.rt.elements;
62134                     let translation = [elements[12], elements[13], elements[14]];
62135                     const currentAspect = state.currentTransform.basicAspect;
62136                     const previousAspect = state.previousTransform.basicAspect;
62137                     const textureScale = currentAspect > previousAspect ?
62138                         [1, previousAspect / currentAspect] :
62139                         [currentAspect / previousAspect, 1];
62140                     let rotation = state.currentImage.rotation;
62141                     let width = state.currentImage.width;
62142                     let height = state.currentImage.height;
62143                     if (isSpherical(previousNode.cameraType)) {
62144                         rotation = state.previousImage.rotation;
62145                         translation = this._spatial
62146                             .rotate(this._spatial
62147                             .opticalCenter(state.currentImage.rotation, translation)
62148                             .toArray(), rotation)
62149                             .multiplyScalar(-1)
62150                             .toArray();
62151                         width = state.previousImage.width;
62152                         height = state.previousImage.height;
62153                     }
62154                     const transform = new Transform(state.currentImage.exifOrientation, width, height, state.currentImage.scale, rotation, translation, previousNode.image, textureScale, state.currentImage.cameraParameters, state.currentImage.cameraType);
62155                     let mesh = undefined;
62156                     if (isSpherical(previousNode.cameraType)) {
62157                         mesh = this._factory.createMesh(previousNode, motionless ||
62158                             isSpherical(state.currentImage.cameraType) ?
62159                             transform : state.previousTransform);
62160                     }
62161                     else {
62162                         if (motionless) {
62163                             const [[basicX0, basicY0], [basicX1, basicY1]] = this._getBasicCorners(currentAspect, previousAspect);
62164                             mesh = this._factory.createFlatMesh(state.previousImage, transform, basicX0, basicX1, basicY0, basicY1);
62165                         }
62166                         else {
62167                             mesh = this._factory.createMesh(state.previousImage, state.previousTransform);
62168                         }
62169                     }
62170                     const previousPlanes = {};
62171                     previousPlanes[previousNode.id] = mesh;
62172                     this._scene.setImagePlanesOld(previousPlanes);
62173                 }
62174             }
62175             if (currentChanged || modeChanged) {
62176                 if (this._currentKey in this._currentProviderDisposers) {
62177                     this._currentProviderDisposers[this._currentKey]();
62178                     delete this._currentProviderDisposers[this._currentKey];
62179                 }
62180                 this._currentKey = state.currentImage.id;
62181                 const planes = {};
62182                 if (isSpherical(state.currentImage.cameraType)) {
62183                     planes[state.currentImage.id] =
62184                         this._factory.createCurtainMesh(state.currentImage, state.currentTransform);
62185                 }
62186                 else {
62187                     if (motionless) {
62188                         planes[state.currentImage.id] = this._factory.createDistortedCurtainMesh(state.currentImage, state.currentTransform);
62189                     }
62190                     else {
62191                         planes[state.currentImage.id] = this._factory.createCurtainMesh(state.currentImage, state.currentTransform);
62192                     }
62193                 }
62194                 this._scene.setImagePlanes(planes);
62195                 this._updateCurtain();
62196             }
62197         }
62198         _updateTexture(texture) {
62199             this._needsRender = true;
62200             const planes = this._scene.planes;
62201             for (const key in planes) {
62202                 if (!planes.hasOwnProperty(key)) {
62203                     continue;
62204                 }
62205                 const plane = planes[key];
62206                 let material = plane.material;
62207                 let oldTexture = material.uniforms.projectorTex.value;
62208                 material.uniforms.projectorTex.value = null;
62209                 oldTexture.dispose();
62210                 material.uniforms.projectorTex.value = texture;
62211             }
62212         }
62213         _updateTexturePrev(texture) {
62214             this._needsRender = true;
62215             const planes = this._scene.planesOld;
62216             for (const key in planes) {
62217                 if (!planes.hasOwnProperty(key)) {
62218                     continue;
62219                 }
62220                 const plane = planes[key];
62221                 let material = plane.material;
62222                 let oldTexture = material.uniforms.projectorTex.value;
62223                 material.uniforms.projectorTex.value = null;
62224                 oldTexture.dispose();
62225                 material.uniforms.projectorTex.value = texture;
62226             }
62227         }
62228     }
62229
62230     class SliderDOMRenderer {
62231         constructor(container) {
62232             this._container = container;
62233             this._interacting = false;
62234             this._notifyModeChanged$ = new Subject();
62235             this._notifyPositionChanged$ = new Subject();
62236             this._stopInteractionSubscription = null;
62237         }
62238         get mode$() {
62239             return this._notifyModeChanged$;
62240         }
62241         get position$() {
62242             return this._notifyPositionChanged$;
62243         }
62244         activate() {
62245             if (!!this._stopInteractionSubscription) {
62246                 return;
62247             }
62248             this._stopInteractionSubscription = merge(this._container.mouseService.documentMouseUp$, this._container.touchService.touchEnd$.pipe(filter((touchEvent) => {
62249                 return touchEvent.touches.length === 0;
62250             })))
62251                 .subscribe((event) => {
62252                 if (this._interacting) {
62253                     this._interacting = false;
62254                 }
62255             });
62256         }
62257         deactivate() {
62258             if (!this._stopInteractionSubscription) {
62259                 return;
62260             }
62261             this._interacting = false;
62262             this._stopInteractionSubscription.unsubscribe();
62263             this._stopInteractionSubscription = null;
62264         }
62265         render(position, mode, motionless, spherical, visible) {
62266             const children = [];
62267             if (visible) {
62268                 children.push(virtualDom.h("div.mapillary-slider-border", []));
62269                 const modeVisible = !(motionless || spherical);
62270                 if (modeVisible) {
62271                     children.push(this._createModeButton(mode));
62272                     children.push(this._createModeButton2d(mode));
62273                 }
62274                 children.push(this._createPositionInput(position, modeVisible));
62275             }
62276             const boundingRect = this._container.domContainer.getBoundingClientRect();
62277             const width = Math.max(215, Math.min(400, boundingRect.width - 100));
62278             return virtualDom.h("div.mapillary-slider-container", { style: { width: `${width}px` } }, children);
62279         }
62280         _createModeButton(mode) {
62281             const properties = {
62282                 onclick: () => {
62283                     if (mode === exports.SliderConfigurationMode.Motion) {
62284                         return;
62285                     }
62286                     this._notifyModeChanged$.next(exports.SliderConfigurationMode.Motion);
62287                 },
62288             };
62289             const className = mode === exports.SliderConfigurationMode.Stationary ?
62290                 "mapillary-slider-mode-button-inactive" :
62291                 "mapillary-slider-mode-button";
62292             return virtualDom.h("div." + className, properties, [virtualDom.h("div.mapillary-slider-mode-icon", [])]);
62293         }
62294         _createModeButton2d(mode) {
62295             const properties = {
62296                 onclick: () => {
62297                     if (mode === exports.SliderConfigurationMode.Stationary) {
62298                         return;
62299                     }
62300                     this._notifyModeChanged$.next(exports.SliderConfigurationMode.Stationary);
62301                 },
62302             };
62303             const className = mode === exports.SliderConfigurationMode.Motion ?
62304                 "mapillary-slider-mode-button-2d-inactive" :
62305                 "mapillary-slider-mode-button-2d";
62306             return virtualDom.h("div." + className, properties, [virtualDom.h("div.mapillary-slider-mode-icon-2d", [])]);
62307         }
62308         _createPositionInput(position, modeVisible) {
62309             const onChange = (e) => {
62310                 this._notifyPositionChanged$.next(Number(e.target.value) / 1000);
62311             };
62312             const onStart = (e) => {
62313                 this._interacting = true;
62314                 e.stopPropagation();
62315             };
62316             const onMove = (e) => {
62317                 if (this._interacting) {
62318                     e.stopPropagation();
62319                 }
62320             };
62321             const onKeyDown = (e) => {
62322                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
62323                     e.key === "ArrowRight" || e.key === "ArrowUp") {
62324                     e.preventDefault();
62325                 }
62326             };
62327             const boundingRect = this._container.domContainer.getBoundingClientRect();
62328             const width = Math.max(215, Math.min(400, boundingRect.width - 105)) - 84 + (modeVisible ? 0 : 52);
62329             const positionInput = virtualDom.h("input.mapillary-slider-position", {
62330                 max: 1000,
62331                 min: 0,
62332                 onchange: onChange,
62333                 oninput: onChange,
62334                 onkeydown: onKeyDown,
62335                 onpointerdown: onStart,
62336                 onpointermove: onMove,
62337                 ontouchmove: onMove,
62338                 ontouchstart: onStart,
62339                 style: {
62340                     width: `${width}px`,
62341                 },
62342                 type: "range",
62343                 value: 1000 * position,
62344             }, []);
62345             return virtualDom.h("div.mapillary-slider-position-container", [positionInput]);
62346         }
62347     }
62348
62349     /**
62350      * @class SliderComponent
62351      *
62352      * @classdesc Component for comparing pairs of images. Renders
62353      * a slider for adjusting the curtain of the first image.
62354      *
62355      * Deactivate the sequence, direction and image plane
62356      * components when activating the slider component to avoid
62357      * interfering UI elements.
62358      *
62359      * To retrive and use the slider component
62360      *
62361      * @example
62362      * ```js
62363      * var viewer = new Viewer({ ... });
62364      *
62365      * viewer.deactivateComponent("image");
62366      * viewer.deactivateComponent("direction");
62367      * viewer.deactivateComponent("sequence");
62368      *
62369      * viewer.activateComponent("slider");
62370      *
62371      * var sliderComponent = viewer.getComponent("slider");
62372      * ```
62373      */
62374     class SliderComponent extends Component {
62375         /** @ignore */
62376         constructor(name, container, navigator, viewportCoords) {
62377             super(name, container, navigator);
62378             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
62379             this._domRenderer = new SliderDOMRenderer(container);
62380             this._imageTileLoader = new TileLoader(navigator.api);
62381             this._roiCalculator = new RegionOfInterestCalculator();
62382             this._spatial = new Spatial();
62383             this._glRendererOperation$ = new Subject();
62384             this._glRendererCreator$ = new Subject();
62385             this._glRendererDisposer$ = new Subject();
62386             this._glRenderer$ = this._glRendererOperation$.pipe(scan((glRenderer, operation) => {
62387                 return operation(glRenderer);
62388             }, null), filter((glRenderer) => {
62389                 return glRenderer != null;
62390             }), distinctUntilChanged(undefined, (glRenderer) => {
62391                 return glRenderer.frameId;
62392             }));
62393             this._glRendererCreator$.pipe(map(() => {
62394                 return (glRenderer) => {
62395                     if (glRenderer != null) {
62396                         throw new Error("Multiple slider states can not be created at the same time");
62397                     }
62398                     return new SliderGLRenderer();
62399                 };
62400             }))
62401                 .subscribe(this._glRendererOperation$);
62402             this._glRendererDisposer$.pipe(map(() => {
62403                 return (glRenderer) => {
62404                     glRenderer.dispose();
62405                     return null;
62406                 };
62407             }))
62408                 .subscribe(this._glRendererOperation$);
62409         }
62410         _activate() {
62411             const subs = this._subscriptions;
62412             subs.push(this._domRenderer.mode$
62413                 .subscribe((mode) => {
62414                 this.configure({ mode });
62415             }));
62416             subs.push(this._glRenderer$.pipe(map((glRenderer) => {
62417                 let renderHash = {
62418                     name: this._name,
62419                     renderer: {
62420                         frameId: glRenderer.frameId,
62421                         needsRender: glRenderer.needsRender,
62422                         render: glRenderer.render.bind(glRenderer),
62423                         pass: RenderPass.Background,
62424                     },
62425                 };
62426                 return renderHash;
62427             }))
62428                 .subscribe(this._container.glRenderer.render$));
62429             const position$ = concat(this.configuration$.pipe(map((configuration) => {
62430                 return configuration.initialPosition != null ?
62431                     configuration.initialPosition : 1;
62432             }), first()), this._domRenderer.position$);
62433             const mode$ = this.configuration$.pipe(map((configuration) => {
62434                 return configuration.mode;
62435             }), distinctUntilChanged());
62436             const motionless$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
62437                 return frame.state.motionless;
62438             }), distinctUntilChanged());
62439             const spherical$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
62440                 return isSpherical(frame.state.currentImage.cameraType);
62441             }), distinctUntilChanged());
62442             const sliderVisible$ = combineLatest(this._configuration$.pipe(map((configuration) => {
62443                 return configuration.sliderVisible;
62444             })), this._navigator.stateService.currentState$.pipe(map((frame) => {
62445                 return !(frame.state.currentImage == null ||
62446                     frame.state.previousImage == null ||
62447                     (isSpherical(frame.state.currentImage.cameraType) &&
62448                         !isSpherical(frame.state.previousImage.cameraType)));
62449             }), distinctUntilChanged())).pipe(map(([sliderVisible, enabledState]) => {
62450                 return sliderVisible && enabledState;
62451             }), distinctUntilChanged());
62452             this._waitSubscription = combineLatest(mode$, motionless$, spherical$, sliderVisible$).pipe(withLatestFrom(this._navigator.stateService.state$))
62453                 .subscribe(([[mode, motionless, spherical, sliderVisible], state]) => {
62454                 const interactive = sliderVisible &&
62455                     (motionless ||
62456                         mode === exports.SliderConfigurationMode.Stationary ||
62457                         spherical);
62458                 if (interactive && state !== State.WaitingInteractively) {
62459                     this._navigator.stateService.waitInteractively();
62460                 }
62461                 else if (!interactive && state !== State.Waiting) {
62462                     this._navigator.stateService.wait();
62463                 }
62464             });
62465             subs.push(combineLatest(position$, mode$, motionless$, spherical$, sliderVisible$)
62466                 .subscribe(([position, mode, motionless, spherical]) => {
62467                 if (motionless || mode === exports.SliderConfigurationMode.Stationary || spherical) {
62468                     this._navigator.stateService.moveTo(1);
62469                 }
62470                 else {
62471                     this._navigator.stateService.moveTo(position);
62472                 }
62473             }));
62474             subs.push(combineLatest(position$, mode$, motionless$, spherical$, sliderVisible$, this._container.renderService.size$).pipe(map(([position, mode, motionless, spherical, sliderVisible]) => {
62475                 return {
62476                     name: this._name,
62477                     vNode: this._domRenderer.render(position, mode, motionless, spherical, sliderVisible),
62478                 };
62479             }))
62480                 .subscribe(this._container.domRenderer.render$));
62481             this._glRendererCreator$.next(null);
62482             subs.push(combineLatest(position$, spherical$, sliderVisible$, this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(map(([position, spherical, visible, render, transform]) => {
62483                 if (!spherical) {
62484                     return visible ? position : 1;
62485                 }
62486                 const basicMin = this._viewportCoords.viewportToBasic(-1.15, 0, transform, render.perspective);
62487                 const basicMax = this._viewportCoords.viewportToBasic(1.15, 0, transform, render.perspective);
62488                 const shiftedMax = basicMax[0] < basicMin[0] ? basicMax[0] + 1 : basicMax[0];
62489                 const basicPosition = basicMin[0] + position * (shiftedMax - basicMin[0]);
62490                 return basicPosition > 1 ? basicPosition - 1 : basicPosition;
62491             }), map((position) => {
62492                 return (glRenderer) => {
62493                     glRenderer.updateCurtain(position);
62494                     return glRenderer;
62495                 };
62496             }))
62497                 .subscribe(this._glRendererOperation$));
62498             subs.push(combineLatest(this._navigator.stateService.currentState$, mode$).pipe(map(([frame, mode]) => {
62499                 return (glRenderer) => {
62500                     glRenderer.update(frame, mode);
62501                     return glRenderer;
62502                 };
62503             }))
62504                 .subscribe(this._glRendererOperation$));
62505             subs.push(this._configuration$.pipe(filter((configuration) => {
62506                 return configuration.ids != null;
62507             }), switchMap((configuration) => {
62508                 return zip(zip(this._catchCacheImage$(configuration.ids.background), this._catchCacheImage$(configuration.ids.foreground)).pipe(map((images) => {
62509                     return { background: images[0], foreground: images[1] };
62510                 })), this._navigator.stateService.currentState$.pipe(first())).pipe(map((nf) => {
62511                     return { images: nf[0], state: nf[1].state };
62512                 }));
62513             }))
62514                 .subscribe((co) => {
62515                 if (co.state.currentImage != null &&
62516                     co.state.previousImage != null &&
62517                     co.state.currentImage.id === co.images.foreground.id &&
62518                     co.state.previousImage.id === co.images.background.id) {
62519                     return;
62520                 }
62521                 if (co.state.currentImage.id === co.images.background.id) {
62522                     this._navigator.stateService.setImages([co.images.foreground]);
62523                     return;
62524                 }
62525                 if (co.state.currentImage.id === co.images.foreground.id &&
62526                     co.state.trajectory.length === 1) {
62527                     this._navigator.stateService.prependImages([co.images.background]);
62528                     return;
62529                 }
62530                 this._navigator.stateService.setImages([co.images.background]);
62531                 this._navigator.stateService.setImages([co.images.foreground]);
62532             }, (e) => {
62533                 console.error(e);
62534             }));
62535             const textureProvider$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
62536                 return active ?
62537                     this._navigator.stateService.currentState$ :
62538                     new Subject();
62539             }), distinctUntilChanged(undefined, (frame) => {
62540                 return frame.state.currentImage.id;
62541             }), withLatestFrom(this._container.glRenderer.webGLRenderer$, this._container.renderService.size$), map(([frame, renderer, size]) => {
62542                 const state = frame.state;
62543                 Math.max(size.width, size.height);
62544                 const currentImage = state.currentImage;
62545                 const currentTransform = state.currentTransform;
62546                 return new TextureProvider(currentImage.id, currentTransform.basicWidth, currentTransform.basicHeight, currentImage.image, this._imageTileLoader, new TileStore(), renderer);
62547             }), publishReplay(1), refCount());
62548             subs.push(textureProvider$.subscribe(() => { }));
62549             subs.push(textureProvider$.pipe(map((provider) => {
62550                 return (renderer) => {
62551                     renderer.setTextureProvider(provider.id, provider);
62552                     return renderer;
62553                 };
62554             }))
62555                 .subscribe(this._glRendererOperation$));
62556             subs.push(textureProvider$.pipe(pairwise())
62557                 .subscribe((pair) => {
62558                 let previous = pair[0];
62559                 previous.abort();
62560             }));
62561             const roiTrigger$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
62562                 return active ?
62563                     combineLatest(this._container.renderService.renderCameraFrame$, this._container.renderService.size$.pipe(debounceTime(250))) :
62564                     new Subject();
62565             }), map(([camera, size]) => {
62566                 return [
62567                     camera.camera.position.clone(),
62568                     camera.camera.lookat.clone(),
62569                     camera.zoom.valueOf(),
62570                     size.height.valueOf(),
62571                     size.width.valueOf()
62572                 ];
62573             }), pairwise(), skipWhile((pls) => {
62574                 return pls[1][2] - pls[0][2] < 0 || pls[1][2] === 0;
62575             }), map((pls) => {
62576                 let samePosition = pls[0][0].equals(pls[1][0]);
62577                 let sameLookat = pls[0][1].equals(pls[1][1]);
62578                 let sameZoom = pls[0][2] === pls[1][2];
62579                 let sameHeight = pls[0][3] === pls[1][3];
62580                 let sameWidth = pls[0][4] === pls[1][4];
62581                 return samePosition && sameLookat && sameZoom && sameHeight && sameWidth;
62582             }), distinctUntilChanged(), filter((stalled) => {
62583                 return stalled;
62584             }), switchMap(() => {
62585                 return this._container.renderService.renderCameraFrame$.pipe(first());
62586             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
62587             subs.push(textureProvider$.pipe(switchMap((provider) => {
62588                 return roiTrigger$.pipe(map(([camera, size, transform]) => {
62589                     return [
62590                         this._roiCalculator.computeRegionOfInterest(camera, size, transform),
62591                         provider,
62592                     ];
62593                 }));
62594             }), filter((args) => {
62595                 return !args[1].disposed;
62596             }))
62597                 .subscribe((args) => {
62598                 let roi = args[0];
62599                 let provider = args[1];
62600                 provider.setRegionOfInterest(roi);
62601             }));
62602             const hasTexture$ = textureProvider$.pipe(switchMap((provider) => {
62603                 return provider.hasTexture$;
62604             }), startWith(false), publishReplay(1), refCount());
62605             subs.push(hasTexture$.subscribe(() => { }));
62606             const textureProviderPrev$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
62607                 return active ?
62608                     this._navigator.stateService.currentState$ :
62609                     new Subject();
62610             }), filter((frame) => {
62611                 return !!frame.state.previousImage;
62612             }), distinctUntilChanged(undefined, (frame) => {
62613                 return frame.state.previousImage.id;
62614             }), withLatestFrom(this._container.glRenderer.webGLRenderer$, this._container.renderService.size$), map(([frame, renderer, size]) => {
62615                 const state = frame.state;
62616                 const previousImage = state.previousImage;
62617                 const previousTransform = state.previousTransform;
62618                 return new TextureProvider(previousImage.id, previousTransform.basicWidth, previousTransform.basicHeight, previousImage.image, this._imageTileLoader, new TileStore(), renderer);
62619             }), publishReplay(1), refCount());
62620             subs.push(textureProviderPrev$.subscribe(() => { }));
62621             subs.push(textureProviderPrev$.pipe(map((provider) => {
62622                 return (renderer) => {
62623                     renderer.setTextureProviderPrev(provider.id, provider);
62624                     return renderer;
62625                 };
62626             }))
62627                 .subscribe(this._glRendererOperation$));
62628             subs.push(textureProviderPrev$.pipe(pairwise())
62629                 .subscribe((pair) => {
62630                 let previous = pair[0];
62631                 previous.abort();
62632             }));
62633             const roiTriggerPrev$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
62634                 return active ?
62635                     combineLatest(this._container.renderService.renderCameraFrame$, this._container.renderService.size$.pipe(debounceTime(250))) :
62636                     new Subject();
62637             }), map(([camera, size]) => {
62638                 return [
62639                     camera.camera.position.clone(),
62640                     camera.camera.lookat.clone(),
62641                     camera.zoom.valueOf(),
62642                     size.height.valueOf(),
62643                     size.width.valueOf()
62644                 ];
62645             }), pairwise(), skipWhile((pls) => {
62646                 return pls[1][2] - pls[0][2] < 0 || pls[1][2] === 0;
62647             }), map((pls) => {
62648                 let samePosition = pls[0][0].equals(pls[1][0]);
62649                 let sameLookat = pls[0][1].equals(pls[1][1]);
62650                 let sameZoom = pls[0][2] === pls[1][2];
62651                 let sameHeight = pls[0][3] === pls[1][3];
62652                 let sameWidth = pls[0][4] === pls[1][4];
62653                 return samePosition && sameLookat && sameZoom && sameHeight && sameWidth;
62654             }), distinctUntilChanged(), filter((stalled) => {
62655                 return stalled;
62656             }), switchMap(() => {
62657                 return this._container.renderService.renderCameraFrame$.pipe(first());
62658             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
62659             subs.push(textureProviderPrev$.pipe(switchMap((provider) => {
62660                 return roiTriggerPrev$.pipe(map(([camera, size, transform]) => {
62661                     return [
62662                         this._roiCalculator.computeRegionOfInterest(camera, size, transform),
62663                         provider,
62664                     ];
62665                 }));
62666             }), filter((args) => {
62667                 return !args[1].disposed;
62668             }), withLatestFrom(this._navigator.stateService.currentState$))
62669                 .subscribe(([[roi, provider], frame]) => {
62670                 let shiftedRoi = null;
62671                 if (isSpherical(frame.state.previousImage.cameraType)) {
62672                     if (isSpherical(frame.state.currentImage.cameraType)) {
62673                         const currentViewingDirection = this._spatial.viewingDirection(frame.state.currentImage.rotation);
62674                         const previousViewingDirection = this._spatial.viewingDirection(frame.state.previousImage.rotation);
62675                         const directionDiff = this._spatial.angleBetweenVector2(currentViewingDirection.x, currentViewingDirection.y, previousViewingDirection.x, previousViewingDirection.y);
62676                         const shift = directionDiff / (2 * Math.PI);
62677                         const bbox = {
62678                             maxX: this._spatial.wrap(roi.bbox.maxX + shift, 0, 1),
62679                             maxY: roi.bbox.maxY,
62680                             minX: this._spatial.wrap(roi.bbox.minX + shift, 0, 1),
62681                             minY: roi.bbox.minY,
62682                         };
62683                         shiftedRoi = {
62684                             bbox: bbox,
62685                             pixelHeight: roi.pixelHeight,
62686                             pixelWidth: roi.pixelWidth,
62687                         };
62688                     }
62689                     else {
62690                         const currentViewingDirection = this._spatial.viewingDirection(frame.state.currentImage.rotation);
62691                         const previousViewingDirection = this._spatial.viewingDirection(frame.state.previousImage.rotation);
62692                         const directionDiff = this._spatial.angleBetweenVector2(currentViewingDirection.x, currentViewingDirection.y, previousViewingDirection.x, previousViewingDirection.y);
62693                         const shiftX = directionDiff / (2 * Math.PI);
62694                         const a1 = this._spatial.angleToPlane(currentViewingDirection.toArray(), [0, 0, 1]);
62695                         const a2 = this._spatial.angleToPlane(previousViewingDirection.toArray(), [0, 0, 1]);
62696                         const shiftY = (a2 - a1) / (2 * Math.PI);
62697                         const currentTransform = frame.state.currentTransform;
62698                         const size = Math.max(currentTransform.basicWidth, currentTransform.basicHeight);
62699                         const hFov = size > 0 ?
62700                             2 * Math.atan(0.5 * currentTransform.basicWidth / (size * currentTransform.focal)) :
62701                             Math.PI / 3;
62702                         const vFov = size > 0 ?
62703                             2 * Math.atan(0.5 * currentTransform.basicHeight / (size * currentTransform.focal)) :
62704                             Math.PI / 3;
62705                         const spanningWidth = hFov / (2 * Math.PI);
62706                         const spanningHeight = vFov / Math.PI;
62707                         const basicWidth = (roi.bbox.maxX - roi.bbox.minX) * spanningWidth;
62708                         const basicHeight = (roi.bbox.maxY - roi.bbox.minY) * spanningHeight;
62709                         const pixelWidth = roi.pixelWidth * spanningWidth;
62710                         const pixelHeight = roi.pixelHeight * spanningHeight;
62711                         const zoomShiftX = (roi.bbox.minX + roi.bbox.maxX) / 2 - 0.5;
62712                         const zoomShiftY = (roi.bbox.minY + roi.bbox.maxY) / 2 - 0.5;
62713                         const minX = 0.5 + shiftX + spanningWidth * zoomShiftX - basicWidth / 2;
62714                         const maxX = 0.5 + shiftX + spanningWidth * zoomShiftX + basicWidth / 2;
62715                         const minY = 0.5 + shiftY + spanningHeight * zoomShiftY - basicHeight / 2;
62716                         const maxY = 0.5 + shiftY + spanningHeight * zoomShiftY + basicHeight / 2;
62717                         const bbox = {
62718                             maxX: this._spatial.wrap(maxX, 0, 1),
62719                             maxY: maxY,
62720                             minX: this._spatial.wrap(minX, 0, 1),
62721                             minY: minY,
62722                         };
62723                         shiftedRoi = {
62724                             bbox: bbox,
62725                             pixelHeight: pixelHeight,
62726                             pixelWidth: pixelWidth,
62727                         };
62728                     }
62729                 }
62730                 else {
62731                     const currentBasicAspect = frame.state.currentTransform.basicAspect;
62732                     const previousBasicAspect = frame.state.previousTransform.basicAspect;
62733                     const [[cornerMinX, cornerMinY], [cornerMaxX, cornerMaxY]] = this._getBasicCorners(currentBasicAspect, previousBasicAspect);
62734                     const basicWidth = cornerMaxX - cornerMinX;
62735                     const basicHeight = cornerMaxY - cornerMinY;
62736                     const pixelWidth = roi.pixelWidth / basicWidth;
62737                     const pixelHeight = roi.pixelHeight / basicHeight;
62738                     const minX = (basicWidth - 1) / (2 * basicWidth) + roi.bbox.minX / basicWidth;
62739                     const maxX = (basicWidth - 1) / (2 * basicWidth) + roi.bbox.maxX / basicWidth;
62740                     const minY = (basicHeight - 1) / (2 * basicHeight) + roi.bbox.minY / basicHeight;
62741                     const maxY = (basicHeight - 1) / (2 * basicHeight) + roi.bbox.maxY / basicHeight;
62742                     const bbox = {
62743                         maxX: maxX,
62744                         maxY: maxY,
62745                         minX: minX,
62746                         minY: minY,
62747                     };
62748                     this._clipBoundingBox(bbox);
62749                     shiftedRoi = {
62750                         bbox: bbox,
62751                         pixelHeight: pixelHeight,
62752                         pixelWidth: pixelWidth,
62753                     };
62754                 }
62755                 provider.setRegionOfInterest(shiftedRoi);
62756             }));
62757             const hasTexturePrev$ = textureProviderPrev$.pipe(switchMap((provider) => {
62758                 return provider.hasTexture$;
62759             }), startWith(false), publishReplay(1), refCount());
62760             subs.push(hasTexturePrev$.subscribe(() => { }));
62761         }
62762         _deactivate() {
62763             this._waitSubscription.unsubscribe();
62764             this._navigator.stateService.state$.pipe(first())
62765                 .subscribe((state) => {
62766                 if (state !== State.Traversing) {
62767                     this._navigator.stateService.traverse();
62768                 }
62769             });
62770             this._glRendererDisposer$.next(null);
62771             this._domRenderer.deactivate();
62772             this._subscriptions.unsubscribe();
62773             this.configure({ ids: null });
62774         }
62775         _getDefaultConfiguration() {
62776             return {
62777                 initialPosition: 1,
62778                 mode: exports.SliderConfigurationMode.Motion,
62779                 sliderVisible: true,
62780             };
62781         }
62782         _catchCacheImage$(imageId) {
62783             return this._navigator.graphService.cacheImage$(imageId).pipe(catchError((error) => {
62784                 console.error(`Failed to cache slider image (${imageId})`, error);
62785                 return empty();
62786             }));
62787         }
62788         _getBasicCorners(currentAspect, previousAspect) {
62789             let offsetX;
62790             let offsetY;
62791             if (currentAspect > previousAspect) {
62792                 offsetX = 0.5;
62793                 offsetY = 0.5 * currentAspect / previousAspect;
62794             }
62795             else {
62796                 offsetX = 0.5 * previousAspect / currentAspect;
62797                 offsetY = 0.5;
62798             }
62799             return [[0.5 - offsetX, 0.5 - offsetY], [0.5 + offsetX, 0.5 + offsetY]];
62800         }
62801         _clipBoundingBox(bbox) {
62802             bbox.minX = Math.max(0, Math.min(1, bbox.minX));
62803             bbox.maxX = Math.max(0, Math.min(1, bbox.maxX));
62804             bbox.minY = Math.max(0, Math.min(1, bbox.minY));
62805             bbox.maxY = Math.max(0, Math.min(1, bbox.maxY));
62806         }
62807     }
62808     SliderComponent.componentName = "slider";
62809
62810     class PlayService {
62811         constructor(graphService, stateService) {
62812             this._subscriptions = new SubscriptionHolder();
62813             this._graphService = graphService;
62814             this._stateService = stateService;
62815             const subs = this._subscriptions;
62816             this._directionSubject$ = new Subject();
62817             this._direction$ = this._directionSubject$.pipe(startWith(exports.NavigationDirection.Next), publishReplay(1), refCount());
62818             subs.push(this._direction$.subscribe());
62819             this._playing = false;
62820             this._playingSubject$ = new Subject();
62821             this._playing$ = this._playingSubject$.pipe(startWith(this._playing), publishReplay(1), refCount());
62822             subs.push(this._playing$.subscribe());
62823             this._speed = 0.5;
62824             this._speedSubject$ = new Subject();
62825             this._speed$ = this._speedSubject$.pipe(startWith(this._speed), publishReplay(1), refCount());
62826             subs.push(this._speed$.subscribe());
62827             this._imagesAhead = this._mapImagesAhead(this._mapSpeed(this._speed));
62828             this._bridging$ = null;
62829         }
62830         get playing() {
62831             return this._playing;
62832         }
62833         get direction$() {
62834             return this._direction$;
62835         }
62836         get playing$() {
62837             return this._playing$;
62838         }
62839         get speed$() {
62840             return this._speed$;
62841         }
62842         play() {
62843             if (this._playing) {
62844                 return;
62845             }
62846             this._stateService.cutImages();
62847             const stateSpeed = this._setSpeed(this._speed);
62848             this._stateService.setSpeed(stateSpeed);
62849             this._graphModeSubscription = this._speed$.pipe(map((speed) => {
62850                 return speed > PlayService.sequenceSpeed ? GraphMode.Sequence : GraphMode.Spatial;
62851             }), distinctUntilChanged())
62852                 .subscribe((mode) => {
62853                 this._graphService.setGraphMode(mode);
62854             });
62855             this._cacheSubscription = combineLatest(this._stateService.currentImage$.pipe(map((image) => {
62856                 return [image.sequenceId, image.id];
62857             }), distinctUntilChanged(undefined, ([sequenceId]) => {
62858                 return sequenceId;
62859             })), this._graphService.graphMode$, this._direction$).pipe(switchMap(([[sequenceId, imageId], mode, direction]) => {
62860                 if (direction !== exports.NavigationDirection.Next && direction !== exports.NavigationDirection.Prev) {
62861                     return of([undefined, direction]);
62862                 }
62863                 const sequence$ = (mode === GraphMode.Sequence ?
62864                     this._graphService.cacheSequenceImages$(sequenceId, imageId) :
62865                     this._graphService.cacheSequence$(sequenceId)).pipe(retry(3), catchError((error) => {
62866                     console.error(error);
62867                     return of(undefined);
62868                 }));
62869                 return combineLatest(sequence$, of(direction));
62870             }), switchMap(([sequence, direction]) => {
62871                 if (sequence === undefined) {
62872                     return empty();
62873                 }
62874                 const imageIds = sequence.imageIds.slice();
62875                 if (direction === exports.NavigationDirection.Prev) {
62876                     imageIds.reverse();
62877                 }
62878                 return this._stateService.currentState$.pipe(map((frame) => {
62879                     return [frame.state.trajectory[frame.state.trajectory.length - 1].id, frame.state.imagesAhead];
62880                 }), scan(([lastRequestKey, previousRequestKeys], [lastTrajectoryKey, imagesAhead]) => {
62881                     if (lastRequestKey === undefined) {
62882                         lastRequestKey = lastTrajectoryKey;
62883                     }
62884                     const lastIndex = imageIds.length - 1;
62885                     if (imagesAhead >= this._imagesAhead || imageIds[lastIndex] === lastRequestKey) {
62886                         return [lastRequestKey, []];
62887                     }
62888                     const current = imageIds.indexOf(lastTrajectoryKey);
62889                     const start = imageIds.indexOf(lastRequestKey) + 1;
62890                     const end = Math.min(lastIndex, current + this._imagesAhead - imagesAhead) + 1;
62891                     if (end <= start) {
62892                         return [lastRequestKey, []];
62893                     }
62894                     return [imageIds[end - 1], imageIds.slice(start, end)];
62895                 }, [undefined, []]), mergeMap(([lastRequestKey, newRequestKeys]) => {
62896                     return from(newRequestKeys);
62897                 }));
62898             }), mergeMap((key) => {
62899                 return this._graphService.cacheImage$(key).pipe(catchError(() => {
62900                     return empty();
62901                 }));
62902             }, 6))
62903                 .subscribe();
62904             this._playingSubscription = this._stateService.currentState$.pipe(filter((frame) => {
62905                 return frame.state.imagesAhead < this._imagesAhead;
62906             }), distinctUntilChanged(undefined, (frame) => {
62907                 return frame.state.lastImage.id;
62908             }), map((frame) => {
62909                 const lastImage = frame.state.lastImage;
62910                 const trajectory = frame.state.trajectory;
62911                 let increasingTime = undefined;
62912                 for (let i = trajectory.length - 2; i >= 0; i--) {
62913                     const image = trajectory[i];
62914                     if (image.sequenceId !== lastImage.sequenceId) {
62915                         break;
62916                     }
62917                     if (image.capturedAt !== lastImage.capturedAt) {
62918                         increasingTime = image.capturedAt < lastImage.capturedAt;
62919                         break;
62920                     }
62921                 }
62922                 return [frame.state.lastImage, increasingTime];
62923             }), withLatestFrom(this._direction$), switchMap(([[image, increasingTime], direction]) => {
62924                 return zip(([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
62925                     image.sequenceEdges$ :
62926                     image.spatialEdges$).pipe(first((status) => {
62927                     return status.cached;
62928                 }), timeout(15000)), of(direction)).pipe(map(([s, d]) => {
62929                     for (let edge of s.edges) {
62930                         if (edge.data.direction === d) {
62931                             return edge.target;
62932                         }
62933                     }
62934                     return null;
62935                 }), switchMap((key) => {
62936                     return key != null ?
62937                         this._graphService.cacheImage$(key) :
62938                         empty();
62939                 }));
62940             }))
62941                 .subscribe((image) => {
62942                 this._stateService.appendImagess([image]);
62943             }, (error) => {
62944                 console.error(error);
62945                 this.stop();
62946             });
62947             this._clearSubscription = this._stateService.currentImage$.pipe(bufferCount(1, 10))
62948                 .subscribe((images) => {
62949                 this._stateService.clearPriorImages();
62950             });
62951             this._setPlaying(true);
62952             const currentLastImages$ = this._stateService.currentState$.pipe(map((frame) => {
62953                 return frame.state;
62954             }), distinctUntilChanged(([kc1, kl1], [kc2, kl2]) => {
62955                 return kc1 === kc2 && kl1 === kl2;
62956             }, (state) => {
62957                 return [state.currentImage.id, state.lastImage.id];
62958             }), filter((state) => {
62959                 return state.currentImage.id === state.lastImage.id &&
62960                     state.currentIndex === state.trajectory.length - 1;
62961             }), map((state) => {
62962                 return state.currentImage;
62963             }));
62964             this._stopSubscription = combineLatest(currentLastImages$, this._direction$).pipe(switchMap(([image, direction]) => {
62965                 const edgeStatus$ = ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
62966                     image.sequenceEdges$ :
62967                     image.spatialEdges$).pipe(first((status) => {
62968                     return status.cached;
62969                 }), timeout(15000), catchError((error) => {
62970                     console.error(error);
62971                     return of({ cached: false, edges: [] });
62972                 }));
62973                 return combineLatest(of(direction), edgeStatus$).pipe(map(([d, es]) => {
62974                     for (const edge of es.edges) {
62975                         if (edge.data.direction === d) {
62976                             return true;
62977                         }
62978                     }
62979                     return false;
62980                 }));
62981             }), mergeMap((hasEdge) => {
62982                 if (hasEdge || !this._bridging$) {
62983                     return of(hasEdge);
62984                 }
62985                 return this._bridging$.pipe(map((image) => {
62986                     return image != null;
62987                 }), catchError((error) => {
62988                     console.error(error);
62989                     return of(false);
62990                 }));
62991             }), first((hasEdge) => {
62992                 return !hasEdge;
62993             }))
62994                 .subscribe(undefined, undefined, () => { this.stop(); });
62995             if (this._stopSubscription.closed) {
62996                 this._stopSubscription = null;
62997             }
62998             this._earthSubscription = this._stateService.state$
62999                 .pipe(map((state) => {
63000                 return state === State.Earth;
63001             }), distinctUntilChanged(), first((earth) => {
63002                 return earth;
63003             }))
63004                 .subscribe(undefined, undefined, () => { this.stop(); });
63005             if (this._earthSubscription.closed) {
63006                 this._earthSubscription = null;
63007             }
63008         }
63009         dispose() {
63010             this.stop();
63011             this._subscriptions.unsubscribe();
63012         }
63013         setDirection(direction) {
63014             this._directionSubject$.next(direction);
63015         }
63016         setSpeed(speed) {
63017             speed = Math.max(0, Math.min(1, speed));
63018             if (speed === this._speed) {
63019                 return;
63020             }
63021             const stateSpeed = this._setSpeed(speed);
63022             if (this._playing) {
63023                 this._stateService.setSpeed(stateSpeed);
63024             }
63025             this._speedSubject$.next(this._speed);
63026         }
63027         stop() {
63028             if (!this._playing) {
63029                 return;
63030             }
63031             if (!!this._stopSubscription) {
63032                 if (!this._stopSubscription.closed) {
63033                     this._stopSubscription.unsubscribe();
63034                 }
63035                 this._stopSubscription = null;
63036             }
63037             if (!!this._earthSubscription) {
63038                 if (!this._earthSubscription.closed) {
63039                     this._earthSubscription.unsubscribe();
63040                 }
63041                 this._earthSubscription = null;
63042             }
63043             this._graphModeSubscription.unsubscribe();
63044             this._graphModeSubscription = null;
63045             this._cacheSubscription.unsubscribe();
63046             this._cacheSubscription = null;
63047             this._playingSubscription.unsubscribe();
63048             this._playingSubscription = null;
63049             this._clearSubscription.unsubscribe();
63050             this._clearSubscription = null;
63051             this._stateService.setSpeed(1);
63052             this._stateService.cutImages();
63053             this._graphService.setGraphMode(GraphMode.Spatial);
63054             this._setPlaying(false);
63055         }
63056         _mapSpeed(speed) {
63057             const x = 2 * speed - 1;
63058             return Math.pow(10, x) - 0.2 * x;
63059         }
63060         _mapImagesAhead(stateSpeed) {
63061             return Math.round(Math.max(10, Math.min(50, 8 + 6 * stateSpeed)));
63062         }
63063         _setPlaying(playing) {
63064             this._playing = playing;
63065             this._playingSubject$.next(playing);
63066         }
63067         _setSpeed(speed) {
63068             this._speed = speed;
63069             const stateSpeed = this._mapSpeed(this._speed);
63070             this._imagesAhead = this._mapImagesAhead(stateSpeed);
63071             return stateSpeed;
63072         }
63073     }
63074     PlayService.sequenceSpeed = 0.54;
63075
63076     exports.CameraVisualizationMode = void 0;
63077     (function (CameraVisualizationMode) {
63078         /**
63079          * Cameras are hidden.
63080          */
63081         CameraVisualizationMode[CameraVisualizationMode["Hidden"] = 0] = "Hidden";
63082         /**
63083          * Cameras are shown, all with the same color.
63084          */
63085         CameraVisualizationMode[CameraVisualizationMode["Homogeneous"] = 1] = "Homogeneous";
63086         /**
63087          * Cameras are shown with colors based on the
63088          * their clusters.
63089          */
63090         CameraVisualizationMode[CameraVisualizationMode["Cluster"] = 2] = "Cluster";
63091         /**
63092          * Cameras are shown with colors based on the
63093          * their connected components.
63094          */
63095         CameraVisualizationMode[CameraVisualizationMode["ConnectedComponent"] = 3] = "ConnectedComponent";
63096         /**
63097          * Cameras are shown, with colors based on the
63098          * their sequence.
63099          */
63100         CameraVisualizationMode[CameraVisualizationMode["Sequence"] = 4] = "Sequence";
63101     })(exports.CameraVisualizationMode || (exports.CameraVisualizationMode = {}));
63102
63103     exports.OriginalPositionMode = void 0;
63104     (function (OriginalPositionMode) {
63105         /**
63106          * Original positions are hidden.
63107          */
63108         OriginalPositionMode[OriginalPositionMode["Hidden"] = 0] = "Hidden";
63109         /**
63110          * Visualize original positions with altitude change.
63111          */
63112         OriginalPositionMode[OriginalPositionMode["Altitude"] = 1] = "Altitude";
63113         /**
63114          * Visualize original positions without altitude change,
63115          * i.e. as flat lines from the camera origin.
63116          */
63117         OriginalPositionMode[OriginalPositionMode["Flat"] = 2] = "Flat";
63118     })(exports.OriginalPositionMode || (exports.OriginalPositionMode = {}));
63119
63120     class ClusterPoints extends Points {
63121         constructor(parameters) {
63122             super();
63123             this._originalSize = parameters.originalSize;
63124             const cluster = parameters.cluster;
63125             const scale = parameters.scale;
63126             const translation = parameters.translation;
63127             this._makeAttributes(cluster);
63128             this.material.size = scale * this._originalSize;
63129             this.material.vertexColors = true;
63130             this.material.needsUpdate = true;
63131             this.matrixAutoUpdate = false;
63132             this.position.fromArray(translation);
63133             this.updateMatrix();
63134             this.updateMatrixWorld(false);
63135         }
63136         dispose() {
63137             this.geometry.dispose();
63138             this.material.dispose();
63139         }
63140         resize(scale) {
63141             this.material.size = scale * this._originalSize;
63142             this.material.needsUpdate = true;
63143         }
63144         _makeAttributes(cluster) {
63145             const positions = [];
63146             const colors = [];
63147             const points = cluster.points;
63148             for (const pointId in points) {
63149                 if (!points.hasOwnProperty(pointId)) {
63150                     continue;
63151                 }
63152                 const point = points[pointId];
63153                 positions.push(...point.coordinates);
63154                 const color = point.color;
63155                 colors.push(color[0]);
63156                 colors.push(color[1]);
63157                 colors.push(color[2]);
63158             }
63159             const geometry = this.geometry;
63160             geometry.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3));
63161             geometry.setAttribute("color", new BufferAttribute(new Float32Array(colors), 3));
63162         }
63163     }
63164
63165     class CellLine extends Line {
63166         constructor(vertices) {
63167             super();
63168             this._makeAttributes(vertices);
63169             this.matrixAutoUpdate = false;
63170             this.updateMatrix();
63171             this.updateMatrixWorld(false);
63172         }
63173         dispose() {
63174             this.geometry.dispose();
63175             this.material.dispose();
63176         }
63177         _makeAttributes(vertices) {
63178             const closedPolygon = vertices.slice();
63179             closedPolygon.push(vertices[0]);
63180             let index = 0;
63181             const positions = new Float32Array(3 * (vertices.length + 1));
63182             for (const vertex of closedPolygon) {
63183                 positions[index++] = vertex[0];
63184                 positions[index++] = vertex[1];
63185                 positions[index++] = vertex[2];
63186             }
63187             this.geometry.setAttribute("position", new BufferAttribute(positions, 3));
63188         }
63189     }
63190
63191     // Level 0: 1 x 1 x 1 meter cubes
63192     const OCTREE_ROOT_LEVEL = 14; // 16384 meters
63193     const OCTREE_LEAF_LEVEL = 6; // 64 meters
63194     function isLeafLevel(level, leafLevel) {
63195         return level === leafLevel;
63196     }
63197     function levelToSize(level) {
63198         return Math.pow(2, level);
63199     }
63200     function levelToRootBoundingBox(level) {
63201         const size = levelToSize(level);
63202         const half = size / 2;
63203         const min = [-half, -half, -half];
63204         const max = [half, half, half];
63205         return { min, max };
63206     }
63207
63208     class SpatialOctreeNode {
63209         constructor(level, leafLevel, boundingBox, parent) {
63210             this.level = level;
63211             this.leafLevel = leafLevel;
63212             this.boundingBox = boundingBox;
63213             this.parent = parent;
63214             this.children = [];
63215             this.items = [];
63216             if (parent) {
63217                 parent.children.push(this);
63218             }
63219         }
63220         get isEmpty() {
63221             return !(this.children.length || this.items.length);
63222         }
63223         add(object) {
63224             const self = this;
63225             if (!self.boundingBox.containsPoint(object.position)) {
63226                 throw new Error(`Item not contained in node`);
63227             }
63228             if (isLeafLevel(self.level, self.leafLevel)) {
63229                 self.items.push(object);
63230                 return this;
63231             }
63232             for (const child of self.children) {
63233                 if (child.boundingBox.containsPoint(object.position)) {
63234                     return child.add(object);
63235                 }
63236             }
63237             for (const boundingBox of self._generateBoundingBoxes()) {
63238                 if (boundingBox.containsPoint(object.position)) {
63239                     const child = new SpatialOctreeNode(self.level - 1, self.leafLevel, boundingBox, self);
63240                     return child.add(object);
63241                 }
63242             }
63243             throw new Error(`Item not contained in children`);
63244         }
63245         intersect(ray, target, nodes) {
63246             if (!ray.intersectBox(this.boundingBox, target)) {
63247                 return;
63248             }
63249             if (isLeafLevel(this.level, this.leafLevel)) {
63250                 nodes.push(this);
63251                 return;
63252             }
63253             for (const child of this.children) {
63254                 child.intersect(ray, target, nodes);
63255             }
63256         }
63257         remove(object) {
63258             const index = this.items.indexOf(object);
63259             if (index < 0) {
63260                 throw new Error(`Item does not exist ${object.uuid}`);
63261             }
63262             this.items.splice(index, 1);
63263         }
63264         traverse() {
63265             const self = this;
63266             if (!self.isEmpty) {
63267                 return;
63268             }
63269             const parent = self.parent;
63270             if (!parent) {
63271                 return;
63272             }
63273             const index = parent.children.indexOf(self);
63274             if (index < 0) {
63275                 throw new Error(`Corrupt octree`);
63276             }
63277             parent.children.splice(index, 1);
63278             this.parent = null;
63279             parent.traverse();
63280         }
63281         _generateBoundingBoxes() {
63282             const self = this;
63283             const min = self.boundingBox.min;
63284             const max = self.boundingBox.max;
63285             const size = (max.x - min.x) / 2;
63286             const mins = [
63287                 [min.x, min.y + size, min.z + size],
63288                 [min.x + size, min.y + size, min.z + size],
63289                 [min.x, min.y, min.z + size],
63290                 [min.x + size, min.y, min.z + size],
63291                 [min.x, min.y + size, min.z],
63292                 [min.x + size, min.y + size, min.z],
63293                 [min.x, min.y, min.z],
63294                 [min.x + size, min.y, min.z],
63295             ];
63296             const boundingBoxes = [];
63297             for (const [minX, minY, minZ] of mins) {
63298                 boundingBoxes.push(new Box3(new Vector3(minX, minY, minZ), new Vector3(minX + size, minY + size, minZ + size)));
63299             }
63300             return boundingBoxes;
63301         }
63302     }
63303
63304     class SpatialOctree {
63305         constructor(rootLevel, leafLevel) {
63306             this.rootLevel = rootLevel;
63307             this.leafLevel = leafLevel;
63308             if (leafLevel > rootLevel) {
63309                 throw new Error();
63310             }
63311             this._index = new Map();
63312             this._root = this._makeRoot();
63313         }
63314         get root() {
63315             return this._root;
63316         }
63317         add(object) {
63318             if (!this.root.boundingBox.containsPoint(object.position)) {
63319                 console.warn(`Object outside bounding box ${object.uuid}`);
63320                 return;
63321             }
63322             const leaf = this._root.add(object);
63323             this._index.set(object.uuid, leaf);
63324         }
63325         has(object) {
63326             return this._index.has(object.uuid);
63327         }
63328         intersect(ray) {
63329             const leaves = [];
63330             const target = new Vector3();
63331             this._root.intersect(ray, target, leaves);
63332             return leaves
63333                 .map(leaf => leaf.items)
63334                 .reduce((acc, items) => {
63335                 acc.push(...items);
63336                 return acc;
63337             }, []);
63338         }
63339         reset() {
63340             this._root = this._makeRoot();
63341             this._index.clear();
63342         }
63343         remove(object) {
63344             if (!this.has(object)) {
63345                 throw new Error(`Frame does not exist ${object.uuid}`);
63346             }
63347             const leaf = this._index.get(object.uuid);
63348             leaf.remove(object);
63349             leaf.traverse();
63350             this._index.delete(object.uuid);
63351         }
63352         _makeRoot() {
63353             const level = this.rootLevel;
63354             const bbox = levelToRootBoundingBox(level);
63355             const box = new Box3(new Vector3().fromArray(bbox.min), new Vector3().fromArray(bbox.max));
63356             return new SpatialOctreeNode(level, this.leafLevel, box);
63357         }
63358     }
63359
63360     class SpatialIntersection {
63361         constructor(octree, raycaster) {
63362             this._objects = [];
63363             this._objectImageMap = new Map();
63364             this._octree = octree !== null && octree !== void 0 ? octree : new SpatialOctree(OCTREE_ROOT_LEVEL, OCTREE_LEAF_LEVEL);
63365             this._raycaster = raycaster !== null && raycaster !== void 0 ? raycaster : new Raycaster();
63366             this._interactiveLayer = 1;
63367             this._raycaster = !!raycaster ?
63368                 raycaster :
63369                 new Raycaster(undefined, undefined, 1, 10000);
63370             this._lineThreshold = 0.2;
63371             this._largeLineThreshold = 0.4;
63372             this._raycaster.params.Line.threshold = this._lineThreshold;
63373             this._raycaster.layers.set(this._interactiveLayer);
63374         }
63375         get interactiveLayer() { return this._interactiveLayer; }
63376         get octree() { return this._octree; }
63377         get raycaster() { return this._raycaster; }
63378         add(object, imageId) {
63379             const uuid = object.uuid;
63380             this._objectImageMap.set(uuid, imageId);
63381             this._objects.push(object);
63382             this._octree.add(object);
63383         }
63384         intersectObjects(viewport, camera) {
63385             this._raycaster.setFromCamera(new Vector2().fromArray(viewport), camera);
63386             const objects = this._octree.intersect(this.raycaster.ray);
63387             const intersects = this._raycaster.intersectObjects(objects);
63388             const onMap = this._objectImageMap;
63389             for (const intersect of intersects) {
63390                 const uuid = intersect.object.uuid;
63391                 if (!onMap.has(uuid)) {
63392                     continue;
63393                 }
63394                 return onMap.get(uuid);
63395             }
63396             return null;
63397         }
63398         remove(object) {
63399             const objects = this._objects;
63400             const index = objects.indexOf(object);
63401             if (index !== -1) {
63402                 const deleted = objects.splice(index, 1);
63403                 for (const d of deleted) {
63404                     this._objectImageMap.delete(d.uuid);
63405                 }
63406                 this._octree.remove(object);
63407             }
63408             else {
63409                 console.warn(`Object does not exist`);
63410             }
63411         }
63412         resetIntersectionThreshold(useLarge) {
63413             this._raycaster.params.Line.threshold = useLarge ?
63414                 this._largeLineThreshold :
63415                 this._lineThreshold;
63416         }
63417     }
63418
63419     class PositionLine extends Line {
63420         constructor(parameters) {
63421             super(parameters.geometry, parameters.material);
63422             const mode = parameters.mode;
63423             const originalOrigin = parameters.originalOrigin;
63424             const transform = parameters.transform;
63425             const origin = transform.unprojectBasic([0, 0], 0);
63426             this._relativeAltitude = originalOrigin[2] - origin[2];
63427             this._makeAttributes(origin, originalOrigin, mode);
63428             this.matrixAutoUpdate = false;
63429             this.position.fromArray(origin);
63430             this.updateMatrix();
63431             this.updateMatrixWorld(false);
63432         }
63433         dispose() {
63434             this.geometry.dispose();
63435             this.material.dispose();
63436         }
63437         setMode(mode) {
63438             const positionAttribute = this.geometry.attributes.position;
63439             const positions = positionAttribute.array;
63440             positions[5] = this._modeToAltitude(mode);
63441             positionAttribute.needsUpdate = true;
63442             this.geometry.computeBoundingSphere();
63443         }
63444         _makeAttributes(origin, originalOrigin, mode) {
63445             const positions = new Float32Array(6);
63446             positions[0] = 0;
63447             positions[1] = 0;
63448             positions[2] = 0;
63449             positions[3] = originalOrigin[0] - origin[0];
63450             positions[4] = originalOrigin[1] - origin[1];
63451             positions[5] = this._modeToAltitude(mode);
63452             const attribute = new BufferAttribute(positions, 3);
63453             this.geometry.setAttribute("position", attribute);
63454             attribute.needsUpdate = true;
63455             this.geometry.computeBoundingSphere();
63456         }
63457         _modeToAltitude(mode) {
63458             return mode === exports.OriginalPositionMode.Altitude ?
63459                 this._relativeAltitude : 0;
63460         }
63461     }
63462
63463     class CameraFrameBase extends LineSegments {
63464         constructor(parameters) {
63465             super(parameters.geometry, parameters.material);
63466             const color = parameters.color;
63467             const size = parameters.size;
63468             const scale = parameters.scale;
63469             const transform = parameters.transform;
63470             const origin = transform.unprojectBasic([0, 0], 0);
63471             const positions = this._makePositions(size, transform, origin);
63472             this._makeAttributes(positions, color);
63473             this.geometry.computeBoundingSphere();
63474             this.geometry.computeBoundingBox();
63475             this.matrixAutoUpdate = false;
63476             this.position.fromArray(origin);
63477             this.scale.set(scale, scale, scale);
63478             this.updateMatrix();
63479             this.updateMatrixWorld(false);
63480         }
63481         dispose() {
63482             this.geometry.dispose();
63483             this.material.dispose();
63484         }
63485         setColor(color) {
63486             this._updateColorAttribute(color);
63487             return this;
63488         }
63489         resize(scale) {
63490             this.scale.set(scale, scale, scale);
63491             this.updateMatrix();
63492             this.updateMatrixWorld(false);
63493             return this;
63494         }
63495         _makeAttributes(positions, color) {
63496             const geometry = this.geometry;
63497             const positionAttribute = new BufferAttribute(new Float32Array(positions), 3);
63498             geometry.setAttribute("position", positionAttribute);
63499             positionAttribute.needsUpdate = true;
63500             const colorAttribute = new BufferAttribute(new Float32Array(positions.length), 3);
63501             geometry.setAttribute("color", colorAttribute);
63502             this._updateColorAttribute(color);
63503         }
63504         _updateColorAttribute(color) {
63505             const [r, g, b] = new Color(color).toArray();
63506             const colorAttribute = this.geometry.attributes.color;
63507             const colors = colorAttribute.array;
63508             const length = colors.length;
63509             let index = 0;
63510             for (let i = 0; i < length; i++) {
63511                 colors[index++] = r;
63512                 colors[index++] = g;
63513                 colors[index++] = b;
63514             }
63515             colorAttribute.needsUpdate = true;
63516         }
63517     }
63518
63519     class SphericalCameraFrame extends CameraFrameBase {
63520         _makePositions(size, transform, origin) {
63521             const vs = 10;
63522             const positions = [];
63523             positions.push(...this._makeAxis(size, transform, origin));
63524             positions.push(...this._makeLat(0.5, vs, size, transform, origin));
63525             for (const lat of [0, 0.25, 0.5, 0.75]) {
63526                 positions
63527                     .push(...this._makeLng(lat, vs, size, transform, origin));
63528             }
63529             return positions;
63530         }
63531         _makeAxis(size, transform, origin) {
63532             const south = transform.unprojectBasic([0.5, 1], 0.8 * size);
63533             const north = transform.unprojectBasic([0.5, 0], 1.2 * size);
63534             return [
63535                 south[0] - origin[0],
63536                 south[1] - origin[1],
63537                 south[2] - origin[2],
63538                 north[0] - origin[0],
63539                 north[1] - origin[1],
63540                 north[2] - origin[2],
63541             ];
63542         }
63543         _makeLat(basicY, numVertices, size, transform, origin) {
63544             const dist = 0.8 * size;
63545             const [originX, originY, originZ] = origin;
63546             const positions = [];
63547             const first = transform.unprojectBasic([0, basicY], dist);
63548             first[0] -= originX;
63549             first[1] -= originY;
63550             first[2] -= originZ;
63551             positions.push(...first);
63552             for (let i = 1; i <= numVertices; i++) {
63553                 const position = transform.unprojectBasic([i / numVertices, basicY], dist);
63554                 position[0] -= originX;
63555                 position[1] -= originY;
63556                 position[2] -= originZ;
63557                 positions.push(...position, ...position);
63558             }
63559             positions.push(...first);
63560             return positions;
63561         }
63562         _makeLng(basicX, numVertices, size, transform, origin) {
63563             const dist = 0.8 * size;
63564             const [originX, originY, originZ] = origin;
63565             const positions = [];
63566             const first = transform.unprojectBasic([basicX, 0], dist);
63567             first[0] -= originX;
63568             first[1] -= originY;
63569             first[2] -= originZ;
63570             positions.push(...first);
63571             for (let i = 0; i <= numVertices; i++) {
63572                 const position = transform.unprojectBasic([basicX, i / numVertices], dist);
63573                 position[0] -= originX;
63574                 position[1] -= originY;
63575                 position[2] -= originZ;
63576                 positions.push(...position, ...position);
63577             }
63578             positions.push(...first);
63579             return positions;
63580         }
63581     }
63582
63583     class PerspectiveCameraFrame extends CameraFrameBase {
63584         _makePositions(size, transform, origin) {
63585             const samples = 8;
63586             const positions = [];
63587             positions.push(...this._makeDiags(size, transform, origin));
63588             positions.push(...this._makeFrame(size, samples, transform, origin));
63589             return positions;
63590         }
63591         _makeDiags(size, transform, origin) {
63592             const depth = size;
63593             const [originX, originY, originZ] = origin;
63594             const cameraCenter = [0, 0, 0];
63595             const positions = [];
63596             for (const vertex2d of [[0, 0], [1, 0], [1, 1], [0, 1]]) {
63597                 const corner = transform.unprojectBasic(vertex2d, depth, true);
63598                 corner[0] -= originX;
63599                 corner[1] -= originY;
63600                 corner[2] -= originZ;
63601                 positions.push(...cameraCenter, ...corner);
63602             }
63603             return positions;
63604         }
63605         _makeFrame(size, samples, transform, origin) {
63606             const vertices2d = [];
63607             vertices2d.push(...this._subsample([0, 1], [0, 0], samples));
63608             vertices2d.push(...this._subsample([0, 0], [1, 0], samples));
63609             vertices2d.push(...this._subsample([1, 0], [1, 1], samples));
63610             const depth = size;
63611             const [originX, originY, originZ] = origin;
63612             const positions = [];
63613             for (const vertex2d of vertices2d) {
63614                 const position = transform.unprojectBasic(vertex2d, depth, true);
63615                 position[0] -= originX;
63616                 position[1] -= originY;
63617                 position[2] -= originZ;
63618                 positions.push(...position);
63619             }
63620             return positions;
63621         }
63622         _interpolate(a, b, alpha) {
63623             return a + alpha * (b - a);
63624         }
63625         _subsample(p1, p2, subsamples) {
63626             if (subsamples < 1) {
63627                 return [p1, p2];
63628             }
63629             const samples = [];
63630             samples.push(p1);
63631             for (let i = 0; i <= subsamples; i++) {
63632                 const p = [];
63633                 for (let j = 0; j < 3; j++) {
63634                     p.push(this._interpolate(p1[j], p2[j], i / (subsamples + 1)));
63635                 }
63636                 samples.push(p);
63637                 samples.push(p);
63638             }
63639             samples.push(p2);
63640             return samples;
63641         }
63642     }
63643
63644     class SpatialCell {
63645         constructor(id, _scene, _intersection) {
63646             this.id = id;
63647             this._scene = _scene;
63648             this._intersection = _intersection;
63649             this.cameras = new Object3D();
63650             this.keys = [];
63651             this._positionLines = {};
63652             this._positions = new Object3D();
63653             this._cameraFrames = {};
63654             this._clusters = new Map();
63655             this._connectedComponents = new Map();
63656             this._sequences = new Map();
63657             this._props = {};
63658             this.clusterVisibles = {};
63659             this._frameMaterial = new LineBasicMaterial({
63660                 fog: false,
63661                 vertexColors: true,
63662             });
63663             this._positionMaterial = new LineBasicMaterial({
63664                 fog: false,
63665                 color: 0xff0000,
63666             });
63667             this._scene.add(this.cameras, this._positions);
63668         }
63669         addImage(props) {
63670             const image = props.image;
63671             const id = image.id;
63672             if (this.hasImage(id)) {
63673                 throw new Error(`Image exists ${id}`);
63674             }
63675             const ccId = props.idMap.ccId;
63676             if (!(this._connectedComponents.has(ccId))) {
63677                 this._connectedComponents.set(ccId, []);
63678             }
63679             const cId = props.idMap.clusterId;
63680             if (!this._clusters.has(cId)) {
63681                 this._clusters.set(cId, []);
63682             }
63683             const sId = props.idMap.sequenceId;
63684             if (!this._sequences.has(sId)) {
63685                 this._sequences.set(sId, []);
63686             }
63687             this._props[id] = {
63688                 image: image,
63689                 ids: { ccId, clusterId: cId, sequenceId: sId },
63690             };
63691             this.keys.push(id);
63692         }
63693         applyCameraColor(imageId, color) {
63694             this._cameraFrames[imageId].setColor(color);
63695         }
63696         applyCameraSize(size) {
63697             for (const camera of this.cameras.children) {
63698                 camera.resize(size);
63699             }
63700         }
63701         applyFilter(filter) {
63702             var _a;
63703             const clusterVisibles = this.clusterVisibles;
63704             for (const clusterId in clusterVisibles) {
63705                 if (!clusterVisibles.hasOwnProperty(clusterId)) {
63706                     continue;
63707                 }
63708                 clusterVisibles[clusterId] = false;
63709             }
63710             const cameraFrames = this._cameraFrames;
63711             const positionLines = this._positionLines;
63712             const interactiveLayer = this._intersection.interactiveLayer;
63713             for (const props of Object.values(this._props)) {
63714                 const image = props.image;
63715                 const visible = filter(image);
63716                 const key = image.id;
63717                 positionLines[key].visible = visible;
63718                 const camera = cameraFrames[key];
63719                 this._setCameraVisibility(camera, visible, interactiveLayer);
63720                 clusterVisibles[_a = props.ids.clusterId] || (clusterVisibles[_a] = visible);
63721             }
63722         }
63723         applyPositionMode(mode) {
63724             this._positions.visible =
63725                 mode !== exports.OriginalPositionMode.Hidden;
63726             for (const position of this._positions.children) {
63727                 position.setMode(mode);
63728             }
63729         }
63730         dispose() {
63731             this._disposeCameras();
63732             this._disposePositions();
63733             this._scene = null;
63734             this._intersection = null;
63735         }
63736         getCamerasByMode(mode) {
63737             if (mode === exports.CameraVisualizationMode.Cluster) {
63738                 return this._clusters;
63739             }
63740             else if (mode === exports.CameraVisualizationMode.ConnectedComponent) {
63741                 return this._connectedComponents;
63742             }
63743             else if (mode === exports.CameraVisualizationMode.Sequence) {
63744                 return this._sequences;
63745             }
63746             const cvm = exports.CameraVisualizationMode;
63747             const defaultId = cvm[cvm.Homogeneous];
63748             const cameras = new Map();
63749             cameras.set(defaultId, this.cameras.children);
63750             return cameras;
63751         }
63752         getColorId(imageId, mode) {
63753             const props = this._props[imageId];
63754             const cvm = exports.CameraVisualizationMode;
63755             switch (mode) {
63756                 case cvm.Cluster:
63757                     return props.ids.clusterId;
63758                 case cvm.ConnectedComponent:
63759                     return props.ids.ccId;
63760                 case cvm.Sequence:
63761                     return props.ids.sequenceId;
63762                 default:
63763                     return cvm[cvm.Homogeneous];
63764             }
63765         }
63766         hasImage(key) {
63767             return this.keys.indexOf(key) !== -1;
63768         }
63769         visualize(props) {
63770             var _a, _b;
63771             const id = props.id;
63772             const visible = props.visible;
63773             const transform = props.transform;
63774             const cameraParameters = {
63775                 color: props.color,
63776                 material: this._frameMaterial,
63777                 scale: props.scale,
63778                 size: props.maxSize,
63779                 transform,
63780             };
63781             const camera = isSpherical(transform.cameraType) ?
63782                 new SphericalCameraFrame(cameraParameters) :
63783                 new PerspectiveCameraFrame(cameraParameters);
63784             const interactiveLayer = this._intersection.interactiveLayer;
63785             this._setCameraVisibility(camera, visible, interactiveLayer);
63786             this.cameras.add(camera);
63787             this._cameraFrames[id] = camera;
63788             const intersection = this._intersection;
63789             intersection.add(camera, id);
63790             const ids = this._props[id].ids;
63791             (_a = this.clusterVisibles)[_b = ids.clusterId] || (_a[_b] = visible);
63792             this._connectedComponents.get(ids.ccId).push(camera);
63793             this._clusters.get(ids.clusterId).push(camera);
63794             this._sequences.get(ids.sequenceId).push(camera);
63795             const positionParameters = {
63796                 material: this._positionMaterial,
63797                 mode: props.positionMode,
63798                 originalOrigin: props.originalPosition,
63799                 transform,
63800             };
63801             const position = new PositionLine(positionParameters);
63802             position.visible = visible;
63803             this._positions.add(position);
63804             this._positionLines[id] = position;
63805         }
63806         _disposeCameras() {
63807             const intersection = this._intersection;
63808             const cameras = this.cameras;
63809             for (const camera of cameras.children.slice()) {
63810                 camera.dispose();
63811                 intersection.remove(camera);
63812                 cameras.remove(camera);
63813             }
63814             this._scene.remove(this.cameras);
63815         }
63816         _disposePositions() {
63817             const positions = this._positions;
63818             for (const position of positions.children.slice()) {
63819                 position.dispose();
63820                 positions.remove(position);
63821             }
63822             this._scene.remove(this._positions);
63823         }
63824         _setCameraVisibility(camera, visible, layer) {
63825             camera.visible = visible;
63826             if (visible) {
63827                 camera.layers.enable(layer);
63828             }
63829             else {
63830                 camera.layers.disable(layer);
63831             }
63832         }
63833     }
63834
63835     class SpatialAssets {
63836         constructor() {
63837             this._colors = new Map();
63838             const cvm = exports.CameraVisualizationMode;
63839             this._colors.set(cvm[cvm.Homogeneous], "#FFFFFF");
63840         }
63841         getColor(id) {
63842             const colors = this._colors;
63843             if (!colors.has(id)) {
63844                 colors.set(id, this._randomColor());
63845             }
63846             return colors.get(id);
63847         }
63848         _randomColor() {
63849             return `hsl(${Math.floor(360 * Math.random())}, 100%, 50%)`;
63850         }
63851     }
63852
63853     function isModeVisible(mode) {
63854         return mode !== exports.CameraVisualizationMode.Hidden;
63855     }
63856     function isOverviewState(state) {
63857         return state === State.Custom || state === State.Earth;
63858     }
63859
63860     const NO_CLUSTER_ID = "NO_CLUSTER_ID";
63861     const NO_MERGE_ID = "NO_MERGE_ID";
63862     const NO_SEQUENCE_ID = "NO_SEQUENCE_ID";
63863     class SpatialScene {
63864         constructor(configuration, scene) {
63865             this._rayNearScale = 1.1;
63866             this._originalPointSize = 2;
63867             this._originalCameraSize = 2;
63868             this._imageCellMap = new Map();
63869             this._scene = !!scene ? scene : new Scene();
63870             this._scene.autoUpdate = false;
63871             this._intersection = new SpatialIntersection();
63872             this._assets = new SpatialAssets();
63873             this._needsRender = false;
63874             this._images = {};
63875             this._cells = {};
63876             this._cellClusters = {};
63877             this._clusters = {};
63878             this._cameraVisualizationMode =
63879                 !!configuration.cameraVisualizationMode ?
63880                     configuration.cameraVisualizationMode :
63881                     exports.CameraVisualizationMode.Homogeneous;
63882             this._cameraSize = configuration.cameraSize;
63883             this._pointSize = configuration.pointSize;
63884             this._pointsVisible = configuration.pointsVisible;
63885             this._positionMode = configuration.originalPositionMode;
63886             this._cellsVisible = configuration.cellsVisible;
63887             this._hoveredId = null;
63888             this._selectedId = null;
63889             this._colors = { hover: "#FF0000", select: "#FF8000" };
63890             this._filter = () => true;
63891         }
63892         get needsRender() { return this._needsRender; }
63893         get intersection() {
63894             return this._intersection;
63895         }
63896         addCluster(reconstruction, translation, cellId) {
63897             if (this.hasCluster(reconstruction.id, cellId)) {
63898                 return;
63899             }
63900             const clusterId = reconstruction.id;
63901             if (!(clusterId in this._clusters)) {
63902                 this._clusters[clusterId] = {
63903                     points: new Object3D(),
63904                     cellIds: [],
63905                 };
63906                 const visible = this._getClusterVisible(clusterId);
63907                 this._clusters[clusterId].points.visible = visible;
63908                 this._clusters[clusterId].points.add(new ClusterPoints({
63909                     cluster: reconstruction,
63910                     originalSize: this._originalPointSize,
63911                     scale: this._pointSize,
63912                     translation,
63913                 }));
63914                 this._scene.add(this._clusters[clusterId].points);
63915             }
63916             if (this._clusters[clusterId].cellIds.indexOf(cellId) === -1) {
63917                 this._clusters[clusterId].cellIds.push(cellId);
63918             }
63919             if (!(cellId in this._cellClusters)) {
63920                 this._cellClusters[cellId] = { keys: [] };
63921             }
63922             if (this._cellClusters[cellId].keys.indexOf(clusterId) === -1) {
63923                 this._cellClusters[cellId].keys.push(clusterId);
63924             }
63925             this._needsRender = true;
63926         }
63927         addImage(image, transform, originalPosition, cellId) {
63928             var _a, _b, _c;
63929             const imageId = image.id;
63930             const idMap = {
63931                 clusterId: (_a = image.clusterId) !== null && _a !== void 0 ? _a : NO_CLUSTER_ID,
63932                 sequenceId: (_b = image.sequenceId) !== null && _b !== void 0 ? _b : NO_SEQUENCE_ID,
63933                 ccId: (_c = image.mergeId) !== null && _c !== void 0 ? _c : NO_MERGE_ID,
63934             };
63935             if (!(cellId in this._images)) {
63936                 const created = new SpatialCell(cellId, this._scene, this._intersection);
63937                 created.cameras.visible =
63938                     isModeVisible(this._cameraVisualizationMode);
63939                 created.applyPositionMode(this._positionMode);
63940                 this._images[cellId] = created;
63941             }
63942             const cell = this._images[cellId];
63943             if (cell.hasImage(imageId)) {
63944                 return;
63945             }
63946             cell.addImage({ idMap, image: image });
63947             const colorId = cell.getColorId(imageId, this._cameraVisualizationMode);
63948             const color = this._assets.getColor(colorId);
63949             const visible = this._filter(image);
63950             cell.visualize({
63951                 id: imageId,
63952                 color,
63953                 positionMode: this._positionMode,
63954                 scale: this._cameraSize,
63955                 transform,
63956                 visible,
63957                 maxSize: this._originalCameraSize,
63958                 originalPosition
63959             });
63960             this._imageCellMap.set(imageId, cellId);
63961             if (imageId === this._selectedId) {
63962                 this._highlight(imageId, this._colors.select, this._cameraVisualizationMode);
63963             }
63964             if (idMap.clusterId in this._clusters) {
63965                 const clusterVisible = this._getClusterVisible(idMap.clusterId);
63966                 this._clusters[idMap.clusterId].points.visible = clusterVisible;
63967             }
63968             this._needsRender = true;
63969         }
63970         addCell(vertices, cellId) {
63971             if (this.hasCell(cellId)) {
63972                 return;
63973             }
63974             const cell = new CellLine(vertices);
63975             this._cells[cellId] = new Object3D();
63976             this._cells[cellId].visible = this._cellsVisible;
63977             this._cells[cellId].add(cell);
63978             this._scene.add(this._cells[cellId]);
63979             this._needsRender = true;
63980         }
63981         deactivate() {
63982             this._filter = () => true;
63983             this._selectedId = null;
63984             this._hoveredId = null;
63985             this.uncache();
63986         }
63987         hasCluster(clusterId, cellId) {
63988             return clusterId in this._clusters &&
63989                 this._clusters[clusterId].cellIds.indexOf(cellId) !== -1;
63990         }
63991         hasCell(cellId) {
63992             return cellId in this._cells;
63993         }
63994         hasImage(imageId, cellId) {
63995             return cellId in this._images &&
63996                 this._images[cellId].hasImage(imageId);
63997         }
63998         setCameraSize(cameraSize) {
63999             if (Math.abs(cameraSize - this._cameraSize) < 1e-3) {
64000                 return;
64001             }
64002             const imageCells = this._images;
64003             for (const cellId of Object.keys(imageCells)) {
64004                 imageCells[cellId].applyCameraSize(cameraSize);
64005             }
64006             this._intersection.raycaster.near = this._getNear(cameraSize);
64007             this._cameraSize = cameraSize;
64008             this._needsRender = true;
64009         }
64010         setFilter(filter) {
64011             this._filter = filter;
64012             const clusterVisibles = {};
64013             for (const imageCell of Object.values(this._images)) {
64014                 imageCell.applyFilter(filter);
64015                 const imageCV = imageCell.clusterVisibles;
64016                 for (const clusterId in imageCV) {
64017                     if (!imageCV.hasOwnProperty(clusterId)) {
64018                         continue;
64019                     }
64020                     if (!(clusterId in clusterVisibles)) {
64021                         clusterVisibles[clusterId] = false;
64022                     }
64023                     clusterVisibles[clusterId] || (clusterVisibles[clusterId] = imageCV[clusterId]);
64024                 }
64025             }
64026             const pointsVisible = this._pointsVisible;
64027             for (const clusterId in clusterVisibles) {
64028                 if (!clusterVisibles.hasOwnProperty(clusterId)) {
64029                     continue;
64030                 }
64031                 clusterVisibles[clusterId] && (clusterVisibles[clusterId] = pointsVisible);
64032                 const visible = clusterVisibles[clusterId];
64033                 if (clusterId in this._clusters) {
64034                     this._clusters[clusterId].points.visible = visible;
64035                 }
64036             }
64037             this._needsRender = true;
64038         }
64039         setHoveredImage(imageId) {
64040             if (imageId != null && !this._imageCellMap.has(imageId)) {
64041                 throw new MapillaryError(`Image does not exist: ${imageId}`);
64042             }
64043             if (this._hoveredId === imageId) {
64044                 return;
64045             }
64046             this._needsRender = true;
64047             if (this._hoveredId != null) {
64048                 if (this._hoveredId === this._selectedId) {
64049                     this._highlight(this._hoveredId, this._colors.select, this._cameraVisualizationMode);
64050                 }
64051                 else {
64052                     this._resetCameraColor(this._hoveredId);
64053                 }
64054             }
64055             this._highlight(imageId, this._colors.hover, this._cameraVisualizationMode);
64056             this._hoveredId = imageId;
64057         }
64058         setNavigationState(isOverview) {
64059             this._intersection.resetIntersectionThreshold(isOverview);
64060         }
64061         setPointSize(pointSize) {
64062             if (Math.abs(pointSize - this._pointSize) < 1e-3) {
64063                 return;
64064             }
64065             const clusters = this._clusters;
64066             for (const key in clusters) {
64067                 if (!clusters.hasOwnProperty(key)) {
64068                     continue;
64069                 }
64070                 for (const points of clusters[key].points.children) {
64071                     points.resize(pointSize);
64072                 }
64073             }
64074             this._pointSize = pointSize;
64075             this._needsRender = true;
64076         }
64077         setPointVisibility(visible) {
64078             if (visible === this._pointsVisible) {
64079                 return;
64080             }
64081             for (const clusterId in this._clusters) {
64082                 if (!this._clusters.hasOwnProperty(clusterId)) {
64083                     continue;
64084                 }
64085                 this._clusters[clusterId].points.visible = visible;
64086             }
64087             this._pointsVisible = visible;
64088             this._needsRender = true;
64089         }
64090         setPositionMode(mode) {
64091             if (mode === this._positionMode) {
64092                 return;
64093             }
64094             for (const cell of Object.values(this._images)) {
64095                 cell.applyPositionMode(mode);
64096             }
64097             this._positionMode = mode;
64098             this._needsRender = true;
64099         }
64100         setSelectedImage(id) {
64101             if (this._selectedId === id) {
64102                 return;
64103             }
64104             this._needsRender = true;
64105             if (this._selectedId != null) {
64106                 this._resetCameraColor(this._selectedId);
64107             }
64108             this._highlight(id, this._colors.select, this._cameraVisualizationMode);
64109             this._selectedId = id;
64110         }
64111         setCellVisibility(visible) {
64112             if (visible === this._cellsVisible) {
64113                 return;
64114             }
64115             for (const cellId in this._cells) {
64116                 if (!this._cells.hasOwnProperty(cellId)) {
64117                     continue;
64118                 }
64119                 this._cells[cellId].visible = visible;
64120             }
64121             this._cellsVisible = visible;
64122             this._needsRender = true;
64123         }
64124         setCameraVisualizationMode(mode) {
64125             if (mode === this._cameraVisualizationMode) {
64126                 return;
64127             }
64128             const visible = isModeVisible(mode);
64129             const assets = this._assets;
64130             for (const cell of Object.values(this._images)) {
64131                 cell.cameras.visible = visible;
64132                 const cameraMap = cell.getCamerasByMode(mode);
64133                 cameraMap.forEach((cameras, colorId) => {
64134                     const color = assets.getColor(colorId);
64135                     for (const camera of cameras) {
64136                         camera.setColor(color);
64137                     }
64138                 });
64139             }
64140             this._highlight(this._hoveredId, this._colors.hover, mode);
64141             this._highlight(this._selectedId, this._colors.select, mode);
64142             this._cameraVisualizationMode = mode;
64143             this._needsRender = true;
64144         }
64145         render(camera, renderer) {
64146             renderer.render(this._scene, camera);
64147             this._needsRender = false;
64148         }
64149         uncache(keepCellIds) {
64150             for (const cellId of Object.keys(this._cellClusters)) {
64151                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64152                     continue;
64153                 }
64154                 this._disposeReconstruction(cellId);
64155             }
64156             for (const cellId of Object.keys(this._images)) {
64157                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64158                     continue;
64159                 }
64160                 const nceMap = this._imageCellMap;
64161                 const keys = this._images[cellId].keys;
64162                 for (const key of keys) {
64163                     nceMap.delete(key);
64164                 }
64165                 this._images[cellId].dispose();
64166                 delete this._images[cellId];
64167             }
64168             for (const cellId of Object.keys(this._cells)) {
64169                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64170                     continue;
64171                 }
64172                 this._disposeCell(cellId);
64173             }
64174             this._needsRender = true;
64175         }
64176         _getClusterVisible(clusterId) {
64177             if (!this._pointsVisible) {
64178                 return false;
64179             }
64180             let visible = false;
64181             for (const imageCell of Object.values(this._images)) {
64182                 const imageCV = imageCell.clusterVisibles;
64183                 if (!(clusterId in imageCV)) {
64184                     continue;
64185                 }
64186                 visible || (visible = imageCV[clusterId]);
64187             }
64188             return visible;
64189         }
64190         _disposePoints(cellId) {
64191             for (const clusterId of this._cellClusters[cellId].keys) {
64192                 if (!(clusterId in this._clusters)) {
64193                     continue;
64194                 }
64195                 const index = this._clusters[clusterId].cellIds.indexOf(cellId);
64196                 if (index === -1) {
64197                     continue;
64198                 }
64199                 this._clusters[clusterId].cellIds.splice(index, 1);
64200                 if (this._clusters[clusterId].cellIds.length > 0) {
64201                     continue;
64202                 }
64203                 for (const points of this._clusters[clusterId].points.children.slice()) {
64204                     points.dispose();
64205                 }
64206                 this._scene.remove(this._clusters[clusterId].points);
64207                 delete this._clusters[clusterId];
64208             }
64209         }
64210         _disposeReconstruction(cellId) {
64211             this._disposePoints(cellId);
64212             delete this._cellClusters[cellId];
64213         }
64214         _disposeCell(cellId) {
64215             const cell = this._cells[cellId];
64216             for (const line of cell.children.slice()) {
64217                 line.dispose();
64218                 cell.remove(line);
64219             }
64220             this._scene.remove(cell);
64221             delete this._cells[cellId];
64222         }
64223         _getNear(cameraSize) {
64224             const near = this._rayNearScale *
64225                 this._originalCameraSize *
64226                 cameraSize;
64227             return Math.max(1, near);
64228         }
64229         _resetCameraColor(imageId) {
64230             const nceMap = this._imageCellMap;
64231             if (imageId == null || !nceMap.has(imageId)) {
64232                 return;
64233             }
64234             const cellId = nceMap.get(imageId);
64235             const cell = this._images[cellId];
64236             const colorId = cell.getColorId(imageId, this._cameraVisualizationMode);
64237             const color = this._assets.getColor(colorId);
64238             cell.applyCameraColor(imageId, color);
64239         }
64240         _highlight(imageId, color, mode) {
64241             const nceMap = this._imageCellMap;
64242             if (imageId == null || !nceMap.has(imageId)) {
64243                 return;
64244             }
64245             const cellId = nceMap.get(imageId);
64246             color = mode === exports.CameraVisualizationMode.Homogeneous ?
64247                 color : "#FFFFFF";
64248             this._images[cellId].applyCameraColor(imageId, color);
64249         }
64250     }
64251
64252     class SpatialCache {
64253         constructor(graphService, provider) {
64254             this._graphService = graphService;
64255             this._data = provider;
64256             this._cells = {};
64257             this._cacheRequests = {};
64258             this._clusters = {};
64259             this._clusterCells = {};
64260             this._cellClusters = {};
64261             this._cachingCells$ = {};
64262             this._cachingClusters$ = {};
64263         }
64264         cacheClusters$(cellId) {
64265             if (!this.hasCell(cellId)) {
64266                 throw new Error("Cannot cache reconstructions of a non-existing cell.");
64267             }
64268             if (this.hasClusters(cellId)) {
64269                 throw new Error("Cannot cache reconstructions that already exists.");
64270             }
64271             if (this.isCachingClusters(cellId)) {
64272                 return this._cachingClusters$[cellId];
64273             }
64274             const duplicatedClusters = this.getCell(cellId)
64275                 .filter((n) => {
64276                 return !!n.clusterId && !!n.clusterUrl;
64277             })
64278                 .map((n) => {
64279                 return { key: n.clusterId, url: n.clusterUrl };
64280             });
64281             const clusters = Array
64282                 .from(new Map(duplicatedClusters.map((cd) => {
64283                 return [cd.key, cd];
64284             }))
64285                 .values());
64286             this._cellClusters[cellId] = clusters;
64287             this._cacheRequests[cellId] = [];
64288             let aborter;
64289             const abort = new Promise((_, reject) => {
64290                 aborter = reject;
64291             });
64292             this._cacheRequests[cellId].push(aborter);
64293             this._cachingClusters$[cellId] =
64294                 this._cacheClusters$(clusters, cellId, abort).pipe(finalize(() => {
64295                     if (cellId in this._cachingClusters$) {
64296                         delete this._cachingClusters$[cellId];
64297                     }
64298                     if (cellId in this._cacheRequests) {
64299                         delete this._cacheRequests[cellId];
64300                     }
64301                 }), publish(), refCount());
64302             return this._cachingClusters$[cellId];
64303         }
64304         cacheCell$(cellId) {
64305             if (this.hasCell(cellId)) {
64306                 throw new Error("Cannot cache cell that already exists.");
64307             }
64308             if (this.isCachingCell(cellId)) {
64309                 return this._cachingCells$[cellId];
64310             }
64311             this._cachingCells$[cellId] = this._graphService.cacheCell$(cellId).pipe(catchError((error) => {
64312                 console.error(error);
64313                 return empty();
64314             }), filter(() => {
64315                 return !(cellId in this._cells);
64316             }), tap((images) => {
64317                 this._cells[cellId] = [];
64318                 this._cells[cellId].push(...images);
64319                 delete this._cachingCells$[cellId];
64320             }), finalize(() => {
64321                 if (cellId in this._cachingCells$) {
64322                     delete this._cachingCells$[cellId];
64323                 }
64324             }), publish(), refCount());
64325             return this._cachingCells$[cellId];
64326         }
64327         isCachingClusters(cellId) {
64328             return cellId in this._cachingClusters$;
64329         }
64330         isCachingCell(cellId) {
64331             return cellId in this._cachingCells$;
64332         }
64333         hasClusters(cellId) {
64334             if (cellId in this._cachingClusters$ ||
64335                 !(cellId in this._cellClusters)) {
64336                 return false;
64337             }
64338             for (const cd of this._cellClusters[cellId]) {
64339                 if (!(cd.key in this._clusters)) {
64340                     return false;
64341                 }
64342             }
64343             return true;
64344         }
64345         hasCell(cellId) {
64346             return !(cellId in this._cachingCells$) && cellId in this._cells;
64347         }
64348         getClusters(cellId) {
64349             return cellId in this._cellClusters ?
64350                 this._cellClusters[cellId]
64351                     .map((cd) => {
64352                     return this._clusters[cd.key];
64353                 })
64354                     .filter((reconstruction) => {
64355                     return !!reconstruction;
64356                 }) :
64357                 [];
64358         }
64359         getCell(cellId) {
64360             return cellId in this._cells ? this._cells[cellId] : [];
64361         }
64362         uncache(keepCellIds) {
64363             for (let cellId of Object.keys(this._cacheRequests)) {
64364                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64365                     continue;
64366                 }
64367                 for (const aborter of this._cacheRequests[cellId]) {
64368                     aborter();
64369                 }
64370                 delete this._cacheRequests[cellId];
64371             }
64372             for (let cellId of Object.keys(this._cellClusters)) {
64373                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64374                     continue;
64375                 }
64376                 for (const cd of this._cellClusters[cellId]) {
64377                     if (!(cd.key in this._clusterCells)) {
64378                         continue;
64379                     }
64380                     const index = this._clusterCells[cd.key].indexOf(cellId);
64381                     if (index === -1) {
64382                         continue;
64383                     }
64384                     this._clusterCells[cd.key].splice(index, 1);
64385                     if (this._clusterCells[cd.key].length > 0) {
64386                         continue;
64387                     }
64388                     delete this._clusterCells[cd.key];
64389                     delete this._clusters[cd.key];
64390                 }
64391                 delete this._cellClusters[cellId];
64392             }
64393             for (let cellId of Object.keys(this._cells)) {
64394                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
64395                     continue;
64396                 }
64397                 delete this._cells[cellId];
64398             }
64399         }
64400         updateCell$(cellId) {
64401             if (!this.hasCell(cellId)) {
64402                 throw new Error("Cannot update cell that does not exists.");
64403             }
64404             return this._graphService.cacheCell$(cellId).pipe(catchError((error) => {
64405                 console.error(error);
64406                 return empty();
64407             }), filter(() => {
64408                 return cellId in this._cells;
64409             }), tap((images) => {
64410                 this._cells[cellId] = [];
64411                 this._cells[cellId].push(...images);
64412             }), publish(), refCount());
64413         }
64414         updateClusters$(cellId) {
64415             if (!this.hasCell(cellId)) {
64416                 throw new Error("Cannot update reconstructions of a non-existing cell.");
64417             }
64418             if (!this.hasClusters(cellId)) {
64419                 throw new Error("Cannot update reconstructions for cell that is not cached.");
64420             }
64421             const duplicatedClusters = this.getCell(cellId)
64422                 .filter((n) => {
64423                 return !!n.clusterId && !!n.clusterUrl;
64424             })
64425                 .map((n) => {
64426                 return { key: n.clusterId, url: n.clusterUrl };
64427             });
64428             const clusters = Array
64429                 .from(new Map(duplicatedClusters.map((cd) => {
64430                 return [cd.key, cd];
64431             }))
64432                 .values())
64433                 .filter(cd => {
64434                 return !(cd.key in this._clusters);
64435             });
64436             this._cellClusters[cellId].push(...clusters);
64437             return this._cacheClusters$(clusters, cellId, null);
64438         }
64439         _cacheClusters$(clusters, cellId, cancellation) {
64440             return from(clusters).pipe(mergeMap((cd) => {
64441                 if (this._hasCluster(cd.key)) {
64442                     return of(this._getCluster(cd.key));
64443                 }
64444                 return this._getCluster$(cd.url, cd.key, cancellation)
64445                     .pipe(catchError((error) => {
64446                     if (error instanceof CancelMapillaryError) {
64447                         return empty();
64448                     }
64449                     console.error(error);
64450                     return empty();
64451                 }));
64452             }, 6), filter(() => {
64453                 return cellId in this._cellClusters;
64454             }), tap((reconstruction) => {
64455                 if (!this._hasCluster(reconstruction.id)) {
64456                     this._clusters[reconstruction.id] = reconstruction;
64457                 }
64458                 if (!(reconstruction.id in this._clusterCells)) {
64459                     this._clusterCells[reconstruction.id] = [];
64460                 }
64461                 if (this._clusterCells[reconstruction.id].indexOf(cellId) === -1) {
64462                     this._clusterCells[reconstruction.id].push(cellId);
64463                 }
64464             }));
64465         }
64466         _getCluster(id) {
64467             return this._clusters[id];
64468         }
64469         _getCluster$(url, clusterId, abort) {
64470             return Observable.create((subscriber) => {
64471                 this._data.getCluster(url, abort)
64472                     .then((reconstruction) => {
64473                     reconstruction.id = clusterId;
64474                     subscriber.next(reconstruction);
64475                     subscriber.complete();
64476                 }, (error) => {
64477                     subscriber.error(error);
64478                 });
64479             });
64480         }
64481         _hasCluster(id) {
64482             return id in this._clusters;
64483         }
64484     }
64485
64486     function connectedComponent(cellId, depth, geometry) {
64487         const cells = new Set();
64488         cells.add(cellId);
64489         connectedComponentRecursive(cells, [cellId], 0, depth, geometry);
64490         return Array.from(cells);
64491     }
64492     function connectedComponentRecursive(cells, current, currentDepth, maxDepth, geometry) {
64493         if (currentDepth >= maxDepth) {
64494             return;
64495         }
64496         const adjacent = [];
64497         for (const cellId of current) {
64498             const aCells = geometry.getAdjacent(cellId);
64499             adjacent.push(...aCells);
64500         }
64501         const newCells = [];
64502         for (const a of adjacent) {
64503             if (cells.has(a)) {
64504                 continue;
64505             }
64506             cells.add(a);
64507             newCells.push(a);
64508         }
64509         connectedComponentRecursive(cells, newCells, currentDepth + 1, maxDepth, geometry);
64510     }
64511
64512     class SpatialComponent extends Component {
64513         /** @ignore */
64514         constructor(name, container, navigator) {
64515             super(name, container, navigator);
64516             this._cache = new SpatialCache(navigator.graphService, navigator.api.data);
64517             this._scene = new SpatialScene(this._getDefaultConfiguration());
64518             this._viewportCoords = new ViewportCoords();
64519             this._spatial = new Spatial();
64520         }
64521         /**
64522          * Returns the image id of the camera frame closest to the current
64523          * render camera position at the specified point.
64524          *
64525          * @description Notice that the pixelPoint argument requires x, y
64526          * coordinates from pixel space.
64527          *
64528          * With this function, you can use the coordinates provided by mouse
64529          * events to get information out of the spatial component.
64530          *
64531          * If no camera frame exist at the pixel
64532          * point, `null` will be returned.
64533          *
64534          * @param {Array<number>} pixelPoint - Pixel coordinates on
64535          * the viewer element.
64536          * @returns {string} Image id of the camera frame closest to
64537          * the camera. If no camera frame is intersected at the
64538          * pixel point, `null` will be returned.
64539          *
64540          * @example
64541          * ```js
64542          * spatialComponent.getFrameIdAt([100, 125])
64543          *     .then((imageId) => { console.log(imageId); });
64544          * ```
64545          */
64546         getFrameIdAt(pixelPoint) {
64547             return new Promise((resolve, reject) => {
64548                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
64549                     const viewport = this._viewportCoords
64550                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
64551                     const id = this._scene.intersection
64552                         .intersectObjects(viewport, render.perspective);
64553                     return id;
64554                 }))
64555                     .subscribe((id) => {
64556                     resolve(id);
64557                 }, (error) => {
64558                     reject(error);
64559                 });
64560             });
64561         }
64562         _activate() {
64563             this._navigator.cacheService.configure({ cellDepth: 3 });
64564             const subs = this._subscriptions;
64565             subs.push(this._navigator.stateService.reference$
64566                 .subscribe(() => {
64567                 this._scene.uncache();
64568             }));
64569             subs.push(this._navigator.graphService.filter$
64570                 .subscribe(imageFilter => { this._scene.setFilter(imageFilter); }));
64571             const bearing$ = this._container.renderService.bearing$.pipe(map((bearing) => {
64572                 const interval = 6;
64573                 const discrete = interval * Math.floor(bearing / interval);
64574                 return discrete;
64575             }), distinctUntilChanged(), publishReplay(1), refCount());
64576             const cellId$ = this._navigator.stateService.currentImage$
64577                 .pipe(map((image) => {
64578                 return this._navigator.api.data.geometry
64579                     .lngLatToCellId(image.originalLngLat);
64580             }), distinctUntilChanged(), publishReplay(1), refCount());
64581             const cellGridDepth$ = this._configuration$
64582                 .pipe(map((c) => {
64583                 return this._spatial.clamp(c.cellGridDepth, 1, 3);
64584             }), distinctUntilChanged(), publishReplay(1), refCount());
64585             const sequencePlay$ = combineLatest(this._navigator.playService.playing$, this._navigator.playService.speed$).pipe(map(([playing, speed]) => {
64586                 return playing && speed > PlayService.sequenceSpeed;
64587             }), distinctUntilChanged(), publishReplay(1), refCount());
64588             const isOverview$ = this._navigator.stateService.state$.pipe(map((state) => {
64589                 return isOverviewState(state);
64590             }), distinctUntilChanged(), publishReplay(1), refCount());
64591             subs.push(isOverview$.subscribe((isOverview) => {
64592                 this._scene.setNavigationState(isOverview);
64593             }));
64594             const cell$ = combineLatest(isOverview$, sequencePlay$, bearing$, cellGridDepth$, this._navigator.stateService.currentImage$)
64595                 .pipe(distinctUntilChanged(([o1, s1, b1, d1, i1], [o2, s2, b2, d2, i2]) => {
64596                 if (o1 !== o2) {
64597                     return false;
64598                 }
64599                 const isd = i1.id === i2.id && s1 === s2 && d1 === d2;
64600                 if (o1) {
64601                     return isd;
64602                 }
64603                 return isd && b1 === b2;
64604             }), concatMap(([isOverview, sequencePlay, bearing, depth, image]) => {
64605                 if (isOverview) {
64606                     const geometry = this._navigator.api.data.geometry;
64607                     const cellId = geometry
64608                         .lngLatToCellId(image.originalLngLat);
64609                     const cells = sequencePlay ?
64610                         [cellId] :
64611                         connectedComponent(cellId, depth, geometry);
64612                     return of(cells);
64613                 }
64614                 const fov = sequencePlay ? 30 : 90;
64615                 return of(this._cellsInFov(image, bearing, fov));
64616             }), switchMap((cellIds) => {
64617                 return from(cellIds).pipe(mergeMap((cellId) => {
64618                     const t$ = this._cache.hasCell(cellId) ?
64619                         of(this._cache.getCell(cellId)) :
64620                         this._cache.cacheCell$(cellId);
64621                     return t$.pipe(map((images) => ({ id: cellId, images })));
64622                 }, 6));
64623             }));
64624             subs.push(cell$.pipe(withLatestFrom(this._navigator.stateService.reference$))
64625                 .subscribe(([cell, reference]) => {
64626                 if (this._scene.hasCell(cell.id)) {
64627                     return;
64628                 }
64629                 this._scene.addCell(this._cellToTopocentric(cell.id, reference), cell.id);
64630             }));
64631             subs.push(cell$.pipe(withLatestFrom(this._navigator.stateService.reference$))
64632                 .subscribe(([cell, reference]) => {
64633                 this._addSceneImages(cell, reference);
64634             }));
64635             subs.push(cell$.pipe(concatMap((cell) => {
64636                 const cellId = cell.id;
64637                 let reconstructions$;
64638                 if (this._cache.hasClusters(cellId)) {
64639                     reconstructions$ = from(this._cache.getClusters(cellId));
64640                 }
64641                 else if (this._cache.isCachingClusters(cellId)) {
64642                     reconstructions$ = this._cache.cacheClusters$(cellId).pipe(last(null, {}), switchMap(() => {
64643                         return from(this._cache.getClusters(cellId));
64644                     }));
64645                 }
64646                 else if (this._cache.hasCell(cellId)) {
64647                     reconstructions$ = this._cache.cacheClusters$(cellId);
64648                 }
64649                 else {
64650                     reconstructions$ = empty();
64651                 }
64652                 return combineLatest(of(cellId), reconstructions$);
64653             }), withLatestFrom(this._navigator.stateService.reference$))
64654                 .subscribe(([[cellId, reconstruction], reference]) => {
64655                 if (this._scene
64656                     .hasCluster(reconstruction.id, cellId)) {
64657                     return;
64658                 }
64659                 this._scene.addCluster(reconstruction, this._computeTranslation(reconstruction, reference), cellId);
64660             }));
64661             subs.push(this._configuration$.pipe(map((c) => {
64662                 c.cameraSize = this._spatial.clamp(c.cameraSize, 0.01, 1);
64663                 c.pointSize = this._spatial.clamp(c.pointSize, 0.01, 1);
64664                 return {
64665                     cameraSize: c.cameraSize,
64666                     cameraVisualizationMode: c.cameraVisualizationMode,
64667                     cellsVisible: c.cellsVisible,
64668                     originalPositionMode: c.originalPositionMode,
64669                     pointSize: c.pointSize,
64670                     pointsVisible: c.pointsVisible,
64671                 };
64672             }), distinctUntilChanged((c1, c2) => {
64673                 return c1.cameraSize === c2.cameraSize &&
64674                     c1.cameraVisualizationMode === c2.cameraVisualizationMode &&
64675                     c1.cellsVisible === c2.cellsVisible &&
64676                     c1.originalPositionMode === c2.originalPositionMode &&
64677                     c1.pointSize === c2.pointSize &&
64678                     c1.pointsVisible === c2.pointsVisible;
64679             }))
64680                 .subscribe((c) => {
64681                 this._scene.setCameraSize(c.cameraSize);
64682                 this._scene.setPointSize(c.pointSize);
64683                 this._scene.setPointVisibility(c.pointsVisible);
64684                 this._scene.setCellVisibility(c.cellsVisible);
64685                 const cvm = c.cameraVisualizationMode;
64686                 this._scene.setCameraVisualizationMode(cvm);
64687                 const opm = c.originalPositionMode;
64688                 this._scene.setPositionMode(opm);
64689             }));
64690             subs.push(combineLatest(cellId$, cellGridDepth$)
64691                 .subscribe(([cellId, depth]) => {
64692                 const keepCells = connectedComponent(cellId, depth, this._navigator.api.data.geometry);
64693                 this._scene.uncache(keepCells);
64694                 this._cache.uncache(keepCells);
64695             }));
64696             subs.push(this._navigator.playService.playing$.pipe(switchMap((playing) => {
64697                 return playing ?
64698                     empty() :
64699                     this._container.mouseService.dblClick$;
64700             }), withLatestFrom(this._container.renderService.renderCamera$), switchMap(([event, render]) => {
64701                 const element = this._container.container;
64702                 const [canvasX, canvasY] = this._viewportCoords
64703                     .canvasPosition(event, element);
64704                 const viewport = this._viewportCoords.canvasToViewport(canvasX, canvasY, element);
64705                 const id = this._scene.intersection
64706                     .intersectObjects(viewport, render.perspective);
64707                 return !!id ?
64708                     this._navigator.moveTo$(id).pipe(catchError(() => {
64709                         return empty();
64710                     })) :
64711                     empty();
64712             }))
64713                 .subscribe());
64714             const intersectChange$ = combineLatest(this._configuration$, this._navigator.stateService.state$).pipe(map(([c, state]) => {
64715                 c.cameraSize = this._spatial.clamp(c.cameraSize, 0.01, 1);
64716                 return {
64717                     size: c.cameraSize,
64718                     visible: isModeVisible(c.cameraVisualizationMode),
64719                     state,
64720                 };
64721             }), distinctUntilChanged((c1, c2) => {
64722                 return c1.size === c2.size &&
64723                     c1.visible === c2.visible &&
64724                     c1.state === c2.state;
64725             }));
64726             const mouseMove$ = this._container.mouseService.mouseMove$.pipe(publishReplay(1), refCount());
64727             subs.push(mouseMove$.subscribe());
64728             const mouseHover$ = merge(this._container.mouseService.mouseEnter$, this._container.mouseService.mouseLeave$, this._container.mouseService.windowBlur$);
64729             subs.push(combineLatest(this._navigator.playService.playing$, mouseHover$, isOverview$, this._navigator.graphService.filter$)
64730                 .pipe(switchMap(([playing, mouseHover]) => {
64731                 return !playing && mouseHover.type === "pointerenter" ?
64732                     combineLatest(concat(mouseMove$.pipe(take(1)), this._container.mouseService.mouseMove$), this._container.renderService.renderCamera$, intersectChange$) :
64733                     combineLatest(of(mouseHover), of(null), of(null));
64734             }))
64735                 .subscribe(([event, render]) => {
64736                 if (event.type !== "pointermove") {
64737                     this._scene.setHoveredImage(null);
64738                     return;
64739                 }
64740                 const element = this._container.container;
64741                 const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
64742                 const viewport = this._viewportCoords.canvasToViewport(canvasX, canvasY, element);
64743                 const key = this._scene.intersection
64744                     .intersectObjects(viewport, render.perspective);
64745                 this._scene.setHoveredImage(key);
64746             }));
64747             subs.push(this._navigator.stateService.currentId$
64748                 .subscribe((id) => {
64749                 this._scene.setSelectedImage(id);
64750             }));
64751             subs.push(this._navigator.stateService.currentState$
64752                 .pipe(map((frame) => {
64753                 const scene = this._scene;
64754                 return {
64755                     name: this._name,
64756                     renderer: {
64757                         frameId: frame.id,
64758                         needsRender: scene.needsRender,
64759                         render: scene.render.bind(scene),
64760                         pass: RenderPass.Opaque,
64761                     },
64762                 };
64763             }))
64764                 .subscribe(this._container.glRenderer.render$));
64765             const updatedCell$ = this._navigator.graphService.dataAdded$
64766                 .pipe(filter((cellId) => {
64767                 return this._cache.hasCell(cellId);
64768             }), mergeMap((cellId) => {
64769                 return this._cache.updateCell$(cellId).pipe(map((images) => ({ id: cellId, images })), withLatestFrom(this._navigator.stateService.reference$));
64770             }), publish(), refCount());
64771             subs.push(updatedCell$
64772                 .subscribe(([cell, reference]) => {
64773                 this._addSceneImages(cell, reference);
64774             }));
64775             subs.push(updatedCell$
64776                 .pipe(concatMap(([cell]) => {
64777                 const cellId = cell.id;
64778                 const cache = this._cache;
64779                 let reconstructions$;
64780                 if (cache.hasClusters(cellId)) {
64781                     reconstructions$ =
64782                         cache.updateClusters$(cellId);
64783                 }
64784                 else if (cache.isCachingClusters(cellId)) {
64785                     reconstructions$ = this._cache.cacheClusters$(cellId).pipe(last(null, {}), switchMap(() => {
64786                         return from(cache.updateClusters$(cellId));
64787                     }));
64788                 }
64789                 else {
64790                     reconstructions$ = empty();
64791                 }
64792                 return combineLatest(of(cellId), reconstructions$);
64793             }), withLatestFrom(this._navigator.stateService.reference$))
64794                 .subscribe(([[cellId, reconstruction], reference]) => {
64795                 if (this._scene.hasCluster(reconstruction.id, cellId)) {
64796                     return;
64797                 }
64798                 this._scene.addCluster(reconstruction, this._computeTranslation(reconstruction, reference), cellId);
64799             }));
64800         }
64801         _deactivate() {
64802             this._subscriptions.unsubscribe();
64803             this._cache.uncache();
64804             this._scene.deactivate();
64805             this._navigator.cacheService.configure();
64806         }
64807         _getDefaultConfiguration() {
64808             return {
64809                 cameraSize: 0.1,
64810                 cameraVisualizationMode: exports.CameraVisualizationMode.Homogeneous,
64811                 cellGridDepth: 1,
64812                 originalPositionMode: exports.OriginalPositionMode.Hidden,
64813                 pointSize: 0.1,
64814                 pointsVisible: true,
64815                 cellsVisible: false,
64816             };
64817         }
64818         _addSceneImages(cell, reference) {
64819             const cellId = cell.id;
64820             const images = cell.images;
64821             for (const image of images) {
64822                 if (this._scene.hasImage(image.id, cellId)) {
64823                     continue;
64824                 }
64825                 this._scene.addImage(image, this._createTransform(image, reference), this._computeOriginalPosition(image, reference), cellId);
64826             }
64827         }
64828         _cellsInFov(image, bearing, fov) {
64829             const spatial = this._spatial;
64830             const geometry = this._navigator.api.data.geometry;
64831             const cell = geometry.lngLatToCellId(image.originalLngLat);
64832             const cells = [cell];
64833             const threshold = fov / 2;
64834             const adjacent = geometry.getAdjacent(cell);
64835             for (const a of adjacent) {
64836                 const vertices = geometry.getVertices(a);
64837                 for (const vertex of vertices) {
64838                     const [x, y] = geodeticToEnu(vertex.lng, vertex.lat, 0, image.lngLat.lng, image.lngLat.lat, 0);
64839                     const azimuthal = Math.atan2(y, x);
64840                     const vertexBearing = spatial.radToDeg(spatial.azimuthalToBearing(azimuthal));
64841                     if (Math.abs(vertexBearing - bearing) < threshold) {
64842                         cells.push(a);
64843                     }
64844                 }
64845             }
64846             return cells;
64847         }
64848         _computeOriginalPosition(image, reference) {
64849             return geodeticToEnu(image.originalLngLat.lng, image.originalLngLat.lat, image.originalAltitude != null ? image.originalAltitude : image.computedAltitude, reference.lng, reference.lat, reference.alt);
64850         }
64851         _cellToTopocentric(cellId, reference) {
64852             const vertices = this._navigator.api.data.geometry
64853                 .getVertices(cellId)
64854                 .map((vertex) => {
64855                 return geodeticToEnu(vertex.lng, vertex.lat, -2, reference.lng, reference.lat, reference.alt);
64856             });
64857             return vertices;
64858         }
64859         _computeTranslation(reconstruction, reference) {
64860             return geodeticToEnu(reconstruction.reference.lng, reconstruction.reference.lat, reconstruction.reference.alt, reference.lng, reference.lat, reference.alt);
64861         }
64862         _createTransform(image, reference) {
64863             const translation = computeTranslation({ alt: image.computedAltitude, lat: image.lngLat.lat, lng: image.lngLat.lng }, image.rotation, reference);
64864             const transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, undefined, undefined, image.cameraParameters, image.cameraType);
64865             return transform;
64866         }
64867     }
64868     SpatialComponent.componentName = "spatial";
64869
64870     /**
64871      * @class Geometry
64872      * @abstract
64873      * @classdesc Represents a geometry.
64874      */
64875     class Geometry {
64876         /**
64877          * Create a geometry.
64878          *
64879          * @constructor
64880          * @ignore
64881          */
64882         constructor() {
64883             this._notifyChanged$ = new Subject();
64884         }
64885         /**
64886          * Get changed observable.
64887          *
64888          * @description Emits the geometry itself every time the geometry
64889          * has changed.
64890          *
64891          * @returns {Observable<Geometry>} Observable emitting the geometry instance.
64892          * @ignore
64893          */
64894         get changed$() {
64895             return this._notifyChanged$;
64896         }
64897     }
64898
64899     class GeometryTagError extends MapillaryError {
64900         constructor(message) {
64901             super(message != null ? message : "The provided geometry value is incorrect");
64902             Object.setPrototypeOf(this, GeometryTagError.prototype);
64903             this.name = "GeometryTagError";
64904         }
64905     }
64906
64907     /**
64908      * @class PointsGeometry
64909      *
64910      * @classdesc Represents a point set in the 2D basic image coordinate system.
64911      *
64912      * @example
64913      * ```js
64914      * var points = [[0.5, 0.3], [0.7, 0.3], [0.6, 0.5]];
64915      * var pointsGeometry = new PointsGeometry(points);
64916      * ```
64917      */
64918     class PointsGeometry extends Geometry {
64919         /**
64920          * Create a points geometry.
64921          *
64922          * @constructor
64923          * @param {Array<Array<number>>} points - Array of 2D points on the basic coordinate
64924          * system. The number of points must be greater than or equal to two.
64925          *
64926          * @throws {GeometryTagError} Point coordinates must be valid basic coordinates.
64927          */
64928         constructor(points) {
64929             super();
64930             const pointsLength = points.length;
64931             if (pointsLength < 2) {
64932                 throw new GeometryTagError("A points geometry must have two or more positions.");
64933             }
64934             this._points = [];
64935             for (const point of points) {
64936                 if (point[0] < 0 || point[0] > 1 ||
64937                     point[1] < 0 || point[1] > 1) {
64938                     throw new GeometryTagError("Basic coordinates of points must be on the interval [0, 1].");
64939                 }
64940                 this._points.push(point.slice());
64941             }
64942         }
64943         /**
64944          * Get points property.
64945          * @returns {Array<Array<number>>} Array of 2d points.
64946          */
64947         get points() {
64948             return this._points;
64949         }
64950         /**
64951          * Add a point to the point set.
64952          *
64953          * @param {Array<number>} point - Point to add.
64954          * @ignore
64955          */
64956         addPoint2d(point) {
64957             const clamped = [
64958                 Math.max(0, Math.min(1, point[0])),
64959                 Math.max(0, Math.min(1, point[1])),
64960             ];
64961             this._points.push(clamped);
64962             this._notifyChanged$.next(this);
64963         }
64964         /**
64965          * Get the coordinates of a point from the point set representation of the geometry.
64966          *
64967          * @param {number} index - Point index.
64968          * @returns {Array<number>} Array representing the 2D basic coordinates of the point.
64969          * @ignore
64970          */
64971         getPoint2d(index) {
64972             return this._points[index].slice();
64973         }
64974         /**
64975          * Remove a point from the point set.
64976          *
64977          * @param {number} index - The index of the point to remove.
64978          * @ignore
64979          */
64980         removePoint2d(index) {
64981             if (index < 0 ||
64982                 index >= this._points.length ||
64983                 this._points.length < 3) {
64984                 throw new GeometryTagError("Index for removed point must be valid.");
64985             }
64986             this._points.splice(index, 1);
64987             this._notifyChanged$.next(this);
64988         }
64989         /** @ignore */
64990         setVertex2d(index, value, transform) {
64991             this.setPoint2d(index, value, transform);
64992         }
64993         /** @ignore */
64994         setPoint2d(index, value, transform) {
64995             const changed = [
64996                 Math.max(0, Math.min(1, value[0])),
64997                 Math.max(0, Math.min(1, value[1])),
64998             ];
64999             this._points[index] = changed;
65000             this._notifyChanged$.next(this);
65001         }
65002         /** @ignore */
65003         getPoints3d(transform) {
65004             return this._getPoints3d(this._points, transform);
65005         }
65006         /** @ignore */
65007         getPoint3d(index, transform) {
65008             return transform.unprojectBasic(this._points[index], 200);
65009         }
65010         /** @ignore */
65011         getPoints2d() {
65012             return this._points.slice();
65013         }
65014         /** @ignore */
65015         getCentroid2d(transform) {
65016             if (!transform) {
65017                 throw new GeometryTagError("Get centroid must be called with a transform for points geometries.");
65018             }
65019             const [minX, minY, maxX, maxY] = this.getRect2d(transform);
65020             const centroidX = minX < maxX ?
65021                 (minX + maxX) / 2 :
65022                 ((minX + maxX + 1) / 2) % 1;
65023             const centroidY = (minY + maxY) / 2;
65024             return [centroidX, centroidY];
65025         }
65026         /** @ignore */
65027         getCentroid3d(transform) {
65028             let centroid2d = this.getCentroid2d();
65029             return transform.unprojectBasic(centroid2d, 200);
65030         }
65031         /** @ignore */
65032         getRect2d(transform) {
65033             let minX = 1;
65034             let maxX = 0;
65035             let minY = 1;
65036             let maxY = 0;
65037             const points = this._points;
65038             for (const point of points) {
65039                 if (point[0] < minX) {
65040                     minX = point[0];
65041                 }
65042                 if (point[0] > maxX) {
65043                     maxX = point[0];
65044                 }
65045                 if (point[1] < minY) {
65046                     minY = point[1];
65047                 }
65048                 if (point[1] > maxY) {
65049                     maxY = point[1];
65050                 }
65051             }
65052             if (isSpherical(transform.cameraType)) {
65053                 const indices = [];
65054                 for (let i = 0; i < points.length; i++) {
65055                     indices[i] = i;
65056                 }
65057                 indices.sort((a, b) => {
65058                     return points[a][0] < points[b][0] ?
65059                         -1 :
65060                         points[a][0] > points[b][0] ?
65061                             1 :
65062                             a < b ? -1 : 1;
65063                 });
65064                 let maxDistanceX = points[indices[0]][0] + 1 - points[indices[indices.length - 1]][0];
65065                 let leftMostIndex = 0;
65066                 for (let i = 0; i < indices.length - 1; i++) {
65067                     const index1 = indices[i];
65068                     const index2 = indices[i + 1];
65069                     const distanceX = points[index2][0] - points[index1][0];
65070                     if (distanceX > maxDistanceX) {
65071                         maxDistanceX = distanceX;
65072                         leftMostIndex = i + 1;
65073                     }
65074                 }
65075                 if (leftMostIndex > 0) {
65076                     minX = points[indices[leftMostIndex]][0];
65077                     maxX = points[indices[leftMostIndex - 1]][0];
65078                 }
65079             }
65080             return [minX, minY, maxX, maxY];
65081         }
65082         /** @ignore */
65083         setCentroid2d(value, transform) {
65084             throw new Error("Not implemented");
65085         }
65086         _getPoints3d(points2d, transform) {
65087             return points2d
65088                 .map((point) => {
65089                 return transform.unprojectBasic(point, 200);
65090             });
65091         }
65092     }
65093
65094     class CreateTag {
65095         constructor(geometry, transform, viewportCoords) {
65096             this._geometry = geometry;
65097             this._transform = transform;
65098             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
65099             this._aborted$ = new Subject();
65100             this._created$ = new Subject();
65101             this._glObjectsChanged$ = new Subject();
65102             this._geometryChangedSubscription = this._geometry.changed$
65103                 .subscribe(() => {
65104                 this._onGeometryChanged();
65105                 this._glObjectsChanged$.next(this);
65106             });
65107         }
65108         get geometry() {
65109             return this._geometry;
65110         }
65111         get glObjects() {
65112             return this._glObjects;
65113         }
65114         get aborted$() {
65115             return this._aborted$;
65116         }
65117         get created$() {
65118             return this._created$;
65119         }
65120         get glObjectsChanged$() {
65121             return this._glObjectsChanged$;
65122         }
65123         get geometryChanged$() {
65124             return this._geometry.changed$.pipe(map(() => {
65125                 return this;
65126             }));
65127         }
65128         dispose() {
65129             this._geometryChangedSubscription.unsubscribe();
65130         }
65131         _canvasToTransform(canvas) {
65132             const canvasX = Math.round(canvas[0]);
65133             const canvasY = Math.round(canvas[1]);
65134             const transform = `translate(-50%,-50%) translate(${canvasX}px,${canvasY}px)`;
65135             return transform;
65136         }
65137         _colorToBackground(color) {
65138             return "#" + ("000000" + color.toString(16)).substr(-6);
65139         }
65140         _createOutine(polygon3d, color) {
65141             const positions = this._getLinePositions(polygon3d);
65142             const geometry = new BufferGeometry();
65143             geometry.setAttribute("position", new BufferAttribute(positions, 3));
65144             const material = new LineBasicMaterial({
65145                 color: color,
65146                 linewidth: 1,
65147             });
65148             return new Line(geometry, material);
65149         }
65150         _disposeLine(line) {
65151             if (line == null) {
65152                 return;
65153             }
65154             line.geometry.dispose();
65155             line.material.dispose();
65156         }
65157         _getLinePositions(polygon3d) {
65158             const length = polygon3d.length;
65159             const positions = new Float32Array(length * 3);
65160             for (let i = 0; i < length; ++i) {
65161                 const index = 3 * i;
65162                 const position = polygon3d[i];
65163                 positions[index] = position[0];
65164                 positions[index + 1] = position[1];
65165                 positions[index + 2] = position[2];
65166             }
65167             return positions;
65168         }
65169     }
65170
65171     var earcut_1 = earcut;
65172     var _default$2 = earcut;
65173
65174     function earcut(data, holeIndices, dim) {
65175
65176         dim = dim || 2;
65177
65178         var hasHoles = holeIndices && holeIndices.length,
65179             outerLen = hasHoles ? holeIndices[0] * dim : data.length,
65180             outerNode = linkedList(data, 0, outerLen, dim, true),
65181             triangles = [];
65182
65183         if (!outerNode || outerNode.next === outerNode.prev) return triangles;
65184
65185         var minX, minY, maxX, maxY, x, y, invSize;
65186
65187         if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
65188
65189         // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
65190         if (data.length > 80 * dim) {
65191             minX = maxX = data[0];
65192             minY = maxY = data[1];
65193
65194             for (var i = dim; i < outerLen; i += dim) {
65195                 x = data[i];
65196                 y = data[i + 1];
65197                 if (x < minX) minX = x;
65198                 if (y < minY) minY = y;
65199                 if (x > maxX) maxX = x;
65200                 if (y > maxY) maxY = y;
65201             }
65202
65203             // minX, minY and invSize are later used to transform coords into integers for z-order calculation
65204             invSize = Math.max(maxX - minX, maxY - minY);
65205             invSize = invSize !== 0 ? 1 / invSize : 0;
65206         }
65207
65208         earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
65209
65210         return triangles;
65211     }
65212
65213     // create a circular doubly linked list from polygon points in the specified winding order
65214     function linkedList(data, start, end, dim, clockwise) {
65215         var i, last;
65216
65217         if (clockwise === (signedArea$1(data, start, end, dim) > 0)) {
65218             for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
65219         } else {
65220             for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
65221         }
65222
65223         if (last && equals$1(last, last.next)) {
65224             removeNode(last);
65225             last = last.next;
65226         }
65227
65228         return last;
65229     }
65230
65231     // eliminate colinear or duplicate points
65232     function filterPoints(start, end) {
65233         if (!start) return start;
65234         if (!end) end = start;
65235
65236         var p = start,
65237             again;
65238         do {
65239             again = false;
65240
65241             if (!p.steiner && (equals$1(p, p.next) || area(p.prev, p, p.next) === 0)) {
65242                 removeNode(p);
65243                 p = end = p.prev;
65244                 if (p === p.next) break;
65245                 again = true;
65246
65247             } else {
65248                 p = p.next;
65249             }
65250         } while (again || p !== end);
65251
65252         return end;
65253     }
65254
65255     // main ear slicing loop which triangulates a polygon (given as a linked list)
65256     function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
65257         if (!ear) return;
65258
65259         // interlink polygon nodes in z-order
65260         if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
65261
65262         var stop = ear,
65263             prev, next;
65264
65265         // iterate through ears, slicing them one by one
65266         while (ear.prev !== ear.next) {
65267             prev = ear.prev;
65268             next = ear.next;
65269
65270             if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
65271                 // cut off the triangle
65272                 triangles.push(prev.i / dim);
65273                 triangles.push(ear.i / dim);
65274                 triangles.push(next.i / dim);
65275
65276                 removeNode(ear);
65277
65278                 // skipping the next vertex leads to less sliver triangles
65279                 ear = next.next;
65280                 stop = next.next;
65281
65282                 continue;
65283             }
65284
65285             ear = next;
65286
65287             // if we looped through the whole remaining polygon and can't find any more ears
65288             if (ear === stop) {
65289                 // try filtering points and slicing again
65290                 if (!pass) {
65291                     earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
65292
65293                 // if this didn't work, try curing all small self-intersections locally
65294                 } else if (pass === 1) {
65295                     ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
65296                     earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
65297
65298                 // as a last resort, try splitting the remaining polygon into two
65299                 } else if (pass === 2) {
65300                     splitEarcut(ear, triangles, dim, minX, minY, invSize);
65301                 }
65302
65303                 break;
65304             }
65305         }
65306     }
65307
65308     // check whether a polygon node forms a valid ear with adjacent nodes
65309     function isEar(ear) {
65310         var a = ear.prev,
65311             b = ear,
65312             c = ear.next;
65313
65314         if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
65315
65316         // now make sure we don't have other points inside the potential ear
65317         var p = ear.next.next;
65318
65319         while (p !== ear.prev) {
65320             if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
65321                 area(p.prev, p, p.next) >= 0) return false;
65322             p = p.next;
65323         }
65324
65325         return true;
65326     }
65327
65328     function isEarHashed(ear, minX, minY, invSize) {
65329         var a = ear.prev,
65330             b = ear,
65331             c = ear.next;
65332
65333         if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
65334
65335         // triangle bbox; min & max are calculated like this for speed
65336         var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),
65337             minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),
65338             maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),
65339             maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
65340
65341         // z-order range for the current triangle bbox;
65342         var minZ = zOrder(minTX, minTY, minX, minY, invSize),
65343             maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
65344
65345         var p = ear.prevZ,
65346             n = ear.nextZ;
65347
65348         // look for points inside the triangle in both directions
65349         while (p && p.z >= minZ && n && n.z <= maxZ) {
65350             if (p !== ear.prev && p !== ear.next &&
65351                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
65352                 area(p.prev, p, p.next) >= 0) return false;
65353             p = p.prevZ;
65354
65355             if (n !== ear.prev && n !== ear.next &&
65356                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
65357                 area(n.prev, n, n.next) >= 0) return false;
65358             n = n.nextZ;
65359         }
65360
65361         // look for remaining points in decreasing z-order
65362         while (p && p.z >= minZ) {
65363             if (p !== ear.prev && p !== ear.next &&
65364                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
65365                 area(p.prev, p, p.next) >= 0) return false;
65366             p = p.prevZ;
65367         }
65368
65369         // look for remaining points in increasing z-order
65370         while (n && n.z <= maxZ) {
65371             if (n !== ear.prev && n !== ear.next &&
65372                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
65373                 area(n.prev, n, n.next) >= 0) return false;
65374             n = n.nextZ;
65375         }
65376
65377         return true;
65378     }
65379
65380     // go through all polygon nodes and cure small local self-intersections
65381     function cureLocalIntersections(start, triangles, dim) {
65382         var p = start;
65383         do {
65384             var a = p.prev,
65385                 b = p.next.next;
65386
65387             if (!equals$1(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
65388
65389                 triangles.push(a.i / dim);
65390                 triangles.push(p.i / dim);
65391                 triangles.push(b.i / dim);
65392
65393                 // remove two nodes involved
65394                 removeNode(p);
65395                 removeNode(p.next);
65396
65397                 p = start = b;
65398             }
65399             p = p.next;
65400         } while (p !== start);
65401
65402         return filterPoints(p);
65403     }
65404
65405     // try splitting polygon into two and triangulate them independently
65406     function splitEarcut(start, triangles, dim, minX, minY, invSize) {
65407         // look for a valid diagonal that divides the polygon into two
65408         var a = start;
65409         do {
65410             var b = a.next.next;
65411             while (b !== a.prev) {
65412                 if (a.i !== b.i && isValidDiagonal(a, b)) {
65413                     // split the polygon in two by the diagonal
65414                     var c = splitPolygon(a, b);
65415
65416                     // filter colinear points around the cuts
65417                     a = filterPoints(a, a.next);
65418                     c = filterPoints(c, c.next);
65419
65420                     // run earcut on each half
65421                     earcutLinked(a, triangles, dim, minX, minY, invSize);
65422                     earcutLinked(c, triangles, dim, minX, minY, invSize);
65423                     return;
65424                 }
65425                 b = b.next;
65426             }
65427             a = a.next;
65428         } while (a !== start);
65429     }
65430
65431     // link every hole into the outer loop, producing a single-ring polygon without holes
65432     function eliminateHoles(data, holeIndices, outerNode, dim) {
65433         var queue = [],
65434             i, len, start, end, list;
65435
65436         for (i = 0, len = holeIndices.length; i < len; i++) {
65437             start = holeIndices[i] * dim;
65438             end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
65439             list = linkedList(data, start, end, dim, false);
65440             if (list === list.next) list.steiner = true;
65441             queue.push(getLeftmost(list));
65442         }
65443
65444         queue.sort(compareX);
65445
65446         // process holes from left to right
65447         for (i = 0; i < queue.length; i++) {
65448             eliminateHole(queue[i], outerNode);
65449             outerNode = filterPoints(outerNode, outerNode.next);
65450         }
65451
65452         return outerNode;
65453     }
65454
65455     function compareX(a, b) {
65456         return a.x - b.x;
65457     }
65458
65459     // find a bridge between vertices that connects hole with an outer ring and and link it
65460     function eliminateHole(hole, outerNode) {
65461         outerNode = findHoleBridge(hole, outerNode);
65462         if (outerNode) {
65463             var b = splitPolygon(outerNode, hole);
65464
65465             // filter collinear points around the cuts
65466             filterPoints(outerNode, outerNode.next);
65467             filterPoints(b, b.next);
65468         }
65469     }
65470
65471     // David Eberly's algorithm for finding a bridge between hole and outer polygon
65472     function findHoleBridge(hole, outerNode) {
65473         var p = outerNode,
65474             hx = hole.x,
65475             hy = hole.y,
65476             qx = -Infinity,
65477             m;
65478
65479         // find a segment intersected by a ray from the hole's leftmost point to the left;
65480         // segment's endpoint with lesser x will be potential connection point
65481         do {
65482             if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
65483                 var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
65484                 if (x <= hx && x > qx) {
65485                     qx = x;
65486                     if (x === hx) {
65487                         if (hy === p.y) return p;
65488                         if (hy === p.next.y) return p.next;
65489                     }
65490                     m = p.x < p.next.x ? p : p.next;
65491                 }
65492             }
65493             p = p.next;
65494         } while (p !== outerNode);
65495
65496         if (!m) return null;
65497
65498         if (hx === qx) return m; // hole touches outer segment; pick leftmost endpoint
65499
65500         // look for points inside the triangle of hole point, segment intersection and endpoint;
65501         // if there are no points found, we have a valid connection;
65502         // otherwise choose the point of the minimum angle with the ray as connection point
65503
65504         var stop = m,
65505             mx = m.x,
65506             my = m.y,
65507             tanMin = Infinity,
65508             tan;
65509
65510         p = m;
65511
65512         do {
65513             if (hx >= p.x && p.x >= mx && hx !== p.x &&
65514                     pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
65515
65516                 tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
65517
65518                 if (locallyInside(p, hole) &&
65519                     (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
65520                     m = p;
65521                     tanMin = tan;
65522                 }
65523             }
65524
65525             p = p.next;
65526         } while (p !== stop);
65527
65528         return m;
65529     }
65530
65531     // whether sector in vertex m contains sector in vertex p in the same coordinates
65532     function sectorContainsSector(m, p) {
65533         return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
65534     }
65535
65536     // interlink polygon nodes in z-order
65537     function indexCurve(start, minX, minY, invSize) {
65538         var p = start;
65539         do {
65540             if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize);
65541             p.prevZ = p.prev;
65542             p.nextZ = p.next;
65543             p = p.next;
65544         } while (p !== start);
65545
65546         p.prevZ.nextZ = null;
65547         p.prevZ = null;
65548
65549         sortLinked(p);
65550     }
65551
65552     // Simon Tatham's linked list merge sort algorithm
65553     // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
65554     function sortLinked(list) {
65555         var i, p, q, e, tail, numMerges, pSize, qSize,
65556             inSize = 1;
65557
65558         do {
65559             p = list;
65560             list = null;
65561             tail = null;
65562             numMerges = 0;
65563
65564             while (p) {
65565                 numMerges++;
65566                 q = p;
65567                 pSize = 0;
65568                 for (i = 0; i < inSize; i++) {
65569                     pSize++;
65570                     q = q.nextZ;
65571                     if (!q) break;
65572                 }
65573                 qSize = inSize;
65574
65575                 while (pSize > 0 || (qSize > 0 && q)) {
65576
65577                     if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
65578                         e = p;
65579                         p = p.nextZ;
65580                         pSize--;
65581                     } else {
65582                         e = q;
65583                         q = q.nextZ;
65584                         qSize--;
65585                     }
65586
65587                     if (tail) tail.nextZ = e;
65588                     else list = e;
65589
65590                     e.prevZ = tail;
65591                     tail = e;
65592                 }
65593
65594                 p = q;
65595             }
65596
65597             tail.nextZ = null;
65598             inSize *= 2;
65599
65600         } while (numMerges > 1);
65601
65602         return list;
65603     }
65604
65605     // z-order of a point given coords and inverse of the longer side of data bbox
65606     function zOrder(x, y, minX, minY, invSize) {
65607         // coords are transformed into non-negative 15-bit integer range
65608         x = 32767 * (x - minX) * invSize;
65609         y = 32767 * (y - minY) * invSize;
65610
65611         x = (x | (x << 8)) & 0x00FF00FF;
65612         x = (x | (x << 4)) & 0x0F0F0F0F;
65613         x = (x | (x << 2)) & 0x33333333;
65614         x = (x | (x << 1)) & 0x55555555;
65615
65616         y = (y | (y << 8)) & 0x00FF00FF;
65617         y = (y | (y << 4)) & 0x0F0F0F0F;
65618         y = (y | (y << 2)) & 0x33333333;
65619         y = (y | (y << 1)) & 0x55555555;
65620
65621         return x | (y << 1);
65622     }
65623
65624     // find the leftmost node of a polygon ring
65625     function getLeftmost(start) {
65626         var p = start,
65627             leftmost = start;
65628         do {
65629             if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
65630             p = p.next;
65631         } while (p !== start);
65632
65633         return leftmost;
65634     }
65635
65636     // check if a point lies within a convex triangle
65637     function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
65638         return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
65639                (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
65640                (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
65641     }
65642
65643     // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
65644     function isValidDiagonal(a, b) {
65645         return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
65646                (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
65647                 (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
65648                 equals$1(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
65649     }
65650
65651     // signed area of a triangle
65652     function area(p, q, r) {
65653         return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
65654     }
65655
65656     // check if two points are equal
65657     function equals$1(p1, p2) {
65658         return p1.x === p2.x && p1.y === p2.y;
65659     }
65660
65661     // check if two segments intersect
65662     function intersects(p1, q1, p2, q2) {
65663         var o1 = sign(area(p1, q1, p2));
65664         var o2 = sign(area(p1, q1, q2));
65665         var o3 = sign(area(p2, q2, p1));
65666         var o4 = sign(area(p2, q2, q1));
65667
65668         if (o1 !== o2 && o3 !== o4) return true; // general case
65669
65670         if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
65671         if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
65672         if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
65673         if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
65674
65675         return false;
65676     }
65677
65678     // for collinear points p, q, r, check if point q lies on segment pr
65679     function onSegment(p, q, r) {
65680         return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
65681     }
65682
65683     function sign(num) {
65684         return num > 0 ? 1 : num < 0 ? -1 : 0;
65685     }
65686
65687     // check if a polygon diagonal intersects any polygon segments
65688     function intersectsPolygon(a, b) {
65689         var p = a;
65690         do {
65691             if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
65692                     intersects(p, p.next, a, b)) return true;
65693             p = p.next;
65694         } while (p !== a);
65695
65696         return false;
65697     }
65698
65699     // check if a polygon diagonal is locally inside the polygon
65700     function locallyInside(a, b) {
65701         return area(a.prev, a, a.next) < 0 ?
65702             area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
65703             area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
65704     }
65705
65706     // check if the middle point of a polygon diagonal is inside the polygon
65707     function middleInside(a, b) {
65708         var p = a,
65709             inside = false,
65710             px = (a.x + b.x) / 2,
65711             py = (a.y + b.y) / 2;
65712         do {
65713             if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
65714                     (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
65715                 inside = !inside;
65716             p = p.next;
65717         } while (p !== a);
65718
65719         return inside;
65720     }
65721
65722     // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
65723     // if one belongs to the outer ring and another to a hole, it merges it into a single ring
65724     function splitPolygon(a, b) {
65725         var a2 = new Node(a.i, a.x, a.y),
65726             b2 = new Node(b.i, b.x, b.y),
65727             an = a.next,
65728             bp = b.prev;
65729
65730         a.next = b;
65731         b.prev = a;
65732
65733         a2.next = an;
65734         an.prev = a2;
65735
65736         b2.next = a2;
65737         a2.prev = b2;
65738
65739         bp.next = b2;
65740         b2.prev = bp;
65741
65742         return b2;
65743     }
65744
65745     // create a node and optionally link it with previous one (in a circular doubly linked list)
65746     function insertNode(i, x, y, last) {
65747         var p = new Node(i, x, y);
65748
65749         if (!last) {
65750             p.prev = p;
65751             p.next = p;
65752
65753         } else {
65754             p.next = last.next;
65755             p.prev = last;
65756             last.next.prev = p;
65757             last.next = p;
65758         }
65759         return p;
65760     }
65761
65762     function removeNode(p) {
65763         p.next.prev = p.prev;
65764         p.prev.next = p.next;
65765
65766         if (p.prevZ) p.prevZ.nextZ = p.nextZ;
65767         if (p.nextZ) p.nextZ.prevZ = p.prevZ;
65768     }
65769
65770     function Node(i, x, y) {
65771         // vertex index in coordinates array
65772         this.i = i;
65773
65774         // vertex coordinates
65775         this.x = x;
65776         this.y = y;
65777
65778         // previous and next vertex nodes in a polygon ring
65779         this.prev = null;
65780         this.next = null;
65781
65782         // z-order curve value
65783         this.z = null;
65784
65785         // previous and next nodes in z-order
65786         this.prevZ = null;
65787         this.nextZ = null;
65788
65789         // indicates whether this is a steiner point
65790         this.steiner = false;
65791     }
65792
65793     // return a percentage difference between the polygon area and its triangulation area;
65794     // used to verify correctness of triangulation
65795     earcut.deviation = function (data, holeIndices, dim, triangles) {
65796         var hasHoles = holeIndices && holeIndices.length;
65797         var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
65798
65799         var polygonArea = Math.abs(signedArea$1(data, 0, outerLen, dim));
65800         if (hasHoles) {
65801             for (var i = 0, len = holeIndices.length; i < len; i++) {
65802                 var start = holeIndices[i] * dim;
65803                 var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
65804                 polygonArea -= Math.abs(signedArea$1(data, start, end, dim));
65805             }
65806         }
65807
65808         var trianglesArea = 0;
65809         for (i = 0; i < triangles.length; i += 3) {
65810             var a = triangles[i] * dim;
65811             var b = triangles[i + 1] * dim;
65812             var c = triangles[i + 2] * dim;
65813             trianglesArea += Math.abs(
65814                 (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
65815                 (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
65816         }
65817
65818         return polygonArea === 0 && trianglesArea === 0 ? 0 :
65819             Math.abs((trianglesArea - polygonArea) / polygonArea);
65820     };
65821
65822     function signedArea$1(data, start, end, dim) {
65823         var sum = 0;
65824         for (var i = start, j = end - dim; i < end; i += dim) {
65825             sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
65826             j = i;
65827         }
65828         return sum;
65829     }
65830
65831     // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
65832     earcut.flatten = function (data) {
65833         var dim = data[0][0].length,
65834             result = {vertices: [], holes: [], dimensions: dim},
65835             holeIndex = 0;
65836
65837         for (var i = 0; i < data.length; i++) {
65838             for (var j = 0; j < data[i].length; j++) {
65839                 for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);
65840             }
65841             if (i > 0) {
65842                 holeIndex += data[i - 1].length;
65843                 result.holes.push(holeIndex);
65844             }
65845         }
65846         return result;
65847     };
65848     earcut_1.default = _default$2;
65849
65850     class TinyQueue$1 {
65851         constructor(data = [], compare = defaultCompare$1) {
65852             this.data = data;
65853             this.length = this.data.length;
65854             this.compare = compare;
65855
65856             if (this.length > 0) {
65857                 for (let i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
65858             }
65859         }
65860
65861         push(item) {
65862             this.data.push(item);
65863             this.length++;
65864             this._up(this.length - 1);
65865         }
65866
65867         pop() {
65868             if (this.length === 0) return undefined;
65869
65870             const top = this.data[0];
65871             const bottom = this.data.pop();
65872             this.length--;
65873
65874             if (this.length > 0) {
65875                 this.data[0] = bottom;
65876                 this._down(0);
65877             }
65878
65879             return top;
65880         }
65881
65882         peek() {
65883             return this.data[0];
65884         }
65885
65886         _up(pos) {
65887             const {data, compare} = this;
65888             const item = data[pos];
65889
65890             while (pos > 0) {
65891                 const parent = (pos - 1) >> 1;
65892                 const current = data[parent];
65893                 if (compare(item, current) >= 0) break;
65894                 data[pos] = current;
65895                 pos = parent;
65896             }
65897
65898             data[pos] = item;
65899         }
65900
65901         _down(pos) {
65902             const {data, compare} = this;
65903             const halfLength = this.length >> 1;
65904             const item = data[pos];
65905
65906             while (pos < halfLength) {
65907                 let left = (pos << 1) + 1;
65908                 let best = data[left];
65909                 const right = left + 1;
65910
65911                 if (right < this.length && compare(data[right], best) < 0) {
65912                     left = right;
65913                     best = data[right];
65914                 }
65915                 if (compare(best, item) >= 0) break;
65916
65917                 data[pos] = best;
65918                 pos = left;
65919             }
65920
65921             data[pos] = item;
65922         }
65923     }
65924
65925     function defaultCompare$1(a, b) {
65926         return a < b ? -1 : a > b ? 1 : 0;
65927     }
65928
65929     var tinyqueue$1 = /*#__PURE__*/Object.freeze({
65930         __proto__: null,
65931         'default': TinyQueue$1
65932     });
65933
65934     var require$$0 = /*@__PURE__*/getAugmentedNamespace(tinyqueue$1);
65935
65936     var Queue = require$$0;
65937
65938     if (Queue.default) Queue = Queue.default; // temporary webpack fix
65939
65940     var polylabel_1 = polylabel;
65941     var _default$1 = polylabel;
65942
65943     function polylabel(polygon, precision, debug) {
65944         precision = precision || 1.0;
65945
65946         // find the bounding box of the outer ring
65947         var minX, minY, maxX, maxY;
65948         for (var i = 0; i < polygon[0].length; i++) {
65949             var p = polygon[0][i];
65950             if (!i || p[0] < minX) minX = p[0];
65951             if (!i || p[1] < minY) minY = p[1];
65952             if (!i || p[0] > maxX) maxX = p[0];
65953             if (!i || p[1] > maxY) maxY = p[1];
65954         }
65955
65956         var width = maxX - minX;
65957         var height = maxY - minY;
65958         var cellSize = Math.min(width, height);
65959         var h = cellSize / 2;
65960
65961         if (cellSize === 0) {
65962             var degeneratePoleOfInaccessibility = [minX, minY];
65963             degeneratePoleOfInaccessibility.distance = 0;
65964             return degeneratePoleOfInaccessibility;
65965         }
65966
65967         // a priority queue of cells in order of their "potential" (max distance to polygon)
65968         var cellQueue = new Queue(undefined, compareMax);
65969
65970         // cover polygon with initial cells
65971         for (var x = minX; x < maxX; x += cellSize) {
65972             for (var y = minY; y < maxY; y += cellSize) {
65973                 cellQueue.push(new Cell(x + h, y + h, h, polygon));
65974             }
65975         }
65976
65977         // take centroid as the first best guess
65978         var bestCell = getCentroidCell(polygon);
65979
65980         // special case for rectangular polygons
65981         var bboxCell = new Cell(minX + width / 2, minY + height / 2, 0, polygon);
65982         if (bboxCell.d > bestCell.d) bestCell = bboxCell;
65983
65984         var numProbes = cellQueue.length;
65985
65986         while (cellQueue.length) {
65987             // pick the most promising cell from the queue
65988             var cell = cellQueue.pop();
65989
65990             // update the best cell if we found a better one
65991             if (cell.d > bestCell.d) {
65992                 bestCell = cell;
65993                 if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
65994             }
65995
65996             // do not drill down further if there's no chance of a better solution
65997             if (cell.max - bestCell.d <= precision) continue;
65998
65999             // split the cell into four cells
66000             h = cell.h / 2;
66001             cellQueue.push(new Cell(cell.x - h, cell.y - h, h, polygon));
66002             cellQueue.push(new Cell(cell.x + h, cell.y - h, h, polygon));
66003             cellQueue.push(new Cell(cell.x - h, cell.y + h, h, polygon));
66004             cellQueue.push(new Cell(cell.x + h, cell.y + h, h, polygon));
66005             numProbes += 4;
66006         }
66007
66008         if (debug) {
66009             console.log('num probes: ' + numProbes);
66010             console.log('best distance: ' + bestCell.d);
66011         }
66012
66013         var poleOfInaccessibility = [bestCell.x, bestCell.y];
66014         poleOfInaccessibility.distance = bestCell.d;
66015         return poleOfInaccessibility;
66016     }
66017
66018     function compareMax(a, b) {
66019         return b.max - a.max;
66020     }
66021
66022     function Cell(x, y, h, polygon) {
66023         this.x = x; // cell center x
66024         this.y = y; // cell center y
66025         this.h = h; // half the cell size
66026         this.d = pointToPolygonDist(x, y, polygon); // distance from cell center to polygon
66027         this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
66028     }
66029
66030     // signed distance from point to polygon outline (negative if point is outside)
66031     function pointToPolygonDist(x, y, polygon) {
66032         var inside = false;
66033         var minDistSq = Infinity;
66034
66035         for (var k = 0; k < polygon.length; k++) {
66036             var ring = polygon[k];
66037
66038             for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
66039                 var a = ring[i];
66040                 var b = ring[j];
66041
66042                 if ((a[1] > y !== b[1] > y) &&
66043                     (x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0])) inside = !inside;
66044
66045                 minDistSq = Math.min(minDistSq, getSegDistSq(x, y, a, b));
66046             }
66047         }
66048
66049         return minDistSq === 0 ? 0 : (inside ? 1 : -1) * Math.sqrt(minDistSq);
66050     }
66051
66052     // get polygon centroid
66053     function getCentroidCell(polygon) {
66054         var area = 0;
66055         var x = 0;
66056         var y = 0;
66057         var points = polygon[0];
66058
66059         for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
66060             var a = points[i];
66061             var b = points[j];
66062             var f = a[0] * b[1] - b[0] * a[1];
66063             x += (a[0] + b[0]) * f;
66064             y += (a[1] + b[1]) * f;
66065             area += f * 3;
66066         }
66067         if (area === 0) return new Cell(points[0][0], points[0][1], 0, polygon);
66068         return new Cell(x / area, y / area, 0, polygon);
66069     }
66070
66071     // get squared distance from a point to a segment
66072     function getSegDistSq(px, py, a, b) {
66073
66074         var x = a[0];
66075         var y = a[1];
66076         var dx = b[0] - x;
66077         var dy = b[1] - y;
66078
66079         if (dx !== 0 || dy !== 0) {
66080
66081             var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
66082
66083             if (t > 1) {
66084                 x = b[0];
66085                 y = b[1];
66086
66087             } else if (t > 0) {
66088                 x += dx * t;
66089                 y += dy * t;
66090             }
66091         }
66092
66093         dx = px - x;
66094         dy = py - y;
66095
66096         return dx * dx + dy * dy;
66097     }
66098     polylabel_1.default = _default$1;
66099
66100     function DEFAULT_COMPARE (a, b) { return a > b ? 1 : a < b ? -1 : 0; }
66101
66102     class SplayTree {
66103
66104       constructor(compare = DEFAULT_COMPARE, noDuplicates = false) {
66105         this._compare = compare;
66106         this._root = null;
66107         this._size = 0;
66108         this._noDuplicates = !!noDuplicates;
66109       }
66110
66111
66112       rotateLeft(x) {
66113         var y = x.right;
66114         if (y) {
66115           x.right = y.left;
66116           if (y.left) y.left.parent = x;
66117           y.parent = x.parent;
66118         }
66119
66120         if (!x.parent)                this._root = y;
66121         else if (x === x.parent.left) x.parent.left = y;
66122         else                          x.parent.right = y;
66123         if (y) y.left = x;
66124         x.parent = y;
66125       }
66126
66127
66128       rotateRight(x) {
66129         var y = x.left;
66130         if (y) {
66131           x.left = y.right;
66132           if (y.right) y.right.parent = x;
66133           y.parent = x.parent;
66134         }
66135
66136         if (!x.parent)               this._root = y;
66137         else if(x === x.parent.left) x.parent.left = y;
66138         else                         x.parent.right = y;
66139         if (y) y.right = x;
66140         x.parent = y;
66141       }
66142
66143
66144       _splay(x) {
66145         while (x.parent) {
66146           var p = x.parent;
66147           if (!p.parent) {
66148             if (p.left === x) this.rotateRight(p);
66149             else              this.rotateLeft(p);
66150           } else if (p.left === x && p.parent.left === p) {
66151             this.rotateRight(p.parent);
66152             this.rotateRight(p);
66153           } else if (p.right === x && p.parent.right === p) {
66154             this.rotateLeft(p.parent);
66155             this.rotateLeft(p);
66156           } else if (p.left === x && p.parent.right === p) {
66157             this.rotateRight(p);
66158             this.rotateLeft(p);
66159           } else {
66160             this.rotateLeft(p);
66161             this.rotateRight(p);
66162           }
66163         }
66164       }
66165
66166
66167       splay(x) {
66168         var p, gp, ggp, l, r;
66169
66170         while (x.parent) {
66171           p = x.parent;
66172           gp = p.parent;
66173
66174           if (gp && gp.parent) {
66175             ggp = gp.parent;
66176             if (ggp.left === gp) ggp.left  = x;
66177             else                 ggp.right = x;
66178             x.parent = ggp;
66179           } else {
66180             x.parent = null;
66181             this._root = x;
66182           }
66183
66184           l = x.left; r = x.right;
66185
66186           if (x === p.left) { // left
66187             if (gp) {
66188               if (gp.left === p) {
66189                 /* zig-zig */
66190                 if (p.right) {
66191                   gp.left = p.right;
66192                   gp.left.parent = gp;
66193                 } else gp.left = null;
66194
66195                 p.right   = gp;
66196                 gp.parent = p;
66197               } else {
66198                 /* zig-zag */
66199                 if (l) {
66200                   gp.right = l;
66201                   l.parent = gp;
66202                 } else gp.right = null;
66203
66204                 x.left    = gp;
66205                 gp.parent = x;
66206               }
66207             }
66208             if (r) {
66209               p.left = r;
66210               r.parent = p;
66211             } else p.left = null;
66212
66213             x.right  = p;
66214             p.parent = x;
66215           } else { // right
66216             if (gp) {
66217               if (gp.right === p) {
66218                 /* zig-zig */
66219                 if (p.left) {
66220                   gp.right = p.left;
66221                   gp.right.parent = gp;
66222                 } else gp.right = null;
66223
66224                 p.left = gp;
66225                 gp.parent = p;
66226               } else {
66227                 /* zig-zag */
66228                 if (r) {
66229                   gp.left = r;
66230                   r.parent = gp;
66231                 } else gp.left = null;
66232
66233                 x.right   = gp;
66234                 gp.parent = x;
66235               }
66236             }
66237             if (l) {
66238               p.right = l;
66239               l.parent = p;
66240             } else p.right = null;
66241
66242             x.left   = p;
66243             p.parent = x;
66244           }
66245         }
66246       }
66247
66248
66249       replace(u, v) {
66250         if (!u.parent) this._root = v;
66251         else if (u === u.parent.left) u.parent.left = v;
66252         else u.parent.right = v;
66253         if (v) v.parent = u.parent;
66254       }
66255
66256
66257       minNode(u = this._root) {
66258         if (u) while (u.left) u = u.left;
66259         return u;
66260       }
66261
66262
66263       maxNode(u = this._root) {
66264         if (u) while (u.right) u = u.right;
66265         return u;
66266       }
66267
66268
66269       insert(key, data) {
66270         var z = this._root;
66271         var p = null;
66272         var comp = this._compare;
66273         var cmp;
66274
66275         if (this._noDuplicates) {
66276           while (z) {
66277             p = z;
66278             cmp = comp(z.key, key);
66279             if (cmp === 0) return;
66280             else if (comp(z.key, key) < 0) z = z.right;
66281             else z = z.left;
66282           }
66283         } else {
66284           while (z) {
66285             p = z;
66286             if (comp(z.key, key) < 0) z = z.right;
66287             else z = z.left;
66288           }
66289         }
66290
66291         z = { key, data, left: null, right: null, parent: p };
66292
66293         if (!p)                          this._root = z;
66294         else if (comp(p.key, z.key) < 0) p.right = z;
66295         else                             p.left  = z;
66296
66297         this.splay(z);
66298         this._size++;
66299         return z;
66300       }
66301
66302
66303       find (key) {
66304         var z    = this._root;
66305         var comp = this._compare;
66306         while (z) {
66307           var cmp = comp(z.key, key);
66308           if      (cmp < 0) z = z.right;
66309           else if (cmp > 0) z = z.left;
66310           else              return z;
66311         }
66312         return null;
66313       }
66314
66315       /**
66316        * Whether the tree contains a node with the given key
66317        * @param  {Key} key
66318        * @return {boolean} true/false
66319        */
66320       contains (key) {
66321         var node       = this._root;
66322         var comparator = this._compare;
66323         while (node)  {
66324           var cmp = comparator(key, node.key);
66325           if      (cmp === 0) return true;
66326           else if (cmp < 0)   node = node.left;
66327           else                node = node.right;
66328         }
66329
66330         return false;
66331       }
66332
66333
66334       remove (key) {
66335         var z = this.find(key);
66336
66337         if (!z) return false;
66338
66339         this.splay(z);
66340
66341         if (!z.left) this.replace(z, z.right);
66342         else if (!z.right) this.replace(z, z.left);
66343         else {
66344           var y = this.minNode(z.right);
66345           if (y.parent !== z) {
66346             this.replace(y, y.right);
66347             y.right = z.right;
66348             y.right.parent = y;
66349           }
66350           this.replace(z, y);
66351           y.left = z.left;
66352           y.left.parent = y;
66353         }
66354
66355         this._size--;
66356         return true;
66357       }
66358
66359
66360       removeNode(z) {
66361         if (!z) return false;
66362
66363         this.splay(z);
66364
66365         if (!z.left) this.replace(z, z.right);
66366         else if (!z.right) this.replace(z, z.left);
66367         else {
66368           var y = this.minNode(z.right);
66369           if (y.parent !== z) {
66370             this.replace(y, y.right);
66371             y.right = z.right;
66372             y.right.parent = y;
66373           }
66374           this.replace(z, y);
66375           y.left = z.left;
66376           y.left.parent = y;
66377         }
66378
66379         this._size--;
66380         return true;
66381       }
66382
66383
66384       erase (key) {
66385         var z = this.find(key);
66386         if (!z) return;
66387
66388         this.splay(z);
66389
66390         var s = z.left;
66391         var t = z.right;
66392
66393         var sMax = null;
66394         if (s) {
66395           s.parent = null;
66396           sMax = this.maxNode(s);
66397           this.splay(sMax);
66398           this._root = sMax;
66399         }
66400         if (t) {
66401           if (s) sMax.right = t;
66402           else   this._root = t;
66403           t.parent = sMax;
66404         }
66405
66406         this._size--;
66407       }
66408
66409       /**
66410        * Removes and returns the node with smallest key
66411        * @return {?Node}
66412        */
66413       pop () {
66414         var node = this._root, returnValue = null;
66415         if (node) {
66416           while (node.left) node = node.left;
66417           returnValue = { key: node.key, data: node.data };
66418           this.remove(node.key);
66419         }
66420         return returnValue;
66421       }
66422
66423
66424       /* eslint-disable class-methods-use-this */
66425
66426       /**
66427        * Successor node
66428        * @param  {Node} node
66429        * @return {?Node}
66430        */
66431       next (node) {
66432         var successor = node;
66433         if (successor) {
66434           if (successor.right) {
66435             successor = successor.right;
66436             while (successor && successor.left) successor = successor.left;
66437           } else {
66438             successor = node.parent;
66439             while (successor && successor.right === node) {
66440               node = successor; successor = successor.parent;
66441             }
66442           }
66443         }
66444         return successor;
66445       }
66446
66447
66448       /**
66449        * Predecessor node
66450        * @param  {Node} node
66451        * @return {?Node}
66452        */
66453       prev (node) {
66454         var predecessor = node;
66455         if (predecessor) {
66456           if (predecessor.left) {
66457             predecessor = predecessor.left;
66458             while (predecessor && predecessor.right) predecessor = predecessor.right;
66459           } else {
66460             predecessor = node.parent;
66461             while (predecessor && predecessor.left === node) {
66462               node = predecessor;
66463               predecessor = predecessor.parent;
66464             }
66465           }
66466         }
66467         return predecessor;
66468       }
66469       /* eslint-enable class-methods-use-this */
66470
66471
66472       /**
66473        * @param  {forEachCallback} callback
66474        * @return {SplayTree}
66475        */
66476       forEach(callback) {
66477         var current = this._root;
66478         var s = [], done = false, i = 0;
66479
66480         while (!done) {
66481           // Reach the left most Node of the current Node
66482           if (current) {
66483             // Place pointer to a tree node on the stack
66484             // before traversing the node's left subtree
66485             s.push(current);
66486             current = current.left;
66487           } else {
66488             // BackTrack from the empty subtree and visit the Node
66489             // at the top of the stack; however, if the stack is
66490             // empty you are done
66491             if (s.length > 0) {
66492               current = s.pop();
66493               callback(current, i++);
66494
66495               // We have visited the node and its left
66496               // subtree. Now, it's right subtree's turn
66497               current = current.right;
66498             } else done = true;
66499           }
66500         }
66501         return this;
66502       }
66503
66504
66505       /**
66506        * Walk key range from `low` to `high`. Stops if `fn` returns a value.
66507        * @param  {Key}      low
66508        * @param  {Key}      high
66509        * @param  {Function} fn
66510        * @param  {*?}       ctx
66511        * @return {SplayTree}
66512        */
66513       range(low, high, fn, ctx) {
66514         const Q = [];
66515         const compare = this._compare;
66516         let node = this._root, cmp;
66517
66518         while (Q.length !== 0 || node) {
66519           if (node) {
66520             Q.push(node);
66521             node = node.left;
66522           } else {
66523             node = Q.pop();
66524             cmp = compare(node.key, high);
66525             if (cmp > 0) {
66526               break;
66527             } else if (compare(node.key, low) >= 0) {
66528               if (fn.call(ctx, node)) return this; // stop if smth is returned
66529             }
66530             node = node.right;
66531           }
66532         }
66533         return this;
66534       }
66535
66536       /**
66537        * Returns all keys in order
66538        * @return {Array<Key>}
66539        */
66540       keys () {
66541         var current = this._root;
66542         var s = [], r = [], done = false;
66543
66544         while (!done) {
66545           if (current) {
66546             s.push(current);
66547             current = current.left;
66548           } else {
66549             if (s.length > 0) {
66550               current = s.pop();
66551               r.push(current.key);
66552               current = current.right;
66553             } else done = true;
66554           }
66555         }
66556         return r;
66557       }
66558
66559
66560       /**
66561        * Returns `data` fields of all nodes in order.
66562        * @return {Array<Value>}
66563        */
66564       values () {
66565         var current = this._root;
66566         var s = [], r = [], done = false;
66567
66568         while (!done) {
66569           if (current) {
66570             s.push(current);
66571             current = current.left;
66572           } else {
66573             if (s.length > 0) {
66574               current = s.pop();
66575               r.push(current.data);
66576               current = current.right;
66577             } else done = true;
66578           }
66579         }
66580         return r;
66581       }
66582
66583
66584       /**
66585        * Returns node at given index
66586        * @param  {number} index
66587        * @return {?Node}
66588        */
66589       at (index) {
66590         // removed after a consideration, more misleading than useful
66591         // index = index % this.size;
66592         // if (index < 0) index = this.size - index;
66593
66594         var current = this._root;
66595         var s = [], done = false, i = 0;
66596
66597         while (!done) {
66598           if (current) {
66599             s.push(current);
66600             current = current.left;
66601           } else {
66602             if (s.length > 0) {
66603               current = s.pop();
66604               if (i === index) return current;
66605               i++;
66606               current = current.right;
66607             } else done = true;
66608           }
66609         }
66610         return null;
66611       }
66612
66613       /**
66614        * Bulk-load items. Both array have to be same size
66615        * @param  {Array<Key>}    keys
66616        * @param  {Array<Value>}  [values]
66617        * @param  {Boolean}       [presort=false] Pre-sort keys and values, using
66618        *                                         tree's comparator. Sorting is done
66619        *                                         in-place
66620        * @return {AVLTree}
66621        */
66622       load(keys = [], values = [], presort = false) {
66623         if (this._size !== 0) throw new Error('bulk-load: tree is not empty');
66624         const size = keys.length;
66625         if (presort) sort(keys, values, 0, size - 1, this._compare);
66626         this._root = loadRecursive(null, keys, values, 0, size);
66627         this._size = size;
66628         return this;
66629       }
66630
66631
66632       min() {
66633         var node = this.minNode(this._root);
66634         if (node) return node.key;
66635         else      return null;
66636       }
66637
66638
66639       max() {
66640         var node = this.maxNode(this._root);
66641         if (node) return node.key;
66642         else      return null;
66643       }
66644
66645       isEmpty() { return this._root === null; }
66646       get size() { return this._size; }
66647
66648
66649       /**
66650        * Create a tree and load it with items
66651        * @param  {Array<Key>}          keys
66652        * @param  {Array<Value>?}        [values]
66653
66654        * @param  {Function?}            [comparator]
66655        * @param  {Boolean?}             [presort=false] Pre-sort keys and values, using
66656        *                                               tree's comparator. Sorting is done
66657        *                                               in-place
66658        * @param  {Boolean?}             [noDuplicates=false]   Allow duplicates
66659        * @return {SplayTree}
66660        */
66661       static createTree(keys, values, comparator, presort, noDuplicates) {
66662         return new SplayTree(comparator, noDuplicates).load(keys, values, presort);
66663       }
66664     }
66665
66666
66667     function loadRecursive (parent, keys, values, start, end) {
66668       const size = end - start;
66669       if (size > 0) {
66670         const middle = start + Math.floor(size / 2);
66671         const key    = keys[middle];
66672         const data   = values[middle];
66673         const node   = { key, data, parent };
66674         node.left    = loadRecursive(node, keys, values, start, middle);
66675         node.right   = loadRecursive(node, keys, values, middle + 1, end);
66676         return node;
66677       }
66678       return null;
66679     }
66680
66681
66682     function sort(keys, values, left, right, compare) {
66683       if (left >= right) return;
66684
66685       const pivot = keys[(left + right) >> 1];
66686       let i = left - 1;
66687       let j = right + 1;
66688
66689       while (true) {
66690         do i++; while (compare(keys[i], pivot) < 0);
66691         do j--; while (compare(keys[j], pivot) > 0);
66692         if (i >= j) break;
66693
66694         let tmp = keys[i];
66695         keys[i] = keys[j];
66696         keys[j] = tmp;
66697
66698         tmp = values[i];
66699         values[i] = values[j];
66700         values[j] = tmp;
66701       }
66702
66703       sort(keys, values,  left,     j, compare);
66704       sort(keys, values, j + 1, right, compare);
66705     }
66706
66707     const NORMAL               = 0;
66708     const NON_CONTRIBUTING     = 1;
66709     const SAME_TRANSITION      = 2;
66710     const DIFFERENT_TRANSITION = 3;
66711
66712     const INTERSECTION = 0;
66713     const UNION        = 1;
66714     const DIFFERENCE   = 2;
66715     const XOR          = 3;
66716
66717     /**
66718      * @param  {SweepEvent} event
66719      * @param  {SweepEvent} prev
66720      * @param  {Operation} operation
66721      */
66722     function computeFields (event, prev, operation) {
66723       // compute inOut and otherInOut fields
66724       if (prev === null) {
66725         event.inOut      = false;
66726         event.otherInOut = true;
66727
66728       // previous line segment in sweepline belongs to the same polygon
66729       } else {
66730         if (event.isSubject === prev.isSubject) {
66731           event.inOut      = !prev.inOut;
66732           event.otherInOut = prev.otherInOut;
66733
66734         // previous line segment in sweepline belongs to the clipping polygon
66735         } else {
66736           event.inOut      = !prev.otherInOut;
66737           event.otherInOut = prev.isVertical() ? !prev.inOut : prev.inOut;
66738         }
66739
66740         // compute prevInResult field
66741         if (prev) {
66742           event.prevInResult = (!inResult(prev, operation) || prev.isVertical())
66743             ? prev.prevInResult : prev;
66744         }
66745       }
66746
66747       // check if the line segment belongs to the Boolean operation
66748       let isInResult = inResult(event, operation);
66749       if (isInResult) {
66750         event.resultTransition = determineResultTransition(event, operation);
66751       } else {
66752         event.resultTransition = 0;
66753       }
66754     }
66755
66756
66757     /* eslint-disable indent */
66758     function inResult(event, operation) {
66759       switch (event.type) {
66760         case NORMAL:
66761           switch (operation) {
66762             case INTERSECTION:
66763               return !event.otherInOut;
66764             case UNION:
66765               return event.otherInOut;
66766             case DIFFERENCE:
66767               // return (event.isSubject && !event.otherInOut) ||
66768               //         (!event.isSubject && event.otherInOut);
66769               return (event.isSubject && event.otherInOut) ||
66770                       (!event.isSubject && !event.otherInOut);
66771             case XOR:
66772               return true;
66773           }
66774           break;
66775         case SAME_TRANSITION:
66776           return operation === INTERSECTION || operation === UNION;
66777         case DIFFERENT_TRANSITION:
66778           return operation === DIFFERENCE;
66779         case NON_CONTRIBUTING:
66780           return false;
66781       }
66782       return false;
66783     }
66784     /* eslint-enable indent */
66785
66786
66787     function determineResultTransition(event, operation) {
66788       let thisIn = !event.inOut;
66789       let thatIn = !event.otherInOut;
66790
66791       let isIn;
66792       switch (operation) {
66793         case INTERSECTION:
66794           isIn = thisIn && thatIn; break;
66795         case UNION:
66796           isIn = thisIn || thatIn; break;
66797         case XOR:
66798           isIn = thisIn ^ thatIn; break;
66799         case DIFFERENCE:
66800           if (event.isSubject) {
66801             isIn = thisIn && !thatIn;
66802           } else {
66803             isIn = thatIn && !thisIn;
66804           }
66805           break;
66806       }
66807       return isIn ? +1 : -1;
66808     }
66809
66810     class SweepEvent {
66811
66812
66813       /**
66814        * Sweepline event
66815        *
66816        * @class {SweepEvent}
66817        * @param {Array.<Number>}  point
66818        * @param {Boolean}         left
66819        * @param {SweepEvent=}     otherEvent
66820        * @param {Boolean}         isSubject
66821        * @param {Number}          edgeType
66822        */
66823       constructor (point, left, otherEvent, isSubject, edgeType) {
66824
66825         /**
66826          * Is left endpoint?
66827          * @type {Boolean}
66828          */
66829         this.left = left;
66830
66831         /**
66832          * @type {Array.<Number>}
66833          */
66834         this.point = point;
66835
66836         /**
66837          * Other edge reference
66838          * @type {SweepEvent}
66839          */
66840         this.otherEvent = otherEvent;
66841
66842         /**
66843          * Belongs to source or clipping polygon
66844          * @type {Boolean}
66845          */
66846         this.isSubject = isSubject;
66847
66848         /**
66849          * Edge contribution type
66850          * @type {Number}
66851          */
66852         this.type = edgeType || NORMAL;
66853
66854
66855         /**
66856          * In-out transition for the sweepline crossing polygon
66857          * @type {Boolean}
66858          */
66859         this.inOut = false;
66860
66861
66862         /**
66863          * @type {Boolean}
66864          */
66865         this.otherInOut = false;
66866
66867         /**
66868          * Previous event in result?
66869          * @type {SweepEvent}
66870          */
66871         this.prevInResult = null;
66872
66873         /**
66874          * Type of result transition (0 = not in result, +1 = out-in, -1, in-out)
66875          * @type {Number}
66876          */
66877         this.resultTransition = 0;
66878
66879         // connection step
66880
66881         /**
66882          * @type {Number}
66883          */
66884         this.otherPos = -1;
66885
66886         /**
66887          * @type {Number}
66888          */
66889         this.outputContourId = -1;
66890
66891         this.isExteriorRing = true;   // TODO: Looks unused, remove?
66892       }
66893
66894
66895       /**
66896        * @param  {Array.<Number>}  p
66897        * @return {Boolean}
66898        */
66899       isBelow (p) {
66900         const p0 = this.point, p1 = this.otherEvent.point;
66901         return this.left
66902           ? (p0[0] - p[0]) * (p1[1] - p[1]) - (p1[0] - p[0]) * (p0[1] - p[1]) > 0
66903           // signedArea(this.point, this.otherEvent.point, p) > 0 :
66904           : (p1[0] - p[0]) * (p0[1] - p[1]) - (p0[0] - p[0]) * (p1[1] - p[1]) > 0;
66905           //signedArea(this.otherEvent.point, this.point, p) > 0;
66906       }
66907
66908
66909       /**
66910        * @param  {Array.<Number>}  p
66911        * @return {Boolean}
66912        */
66913       isAbove (p) {
66914         return !this.isBelow(p);
66915       }
66916
66917
66918       /**
66919        * @return {Boolean}
66920        */
66921       isVertical () {
66922         return this.point[0] === this.otherEvent.point[0];
66923       }
66924
66925
66926       /**
66927        * Does event belong to result?
66928        * @return {Boolean}
66929        */
66930       get inResult() {
66931         return this.resultTransition !== 0;
66932       }
66933
66934
66935       clone () {
66936         const copy = new SweepEvent(
66937           this.point, this.left, this.otherEvent, this.isSubject, this.type);
66938
66939         copy.contourId        = this.contourId;
66940         copy.resultTransition = this.resultTransition;
66941         copy.prevInResult     = this.prevInResult;
66942         copy.isExteriorRing   = this.isExteriorRing;
66943         copy.inOut            = this.inOut;
66944         copy.otherInOut       = this.otherInOut;
66945
66946         return copy;
66947       }
66948     }
66949
66950     function equals(p1, p2) {
66951       if (p1[0] === p2[0]) {
66952         if (p1[1] === p2[1]) {
66953           return true;
66954         } else {
66955           return false;
66956         }
66957       }
66958       return false;
66959     }
66960
66961     // const EPSILON = 1e-9;
66962     // const abs = Math.abs;
66963     // TODO https://github.com/w8r/martinez/issues/6#issuecomment-262847164
66964     // Precision problem.
66965     //
66966     // module.exports = function equals(p1, p2) {
66967     //   return abs(p1[0] - p2[0]) <= EPSILON && abs(p1[1] - p2[1]) <= EPSILON;
66968     // };
66969
66970     const epsilon = 1.1102230246251565e-16;
66971     const splitter = 134217729;
66972     const resulterrbound = (3 + 8 * epsilon) * epsilon;
66973
66974     // fast_expansion_sum_zeroelim routine from oritinal code
66975     function sum(elen, e, flen, f, h) {
66976         let Q, Qnew, hh, bvirt;
66977         let enow = e[0];
66978         let fnow = f[0];
66979         let eindex = 0;
66980         let findex = 0;
66981         if ((fnow > enow) === (fnow > -enow)) {
66982             Q = enow;
66983             enow = e[++eindex];
66984         } else {
66985             Q = fnow;
66986             fnow = f[++findex];
66987         }
66988         let hindex = 0;
66989         if (eindex < elen && findex < flen) {
66990             if ((fnow > enow) === (fnow > -enow)) {
66991                 Qnew = enow + Q;
66992                 hh = Q - (Qnew - enow);
66993                 enow = e[++eindex];
66994             } else {
66995                 Qnew = fnow + Q;
66996                 hh = Q - (Qnew - fnow);
66997                 fnow = f[++findex];
66998             }
66999             Q = Qnew;
67000             if (hh !== 0) {
67001                 h[hindex++] = hh;
67002             }
67003             while (eindex < elen && findex < flen) {
67004                 if ((fnow > enow) === (fnow > -enow)) {
67005                     Qnew = Q + enow;
67006                     bvirt = Qnew - Q;
67007                     hh = Q - (Qnew - bvirt) + (enow - bvirt);
67008                     enow = e[++eindex];
67009                 } else {
67010                     Qnew = Q + fnow;
67011                     bvirt = Qnew - Q;
67012                     hh = Q - (Qnew - bvirt) + (fnow - bvirt);
67013                     fnow = f[++findex];
67014                 }
67015                 Q = Qnew;
67016                 if (hh !== 0) {
67017                     h[hindex++] = hh;
67018                 }
67019             }
67020         }
67021         while (eindex < elen) {
67022             Qnew = Q + enow;
67023             bvirt = Qnew - Q;
67024             hh = Q - (Qnew - bvirt) + (enow - bvirt);
67025             enow = e[++eindex];
67026             Q = Qnew;
67027             if (hh !== 0) {
67028                 h[hindex++] = hh;
67029             }
67030         }
67031         while (findex < flen) {
67032             Qnew = Q + fnow;
67033             bvirt = Qnew - Q;
67034             hh = Q - (Qnew - bvirt) + (fnow - bvirt);
67035             fnow = f[++findex];
67036             Q = Qnew;
67037             if (hh !== 0) {
67038                 h[hindex++] = hh;
67039             }
67040         }
67041         if (Q !== 0 || hindex === 0) {
67042             h[hindex++] = Q;
67043         }
67044         return hindex;
67045     }
67046
67047     function estimate(elen, e) {
67048         let Q = e[0];
67049         for (let i = 1; i < elen; i++) Q += e[i];
67050         return Q;
67051     }
67052
67053     function vec(n) {
67054         return new Float64Array(n);
67055     }
67056
67057     const ccwerrboundA = (3 + 16 * epsilon) * epsilon;
67058     const ccwerrboundB = (2 + 12 * epsilon) * epsilon;
67059     const ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;
67060
67061     const B = vec(4);
67062     const C1 = vec(8);
67063     const C2 = vec(12);
67064     const D = vec(16);
67065     const u = vec(4);
67066
67067     function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
67068         let acxtail, acytail, bcxtail, bcytail;
67069         let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
67070
67071         const acx = ax - cx;
67072         const bcx = bx - cx;
67073         const acy = ay - cy;
67074         const bcy = by - cy;
67075
67076         s1 = acx * bcy;
67077         c = splitter * acx;
67078         ahi = c - (c - acx);
67079         alo = acx - ahi;
67080         c = splitter * bcy;
67081         bhi = c - (c - bcy);
67082         blo = bcy - bhi;
67083         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
67084         t1 = acy * bcx;
67085         c = splitter * acy;
67086         ahi = c - (c - acy);
67087         alo = acy - ahi;
67088         c = splitter * bcx;
67089         bhi = c - (c - bcx);
67090         blo = bcx - bhi;
67091         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
67092         _i = s0 - t0;
67093         bvirt = s0 - _i;
67094         B[0] = s0 - (_i + bvirt) + (bvirt - t0);
67095         _j = s1 + _i;
67096         bvirt = _j - s1;
67097         _0 = s1 - (_j - bvirt) + (_i - bvirt);
67098         _i = _0 - t1;
67099         bvirt = _0 - _i;
67100         B[1] = _0 - (_i + bvirt) + (bvirt - t1);
67101         u3 = _j + _i;
67102         bvirt = u3 - _j;
67103         B[2] = _j - (u3 - bvirt) + (_i - bvirt);
67104         B[3] = u3;
67105
67106         let det = estimate(4, B);
67107         let errbound = ccwerrboundB * detsum;
67108         if (det >= errbound || -det >= errbound) {
67109             return det;
67110         }
67111
67112         bvirt = ax - acx;
67113         acxtail = ax - (acx + bvirt) + (bvirt - cx);
67114         bvirt = bx - bcx;
67115         bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
67116         bvirt = ay - acy;
67117         acytail = ay - (acy + bvirt) + (bvirt - cy);
67118         bvirt = by - bcy;
67119         bcytail = by - (bcy + bvirt) + (bvirt - cy);
67120
67121         if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
67122             return det;
67123         }
67124
67125         errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
67126         det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
67127         if (det >= errbound || -det >= errbound) return det;
67128
67129         s1 = acxtail * bcy;
67130         c = splitter * acxtail;
67131         ahi = c - (c - acxtail);
67132         alo = acxtail - ahi;
67133         c = splitter * bcy;
67134         bhi = c - (c - bcy);
67135         blo = bcy - bhi;
67136         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
67137         t1 = acytail * bcx;
67138         c = splitter * acytail;
67139         ahi = c - (c - acytail);
67140         alo = acytail - ahi;
67141         c = splitter * bcx;
67142         bhi = c - (c - bcx);
67143         blo = bcx - bhi;
67144         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
67145         _i = s0 - t0;
67146         bvirt = s0 - _i;
67147         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
67148         _j = s1 + _i;
67149         bvirt = _j - s1;
67150         _0 = s1 - (_j - bvirt) + (_i - bvirt);
67151         _i = _0 - t1;
67152         bvirt = _0 - _i;
67153         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
67154         u3 = _j + _i;
67155         bvirt = u3 - _j;
67156         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
67157         u[3] = u3;
67158         const C1len = sum(4, B, 4, u, C1);
67159
67160         s1 = acx * bcytail;
67161         c = splitter * acx;
67162         ahi = c - (c - acx);
67163         alo = acx - ahi;
67164         c = splitter * bcytail;
67165         bhi = c - (c - bcytail);
67166         blo = bcytail - bhi;
67167         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
67168         t1 = acy * bcxtail;
67169         c = splitter * acy;
67170         ahi = c - (c - acy);
67171         alo = acy - ahi;
67172         c = splitter * bcxtail;
67173         bhi = c - (c - bcxtail);
67174         blo = bcxtail - bhi;
67175         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
67176         _i = s0 - t0;
67177         bvirt = s0 - _i;
67178         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
67179         _j = s1 + _i;
67180         bvirt = _j - s1;
67181         _0 = s1 - (_j - bvirt) + (_i - bvirt);
67182         _i = _0 - t1;
67183         bvirt = _0 - _i;
67184         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
67185         u3 = _j + _i;
67186         bvirt = u3 - _j;
67187         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
67188         u[3] = u3;
67189         const C2len = sum(C1len, C1, 4, u, C2);
67190
67191         s1 = acxtail * bcytail;
67192         c = splitter * acxtail;
67193         ahi = c - (c - acxtail);
67194         alo = acxtail - ahi;
67195         c = splitter * bcytail;
67196         bhi = c - (c - bcytail);
67197         blo = bcytail - bhi;
67198         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
67199         t1 = acytail * bcxtail;
67200         c = splitter * acytail;
67201         ahi = c - (c - acytail);
67202         alo = acytail - ahi;
67203         c = splitter * bcxtail;
67204         bhi = c - (c - bcxtail);
67205         blo = bcxtail - bhi;
67206         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
67207         _i = s0 - t0;
67208         bvirt = s0 - _i;
67209         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
67210         _j = s1 + _i;
67211         bvirt = _j - s1;
67212         _0 = s1 - (_j - bvirt) + (_i - bvirt);
67213         _i = _0 - t1;
67214         bvirt = _0 - _i;
67215         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
67216         u3 = _j + _i;
67217         bvirt = u3 - _j;
67218         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
67219         u[3] = u3;
67220         const Dlen = sum(C2len, C2, 4, u, D);
67221
67222         return D[Dlen - 1];
67223     }
67224
67225     function orient2d(ax, ay, bx, by, cx, cy) {
67226         const detleft = (ay - cy) * (bx - cx);
67227         const detright = (ax - cx) * (by - cy);
67228         const det = detleft - detright;
67229
67230         if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
67231
67232         const detsum = Math.abs(detleft + detright);
67233         if (Math.abs(det) >= ccwerrboundA * detsum) return det;
67234
67235         return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
67236     }
67237
67238     /**
67239      * Signed area of the triangle (p0, p1, p2)
67240      * @param  {Array.<Number>} p0
67241      * @param  {Array.<Number>} p1
67242      * @param  {Array.<Number>} p2
67243      * @return {Number}
67244      */
67245     function signedArea(p0, p1, p2) {
67246       const res = orient2d(p0[0], p0[1], p1[0], p1[1], p2[0], p2[1]);
67247       if (res > 0) return -1;
67248       if (res < 0) return 1;
67249       return 0;
67250     }
67251
67252     /**
67253      * @param  {SweepEvent} e1
67254      * @param  {SweepEvent} e2
67255      * @return {Number}
67256      */
67257     function compareEvents(e1, e2) {
67258       const p1 = e1.point;
67259       const p2 = e2.point;
67260
67261       // Different x-coordinate
67262       if (p1[0] > p2[0]) return 1;
67263       if (p1[0] < p2[0]) return -1;
67264
67265       // Different points, but same x-coordinate
67266       // Event with lower y-coordinate is processed first
67267       if (p1[1] !== p2[1]) return p1[1] > p2[1] ? 1 : -1;
67268
67269       return specialCases(e1, e2, p1);
67270     }
67271
67272
67273     /* eslint-disable no-unused-vars */
67274     function specialCases(e1, e2, p1, p2) {
67275       // Same coordinates, but one is a left endpoint and the other is
67276       // a right endpoint. The right endpoint is processed first
67277       if (e1.left !== e2.left)
67278         return e1.left ? 1 : -1;
67279
67280       // const p2 = e1.otherEvent.point, p3 = e2.otherEvent.point;
67281       // const sa = (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])
67282       // Same coordinates, both events
67283       // are left endpoints or right endpoints.
67284       // not collinear
67285       if (signedArea(p1, e1.otherEvent.point, e2.otherEvent.point) !== 0) {
67286         // the event associate to the bottom segment is processed first
67287         return (!e1.isBelow(e2.otherEvent.point)) ? 1 : -1;
67288       }
67289
67290       return (!e1.isSubject && e2.isSubject) ? 1 : -1;
67291     }
67292     /* eslint-enable no-unused-vars */
67293
67294     /**
67295      * @param  {SweepEvent} se
67296      * @param  {Array.<Number>} p
67297      * @param  {Queue} queue
67298      * @return {Queue}
67299      */
67300     function divideSegment(se, p, queue)  {
67301       const r = new SweepEvent(p, false, se,            se.isSubject);
67302       const l = new SweepEvent(p, true,  se.otherEvent, se.isSubject);
67303
67304       /* eslint-disable no-console */
67305       if (equals(se.point, se.otherEvent.point)) {
67306         console.warn('what is that, a collapsed segment?', se);
67307       }
67308       /* eslint-enable no-console */
67309
67310       r.contourId = l.contourId = se.contourId;
67311
67312       // avoid a rounding error. The left event would be processed after the right event
67313       if (compareEvents(l, se.otherEvent) > 0) {
67314         se.otherEvent.left = true;
67315         l.left = false;
67316       }
67317
67318       // avoid a rounding error. The left event would be processed after the right event
67319       // if (compareEvents(se, r) > 0) {}
67320
67321       se.otherEvent.otherEvent = l;
67322       se.otherEvent = r;
67323
67324       queue.push(l);
67325       queue.push(r);
67326
67327       return queue;
67328     }
67329
67330     //const EPS = 1e-9;
67331
67332     /**
67333      * Finds the magnitude of the cross product of two vectors (if we pretend
67334      * they're in three dimensions)
67335      *
67336      * @param {Object} a First vector
67337      * @param {Object} b Second vector
67338      * @private
67339      * @returns {Number} The magnitude of the cross product
67340      */
67341     function crossProduct(a, b) {
67342       return (a[0] * b[1]) - (a[1] * b[0]);
67343     }
67344
67345     /**
67346      * Finds the dot product of two vectors.
67347      *
67348      * @param {Object} a First vector
67349      * @param {Object} b Second vector
67350      * @private
67351      * @returns {Number} The dot product
67352      */
67353     function dotProduct(a, b) {
67354       return (a[0] * b[0]) + (a[1] * b[1]);
67355     }
67356
67357     /**
67358      * Finds the intersection (if any) between two line segments a and b, given the
67359      * line segments' end points a1, a2 and b1, b2.
67360      *
67361      * This algorithm is based on Schneider and Eberly.
67362      * http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf
67363      * Page 244.
67364      *
67365      * @param {Array.<Number>} a1 point of first line
67366      * @param {Array.<Number>} a2 point of first line
67367      * @param {Array.<Number>} b1 point of second line
67368      * @param {Array.<Number>} b2 point of second line
67369      * @param {Boolean=}       noEndpointTouch whether to skip single touchpoints
67370      *                                         (meaning connected segments) as
67371      *                                         intersections
67372      * @returns {Array.<Array.<Number>>|Null} If the lines intersect, the point of
67373      * intersection. If they overlap, the two end points of the overlapping segment.
67374      * Otherwise, null.
67375      */
67376     function intersection$1 (a1, a2, b1, b2, noEndpointTouch) {
67377       // The algorithm expects our lines in the form P + sd, where P is a point,
67378       // s is on the interval [0, 1], and d is a vector.
67379       // We are passed two points. P can be the first point of each pair. The
67380       // vector, then, could be thought of as the distance (in x and y components)
67381       // from the first point to the second point.
67382       // So first, let's make our vectors:
67383       const va = [a2[0] - a1[0], a2[1] - a1[1]];
67384       const vb = [b2[0] - b1[0], b2[1] - b1[1]];
67385       // We also define a function to convert back to regular point form:
67386
67387       /* eslint-disable arrow-body-style */
67388
67389       function toPoint(p, s, d) {
67390         return [
67391           p[0] + s * d[0],
67392           p[1] + s * d[1]
67393         ];
67394       }
67395
67396       /* eslint-enable arrow-body-style */
67397
67398       // The rest is pretty much a straight port of the algorithm.
67399       const e = [b1[0] - a1[0], b1[1] - a1[1]];
67400       let kross    = crossProduct(va, vb);
67401       let sqrKross = kross * kross;
67402       const sqrLenA  = dotProduct(va, va);
67403       //const sqrLenB  = dotProduct(vb, vb);
67404
67405       // Check for line intersection. This works because of the properties of the
67406       // cross product -- specifically, two vectors are parallel if and only if the
67407       // cross product is the 0 vector. The full calculation involves relative error
67408       // to account for possible very small line segments. See Schneider & Eberly
67409       // for details.
67410       if (sqrKross > 0/* EPS * sqrLenB * sqLenA */) {
67411         // If they're not parallel, then (because these are line segments) they
67412         // still might not actually intersect. This code checks that the
67413         // intersection point of the lines is actually on both line segments.
67414         const s = crossProduct(e, vb) / kross;
67415         if (s < 0 || s > 1) {
67416           // not on line segment a
67417           return null;
67418         }
67419         const t = crossProduct(e, va) / kross;
67420         if (t < 0 || t > 1) {
67421           // not on line segment b
67422           return null;
67423         }
67424         if (s === 0 || s === 1) {
67425           // on an endpoint of line segment a
67426           return noEndpointTouch ? null : [toPoint(a1, s, va)];
67427         }
67428         if (t === 0 || t === 1) {
67429           // on an endpoint of line segment b
67430           return noEndpointTouch ? null : [toPoint(b1, t, vb)];
67431         }
67432         return [toPoint(a1, s, va)];
67433       }
67434
67435       // If we've reached this point, then the lines are either parallel or the
67436       // same, but the segments could overlap partially or fully, or not at all.
67437       // So we need to find the overlap, if any. To do that, we can use e, which is
67438       // the (vector) difference between the two initial points. If this is parallel
67439       // with the line itself, then the two lines are the same line, and there will
67440       // be overlap.
67441       //const sqrLenE = dotProduct(e, e);
67442       kross = crossProduct(e, va);
67443       sqrKross = kross * kross;
67444
67445       if (sqrKross > 0 /* EPS * sqLenB * sqLenE */) {
67446       // Lines are just parallel, not the same. No overlap.
67447         return null;
67448       }
67449
67450       const sa = dotProduct(va, e) / sqrLenA;
67451       const sb = sa + dotProduct(va, vb) / sqrLenA;
67452       const smin = Math.min(sa, sb);
67453       const smax = Math.max(sa, sb);
67454
67455       // this is, essentially, the FindIntersection acting on floats from
67456       // Schneider & Eberly, just inlined into this function.
67457       if (smin <= 1 && smax >= 0) {
67458
67459         // overlap on an end point
67460         if (smin === 1) {
67461           return noEndpointTouch ? null : [toPoint(a1, smin > 0 ? smin : 0, va)];
67462         }
67463
67464         if (smax === 0) {
67465           return noEndpointTouch ? null : [toPoint(a1, smax < 1 ? smax : 1, va)];
67466         }
67467
67468         if (noEndpointTouch && smin === 0 && smax === 1) return null;
67469
67470         // There's overlap on a segment -- two points of intersection. Return both.
67471         return [
67472           toPoint(a1, smin > 0 ? smin : 0, va),
67473           toPoint(a1, smax < 1 ? smax : 1, va)
67474         ];
67475       }
67476
67477       return null;
67478     }
67479
67480     /**
67481      * @param  {SweepEvent} se1
67482      * @param  {SweepEvent} se2
67483      * @param  {Queue}      queue
67484      * @return {Number}
67485      */
67486     function possibleIntersection (se1, se2, queue) {
67487       // that disallows self-intersecting polygons,
67488       // did cost us half a day, so I'll leave it
67489       // out of respect
67490       // if (se1.isSubject === se2.isSubject) return;
67491       const inter = intersection$1(
67492         se1.point, se1.otherEvent.point,
67493         se2.point, se2.otherEvent.point
67494       );
67495
67496       const nintersections = inter ? inter.length : 0;
67497       if (nintersections === 0) return 0; // no intersection
67498
67499       // the line segments intersect at an endpoint of both line segments
67500       if ((nintersections === 1) &&
67501           (equals(se1.point, se2.point) ||
67502            equals(se1.otherEvent.point, se2.otherEvent.point))) {
67503         return 0;
67504       }
67505
67506       if (nintersections === 2 && se1.isSubject === se2.isSubject) {
67507         // if(se1.contourId === se2.contourId){
67508         // console.warn('Edges of the same polygon overlap',
67509         //   se1.point, se1.otherEvent.point, se2.point, se2.otherEvent.point);
67510         // }
67511         //throw new Error('Edges of the same polygon overlap');
67512         return 0;
67513       }
67514
67515       // The line segments associated to se1 and se2 intersect
67516       if (nintersections === 1) {
67517
67518         // if the intersection point is not an endpoint of se1
67519         if (!equals(se1.point, inter[0]) && !equals(se1.otherEvent.point, inter[0])) {
67520           divideSegment(se1, inter[0], queue);
67521         }
67522
67523         // if the intersection point is not an endpoint of se2
67524         if (!equals(se2.point, inter[0]) && !equals(se2.otherEvent.point, inter[0])) {
67525           divideSegment(se2, inter[0], queue);
67526         }
67527         return 1;
67528       }
67529
67530       // The line segments associated to se1 and se2 overlap
67531       const events        = [];
67532       let leftCoincide  = false;
67533       let rightCoincide = false;
67534
67535       if (equals(se1.point, se2.point)) {
67536         leftCoincide = true; // linked
67537       } else if (compareEvents(se1, se2) === 1) {
67538         events.push(se2, se1);
67539       } else {
67540         events.push(se1, se2);
67541       }
67542
67543       if (equals(se1.otherEvent.point, se2.otherEvent.point)) {
67544         rightCoincide = true;
67545       } else if (compareEvents(se1.otherEvent, se2.otherEvent) === 1) {
67546         events.push(se2.otherEvent, se1.otherEvent);
67547       } else {
67548         events.push(se1.otherEvent, se2.otherEvent);
67549       }
67550
67551       if ((leftCoincide && rightCoincide) || leftCoincide) {
67552         // both line segments are equal or share the left endpoint
67553         se2.type = NON_CONTRIBUTING;
67554         se1.type = (se2.inOut === se1.inOut)
67555           ? SAME_TRANSITION : DIFFERENT_TRANSITION;
67556
67557         if (leftCoincide && !rightCoincide) {
67558           // honestly no idea, but changing events selection from [2, 1]
67559           // to [0, 1] fixes the overlapping self-intersecting polygons issue
67560           divideSegment(events[1].otherEvent, events[0].point, queue);
67561         }
67562         return 2;
67563       }
67564
67565       // the line segments share the right endpoint
67566       if (rightCoincide) {
67567         divideSegment(events[0], events[1].point, queue);
67568         return 3;
67569       }
67570
67571       // no line segment includes totally the other one
67572       if (events[0] !== events[3].otherEvent) {
67573         divideSegment(events[0], events[1].point, queue);
67574         divideSegment(events[1], events[2].point, queue);
67575         return 3;
67576       }
67577
67578       // one line segment includes the other one
67579       divideSegment(events[0], events[1].point, queue);
67580       divideSegment(events[3].otherEvent, events[2].point, queue);
67581
67582       return 3;
67583     }
67584
67585     /**
67586      * @param  {SweepEvent} le1
67587      * @param  {SweepEvent} le2
67588      * @return {Number}
67589      */
67590     function compareSegments(le1, le2) {
67591       if (le1 === le2) return 0;
67592
67593       // Segments are not collinear
67594       if (signedArea(le1.point, le1.otherEvent.point, le2.point) !== 0 ||
67595         signedArea(le1.point, le1.otherEvent.point, le2.otherEvent.point) !== 0) {
67596
67597         // If they share their left endpoint use the right endpoint to sort
67598         if (equals(le1.point, le2.point)) return le1.isBelow(le2.otherEvent.point) ? -1 : 1;
67599
67600         // Different left endpoint: use the left endpoint to sort
67601         if (le1.point[0] === le2.point[0]) return le1.point[1] < le2.point[1] ? -1 : 1;
67602
67603         // has the line segment associated to e1 been inserted
67604         // into S after the line segment associated to e2 ?
67605         if (compareEvents(le1, le2) === 1) return le2.isAbove(le1.point) ? -1 : 1;
67606
67607         // The line segment associated to e2 has been inserted
67608         // into S after the line segment associated to e1
67609         return le1.isBelow(le2.point) ? -1 : 1;
67610       }
67611
67612       if (le1.isSubject === le2.isSubject) { // same polygon
67613         let p1 = le1.point, p2 = le2.point;
67614         if (p1[0] === p2[0] && p1[1] === p2[1]/*equals(le1.point, le2.point)*/) {
67615           p1 = le1.otherEvent.point; p2 = le2.otherEvent.point;
67616           if (p1[0] === p2[0] && p1[1] === p2[1]) return 0;
67617           else return le1.contourId > le2.contourId ? 1 : -1;
67618         }
67619       } else { // Segments are collinear, but belong to separate polygons
67620         return le1.isSubject ? -1 : 1;
67621       }
67622
67623       return compareEvents(le1, le2) === 1 ? 1 : -1;
67624     }
67625
67626     function subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation) {
67627       const sweepLine = new SplayTree(compareSegments);
67628       const sortedEvents = [];
67629
67630       const rightbound = Math.min(sbbox[2], cbbox[2]);
67631
67632       let prev, next, begin;
67633
67634       while (eventQueue.length !== 0) {
67635         let event = eventQueue.pop();
67636         sortedEvents.push(event);
67637
67638         // optimization by bboxes for intersection and difference goes here
67639         if ((operation === INTERSECTION && event.point[0] > rightbound) ||
67640             (operation === DIFFERENCE   && event.point[0] > sbbox[2])) {
67641           break;
67642         }
67643
67644         if (event.left) {
67645           next  = prev = sweepLine.insert(event);
67646           begin = sweepLine.minNode();
67647
67648           if (prev !== begin) prev = sweepLine.prev(prev);
67649           else                prev = null;
67650
67651           next = sweepLine.next(next);
67652
67653           const prevEvent = prev ? prev.key : null;
67654           let prevprevEvent;
67655           computeFields(event, prevEvent, operation);
67656           if (next) {
67657             if (possibleIntersection(event, next.key, eventQueue) === 2) {
67658               computeFields(event, prevEvent, operation);
67659               computeFields(event, next.key, operation);
67660             }
67661           }
67662
67663           if (prev) {
67664             if (possibleIntersection(prev.key, event, eventQueue) === 2) {
67665               let prevprev = prev;
67666               if (prevprev !== begin) prevprev = sweepLine.prev(prevprev);
67667               else                    prevprev = null;
67668
67669               prevprevEvent = prevprev ? prevprev.key : null;
67670               computeFields(prevEvent, prevprevEvent, operation);
67671               computeFields(event,     prevEvent,     operation);
67672             }
67673           }
67674         } else {
67675           event = event.otherEvent;
67676           next = prev = sweepLine.find(event);
67677
67678           if (prev && next) {
67679
67680             if (prev !== begin) prev = sweepLine.prev(prev);
67681             else                prev = null;
67682
67683             next = sweepLine.next(next);
67684             sweepLine.remove(event);
67685
67686             if (next && prev) {
67687               possibleIntersection(prev.key, next.key, eventQueue);
67688             }
67689           }
67690         }
67691       }
67692       return sortedEvents;
67693     }
67694
67695     class Contour {
67696
67697       /**
67698        * Contour
67699        *
67700        * @class {Contour}
67701        */
67702       constructor() {
67703         this.points = [];
67704         this.holeIds = [];
67705         this.holeOf = null;
67706         this.depth = null;
67707       }
67708
67709       isExterior() {
67710         return this.holeOf == null;
67711       }
67712
67713     }
67714
67715     /**
67716      * @param  {Array.<SweepEvent>} sortedEvents
67717      * @return {Array.<SweepEvent>}
67718      */
67719     function orderEvents(sortedEvents) {
67720       let event, i, len, tmp;
67721       const resultEvents = [];
67722       for (i = 0, len = sortedEvents.length; i < len; i++) {
67723         event = sortedEvents[i];
67724         if ((event.left && event.inResult) ||
67725           (!event.left && event.otherEvent.inResult)) {
67726           resultEvents.push(event);
67727         }
67728       }
67729       // Due to overlapping edges the resultEvents array can be not wholly sorted
67730       let sorted = false;
67731       while (!sorted) {
67732         sorted = true;
67733         for (i = 0, len = resultEvents.length; i < len; i++) {
67734           if ((i + 1) < len &&
67735             compareEvents(resultEvents[i], resultEvents[i + 1]) === 1) {
67736             tmp = resultEvents[i];
67737             resultEvents[i] = resultEvents[i + 1];
67738             resultEvents[i + 1] = tmp;
67739             sorted = false;
67740           }
67741         }
67742       }
67743
67744
67745       for (i = 0, len = resultEvents.length; i < len; i++) {
67746         event = resultEvents[i];
67747         event.otherPos = i;
67748       }
67749
67750       // imagine, the right event is found in the beginning of the queue,
67751       // when his left counterpart is not marked yet
67752       for (i = 0, len = resultEvents.length; i < len; i++) {
67753         event = resultEvents[i];
67754         if (!event.left) {
67755           tmp = event.otherPos;
67756           event.otherPos = event.otherEvent.otherPos;
67757           event.otherEvent.otherPos = tmp;
67758         }
67759       }
67760
67761       return resultEvents;
67762     }
67763
67764
67765     /**
67766      * @param  {Number} pos
67767      * @param  {Array.<SweepEvent>} resultEvents
67768      * @param  {Object>}    processed
67769      * @return {Number}
67770      */
67771     function nextPos(pos, resultEvents, processed, origPos) {
67772       let newPos = pos + 1,
67773           p = resultEvents[pos].point,
67774           p1;
67775       const length = resultEvents.length;
67776
67777       if (newPos < length)
67778         p1 = resultEvents[newPos].point;
67779
67780       while (newPos < length && p1[0] === p[0] && p1[1] === p[1]) {
67781         if (!processed[newPos]) {
67782           return newPos;
67783         } else   {
67784           newPos++;
67785         }
67786         p1 = resultEvents[newPos].point;
67787       }
67788
67789       newPos = pos - 1;
67790
67791       while (processed[newPos] && newPos > origPos) {
67792         newPos--;
67793       }
67794
67795       return newPos;
67796     }
67797
67798
67799     function initializeContourFromContext(event, contours, contourId) {
67800       const contour = new Contour();
67801       if (event.prevInResult != null) {
67802         const prevInResult = event.prevInResult;
67803         // Note that it is valid to query the "previous in result" for its output contour id,
67804         // because we must have already processed it (i.e., assigned an output contour id)
67805         // in an earlier iteration, otherwise it wouldn't be possible that it is "previous in
67806         // result".
67807         const lowerContourId = prevInResult.outputContourId;
67808         const lowerResultTransition = prevInResult.resultTransition;
67809         if (lowerResultTransition > 0) {
67810           // We are inside. Now we have to check if the thing below us is another hole or
67811           // an exterior contour.
67812           const lowerContour = contours[lowerContourId];
67813           if (lowerContour.holeOf != null) {
67814             // The lower contour is a hole => Connect the new contour as a hole to its parent,
67815             // and use same depth.
67816             const parentContourId = lowerContour.holeOf;
67817             contours[parentContourId].holeIds.push(contourId);
67818             contour.holeOf = parentContourId;
67819             contour.depth = contours[lowerContourId].depth;
67820           } else {
67821             // The lower contour is an exterior contour => Connect the new contour as a hole,
67822             // and increment depth.
67823             contours[lowerContourId].holeIds.push(contourId);
67824             contour.holeOf = lowerContourId;
67825             contour.depth = contours[lowerContourId].depth + 1;
67826           }
67827         } else {
67828           // We are outside => this contour is an exterior contour of same depth.
67829           contour.holeOf = null;
67830           contour.depth = contours[lowerContourId].depth;
67831         }
67832       } else {
67833         // There is no lower/previous contour => this contour is an exterior contour of depth 0.
67834         contour.holeOf = null;
67835         contour.depth = 0;
67836       }
67837       return contour;
67838     }
67839
67840     /**
67841      * @param  {Array.<SweepEvent>} sortedEvents
67842      * @return {Array.<*>} polygons
67843      */
67844     function connectEdges(sortedEvents) {
67845       let i, len;
67846       const resultEvents = orderEvents(sortedEvents);
67847
67848       // "false"-filled array
67849       const processed = {};
67850       const contours = [];
67851
67852       for (i = 0, len = resultEvents.length; i < len; i++) {
67853
67854         if (processed[i]) {
67855           continue;
67856         }
67857
67858         const contourId = contours.length;
67859         const contour = initializeContourFromContext(resultEvents[i], contours, contourId);
67860
67861         // Helper function that combines marking an event as processed with assigning its output contour ID
67862         const markAsProcessed = (pos) => {
67863           processed[pos] = true;
67864           resultEvents[pos].outputContourId = contourId;
67865         };
67866
67867         let pos = i;
67868         let origPos = i;
67869
67870         const initial = resultEvents[i].point;
67871         contour.points.push(initial);
67872
67873         /* eslint no-constant-condition: "off" */
67874         while (true) {
67875           markAsProcessed(pos);
67876
67877           pos = resultEvents[pos].otherPos;
67878
67879           markAsProcessed(pos);
67880           contour.points.push(resultEvents[pos].point);
67881
67882           pos = nextPos(pos, resultEvents, processed, origPos);
67883
67884           if (pos == origPos) {
67885             break;
67886           }
67887         }
67888
67889         contours.push(contour);
67890       }
67891
67892       return contours;
67893     }
67894
67895     var tinyqueue = TinyQueue;
67896     var _default = TinyQueue;
67897
67898     function TinyQueue(data, compare) {
67899         if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
67900
67901         this.data = data || [];
67902         this.length = this.data.length;
67903         this.compare = compare || defaultCompare;
67904
67905         if (this.length > 0) {
67906             for (var i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
67907         }
67908     }
67909
67910     function defaultCompare(a, b) {
67911         return a < b ? -1 : a > b ? 1 : 0;
67912     }
67913
67914     TinyQueue.prototype = {
67915
67916         push: function (item) {
67917             this.data.push(item);
67918             this.length++;
67919             this._up(this.length - 1);
67920         },
67921
67922         pop: function () {
67923             if (this.length === 0) return undefined;
67924
67925             var top = this.data[0];
67926             this.length--;
67927
67928             if (this.length > 0) {
67929                 this.data[0] = this.data[this.length];
67930                 this._down(0);
67931             }
67932             this.data.pop();
67933
67934             return top;
67935         },
67936
67937         peek: function () {
67938             return this.data[0];
67939         },
67940
67941         _up: function (pos) {
67942             var data = this.data;
67943             var compare = this.compare;
67944             var item = data[pos];
67945
67946             while (pos > 0) {
67947                 var parent = (pos - 1) >> 1;
67948                 var current = data[parent];
67949                 if (compare(item, current) >= 0) break;
67950                 data[pos] = current;
67951                 pos = parent;
67952             }
67953
67954             data[pos] = item;
67955         },
67956
67957         _down: function (pos) {
67958             var data = this.data;
67959             var compare = this.compare;
67960             var halfLength = this.length >> 1;
67961             var item = data[pos];
67962
67963             while (pos < halfLength) {
67964                 var left = (pos << 1) + 1;
67965                 var right = left + 1;
67966                 var best = data[left];
67967
67968                 if (right < this.length && compare(data[right], best) < 0) {
67969                     left = right;
67970                     best = data[right];
67971                 }
67972                 if (compare(best, item) >= 0) break;
67973
67974                 data[pos] = best;
67975                 pos = left;
67976             }
67977
67978             data[pos] = item;
67979         }
67980     };
67981     tinyqueue.default = _default;
67982
67983     const max = Math.max;
67984     const min = Math.min;
67985
67986     let contourId = 0;
67987
67988
67989     function processPolygon(contourOrHole, isSubject, depth, Q, bbox, isExteriorRing) {
67990       let i, len, s1, s2, e1, e2;
67991       for (i = 0, len = contourOrHole.length - 1; i < len; i++) {
67992         s1 = contourOrHole[i];
67993         s2 = contourOrHole[i + 1];
67994         e1 = new SweepEvent(s1, false, undefined, isSubject);
67995         e2 = new SweepEvent(s2, false, e1,        isSubject);
67996         e1.otherEvent = e2;
67997
67998         if (s1[0] === s2[0] && s1[1] === s2[1]) {
67999           continue; // skip collapsed edges, or it breaks
68000         }
68001
68002         e1.contourId = e2.contourId = depth;
68003         if (!isExteriorRing) {
68004           e1.isExteriorRing = false;
68005           e2.isExteriorRing = false;
68006         }
68007         if (compareEvents(e1, e2) > 0) {
68008           e2.left = true;
68009         } else {
68010           e1.left = true;
68011         }
68012
68013         const x = s1[0], y = s1[1];
68014         bbox[0] = min(bbox[0], x);
68015         bbox[1] = min(bbox[1], y);
68016         bbox[2] = max(bbox[2], x);
68017         bbox[3] = max(bbox[3], y);
68018
68019         // Pushing it so the queue is sorted from left to right,
68020         // with object on the left having the highest priority.
68021         Q.push(e1);
68022         Q.push(e2);
68023       }
68024     }
68025
68026
68027     function fillQueue(subject, clipping, sbbox, cbbox, operation) {
68028       const eventQueue = new tinyqueue(null, compareEvents);
68029       let polygonSet, isExteriorRing, i, ii, j, jj; //, k, kk;
68030
68031       for (i = 0, ii = subject.length; i < ii; i++) {
68032         polygonSet = subject[i];
68033         for (j = 0, jj = polygonSet.length; j < jj; j++) {
68034           isExteriorRing = j === 0;
68035           if (isExteriorRing) contourId++;
68036           processPolygon(polygonSet[j], true, contourId, eventQueue, sbbox, isExteriorRing);
68037         }
68038       }
68039
68040       for (i = 0, ii = clipping.length; i < ii; i++) {
68041         polygonSet = clipping[i];
68042         for (j = 0, jj = polygonSet.length; j < jj; j++) {
68043           isExteriorRing = j === 0;
68044           if (operation === DIFFERENCE) isExteriorRing = false;
68045           if (isExteriorRing) contourId++;
68046           processPolygon(polygonSet[j], false, contourId, eventQueue, cbbox, isExteriorRing);
68047         }
68048       }
68049
68050       return eventQueue;
68051     }
68052
68053     const EMPTY = [];
68054
68055
68056     function trivialOperation(subject, clipping, operation) {
68057       let result = null;
68058       if (subject.length * clipping.length === 0) {
68059         if        (operation === INTERSECTION) {
68060           result = EMPTY;
68061         } else if (operation === DIFFERENCE) {
68062           result = subject;
68063         } else if (operation === UNION ||
68064                    operation === XOR) {
68065           result = (subject.length === 0) ? clipping : subject;
68066         }
68067       }
68068       return result;
68069     }
68070
68071
68072     function compareBBoxes(subject, clipping, sbbox, cbbox, operation) {
68073       let result = null;
68074       if (sbbox[0] > cbbox[2] ||
68075           cbbox[0] > sbbox[2] ||
68076           sbbox[1] > cbbox[3] ||
68077           cbbox[1] > sbbox[3]) {
68078         if        (operation === INTERSECTION) {
68079           result = EMPTY;
68080         } else if (operation === DIFFERENCE) {
68081           result = subject;
68082         } else if (operation === UNION ||
68083                    operation === XOR) {
68084           result = subject.concat(clipping);
68085         }
68086       }
68087       return result;
68088     }
68089
68090
68091     function boolean(subject, clipping, operation) {
68092       if (typeof subject[0][0][0] === 'number') {
68093         subject = [subject];
68094       }
68095       if (typeof clipping[0][0][0] === 'number') {
68096         clipping = [clipping];
68097       }
68098       let trivial = trivialOperation(subject, clipping, operation);
68099       if (trivial) {
68100         return trivial === EMPTY ? null : trivial;
68101       }
68102       const sbbox = [Infinity, Infinity, -Infinity, -Infinity];
68103       const cbbox = [Infinity, Infinity, -Infinity, -Infinity];
68104
68105       // console.time('fill queue');
68106       const eventQueue = fillQueue(subject, clipping, sbbox, cbbox, operation);
68107       //console.timeEnd('fill queue');
68108
68109       trivial = compareBBoxes(subject, clipping, sbbox, cbbox, operation);
68110       if (trivial) {
68111         return trivial === EMPTY ? null : trivial;
68112       }
68113       // console.time('subdivide edges');
68114       const sortedEvents = subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation);
68115       //console.timeEnd('subdivide edges');
68116
68117       // console.time('connect vertices');
68118       const contours = connectEdges(sortedEvents);
68119       //console.timeEnd('connect vertices');
68120
68121       // Convert contours to polygons
68122       const polygons = [];
68123       for (let i = 0; i < contours.length; i++) {
68124         let contour = contours[i];
68125         if (contour.isExterior()) {
68126           // The exterior ring goes first
68127           let rings = [contour.points];
68128           // Followed by holes if any
68129           for (let j = 0; j < contour.holeIds.length; j++) {
68130             let holeId = contour.holeIds[j];
68131             rings.push(contours[holeId].points);
68132           }
68133           polygons.push(rings);
68134         }
68135       }
68136
68137       return polygons;
68138     }
68139
68140     function intersection (subject, clipping) {
68141       return boolean(subject, clipping, INTERSECTION);
68142     }
68143
68144     /**
68145      * @class VertexGeometry
68146      * @abstract
68147      * @classdesc Represents a vertex geometry.
68148      */
68149     class VertexGeometry extends Geometry {
68150         /**
68151          * Create a vertex geometry.
68152          *
68153          * @constructor
68154          * @ignore
68155          */
68156         constructor() {
68157             super();
68158             this._subsampleThreshold = 0.005;
68159         }
68160         /**
68161          * Finds the polygon pole of inaccessibility, the most distant internal
68162          * point from the polygon outline.
68163          *
68164          * @param {Array<Array<number>>} points2d - 2d points of outline to triangulate.
68165          * @returns {Array<number>} Point of inaccessibility.
68166          * @ignore
68167          */
68168         _getPoleOfInaccessibility2d(points2d) {
68169             let pole2d = polylabel_1([points2d], 3e-2);
68170             return pole2d;
68171         }
68172         _project(points2d, transform) {
68173             const camera = this._createCamera(transform.upVector().toArray(), transform.unprojectSfM([0, 0], 0), transform.unprojectSfM([0, 0], 10));
68174             return this._deunproject(points2d, transform, camera);
68175         }
68176         _subsample(points2d, threshold = this._subsampleThreshold) {
68177             const subsampled = [];
68178             const length = points2d.length;
68179             for (let index = 0; index < length; index++) {
68180                 const p1 = points2d[index];
68181                 const p2 = points2d[(index + 1) % length];
68182                 subsampled.push(p1);
68183                 const dist = Math.sqrt(Math.pow((p2[0] - p1[0]), 2) + Math.pow((p2[1] - p1[1]), 2));
68184                 const subsamples = Math.floor(dist / threshold);
68185                 const coeff = 1 / (subsamples + 1);
68186                 for (let i = 1; i <= subsamples; i++) {
68187                     const alpha = i * coeff;
68188                     const subsample = [
68189                         (1 - alpha) * p1[0] + alpha * p2[0],
68190                         (1 - alpha) * p1[1] + alpha * p2[1],
68191                     ];
68192                     subsampled.push(subsample);
68193                 }
68194             }
68195             return subsampled;
68196         }
68197         /**
68198          * Triangulates a 2d polygon and returns the triangle
68199          * representation as a flattened array of 3d points.
68200          *
68201          * @param {Array<Array<number>>} points2d - 2d points of outline to triangulate.
68202          * @param {Array<Array<number>>} points3d - 3d points of outline corresponding to the 2d points.
68203          * @param {Array<Array<Array<number>>>} [holes2d] - 2d points of holes to triangulate.
68204          * @param {Array<Array<Array<number>>>} [holes3d] - 3d points of holes corresponding to the 2d points.
68205          * @returns {Array<number>} Flattened array of 3d points ordered based on the triangles.
68206          * @ignore
68207          */
68208         _triangulate(points2d, points3d, holes2d, holes3d) {
68209             let data = [points2d.slice(0, -1)];
68210             for (let hole2d of holes2d != null ? holes2d : []) {
68211                 data.push(hole2d.slice(0, -1));
68212             }
68213             let points = points3d.slice(0, -1);
68214             for (let hole3d of holes3d != null ? holes3d : []) {
68215                 points = points.concat(hole3d.slice(0, -1));
68216             }
68217             let flattened = earcut_1.flatten(data);
68218             let indices = earcut_1(flattened.vertices, flattened.holes, flattened.dimensions);
68219             let triangles = [];
68220             for (let i = 0; i < indices.length; ++i) {
68221                 let point = points[indices[i]];
68222                 triangles.push(point[0]);
68223                 triangles.push(point[1]);
68224                 triangles.push(point[2]);
68225             }
68226             return triangles;
68227         }
68228         _triangulateSpherical(points2d, holes2d, transform) {
68229             const triangles = [];
68230             const epsilon = 1e-9;
68231             const subareasX = 3;
68232             const subareasY = 3;
68233             for (let x = 0; x < subareasX; x++) {
68234                 for (let y = 0; y < subareasY; y++) {
68235                     const epsilonX0 = x === 0 ? -epsilon : epsilon;
68236                     const epsilonY0 = y === 0 ? -epsilon : epsilon;
68237                     const x0 = x / subareasX + epsilonX0;
68238                     const y0 = y / subareasY + epsilonY0;
68239                     const x1 = (x + 1) / subareasX + epsilon;
68240                     const y1 = (y + 1) / subareasY + epsilon;
68241                     const bbox2d = [
68242                         [x0, y0],
68243                         [x0, y1],
68244                         [x1, y1],
68245                         [x1, y0],
68246                         [x0, y0],
68247                     ];
68248                     const lookat2d = [
68249                         (2 * x + 1) / (2 * subareasX),
68250                         (2 * y + 1) / (2 * subareasY),
68251                     ];
68252                     triangles.push(...this._triangulateSubarea(points2d, holes2d, bbox2d, lookat2d, transform));
68253                 }
68254             }
68255             return triangles;
68256         }
68257         _unproject(points2d, transform, distance = 200) {
68258             return points2d
68259                 .map((point) => {
68260                 return transform.unprojectBasic(point, distance);
68261             });
68262         }
68263         _createCamera(upVector, position, lookAt) {
68264             const camera = new Camera$1();
68265             camera.up.copy(new Vector3().fromArray(upVector));
68266             camera.position.copy(new Vector3().fromArray(position));
68267             camera.lookAt(new Vector3().fromArray(lookAt));
68268             camera.updateMatrix();
68269             camera.updateMatrixWorld(true);
68270             return camera;
68271         }
68272         _deunproject(points2d, transform, camera) {
68273             return points2d
68274                 .map((point2d) => {
68275                 const pointWorld = transform.unprojectBasic(point2d, 10000);
68276                 const pointCamera = new Vector3(pointWorld[0], pointWorld[1], pointWorld[2])
68277                     .applyMatrix4(camera.matrixWorldInverse);
68278                 return [pointCamera.x / pointCamera.z, pointCamera.y / pointCamera.z];
68279             });
68280         }
68281         _triangulateSubarea(points2d, holes2d, bbox2d, lookat2d, transform) {
68282             const intersections = intersection([points2d, ...holes2d], [bbox2d]);
68283             if (!intersections) {
68284                 return [];
68285             }
68286             const triangles = [];
68287             const threshold = this._subsampleThreshold;
68288             const camera = this._createCamera(transform.upVector().toArray(), transform.unprojectSfM([0, 0], 0), transform.unprojectBasic(lookat2d, 10));
68289             for (const intersection of intersections) {
68290                 const subsampledPolygon2d = this._subsample(intersection[0], threshold);
68291                 const polygon2d = this._deunproject(subsampledPolygon2d, transform, camera);
68292                 const polygon3d = this._unproject(subsampledPolygon2d, transform);
68293                 const polygonHoles2d = [];
68294                 const polygonHoles3d = [];
68295                 for (let i = 1; i < intersection.length; i++) {
68296                     let subsampledHole2d = this._subsample(intersection[i], threshold);
68297                     const hole2d = this._deunproject(subsampledHole2d, transform, camera);
68298                     const hole3d = this._unproject(subsampledHole2d, transform);
68299                     polygonHoles2d.push(hole2d);
68300                     polygonHoles3d.push(hole3d);
68301                 }
68302                 triangles.push(...this._triangulate(polygon2d, polygon3d, polygonHoles2d, polygonHoles3d));
68303             }
68304             return triangles;
68305         }
68306     }
68307
68308     /**
68309      * @class RectGeometry
68310      *
68311      * @classdesc Represents a rectangle geometry in the 2D basic image coordinate system.
68312      *
68313      * @example
68314      * ```js
68315      * var basicRect = [0.5, 0.3, 0.7, 0.4];
68316      * var rectGeometry = new RectGeometry(basicRect);
68317      * ```
68318      */
68319     class RectGeometry extends VertexGeometry {
68320         /**
68321          * Create a rectangle geometry.
68322          *
68323          * @constructor
68324          * @param {Array<number>} rect - An array representing the top-left and bottom-right
68325          * corners of the rectangle in basic coordinates. Ordered according to [x0, y0, x1, y1].
68326          *
68327          * @throws {GeometryTagError} Rectangle coordinates must be valid basic coordinates.
68328          */
68329         constructor(rect) {
68330             super();
68331             if (rect.length !== 4) {
68332                 throw new GeometryTagError("Rectangle needs to have four values.");
68333             }
68334             if (rect[1] > rect[3]) {
68335                 throw new GeometryTagError("Basic Y coordinates values can not be inverted.");
68336             }
68337             for (let coord of rect) {
68338                 if (coord < 0 || coord > 1) {
68339                     throw new GeometryTagError("Basic coordinates must be on the interval [0, 1].");
68340                 }
68341             }
68342             this._anchorIndex = undefined;
68343             this._rect = rect.slice(0, 4);
68344             this._inverted = this._rect[0] > this._rect[2];
68345         }
68346         /**
68347          * Get anchor index property.
68348          *
68349          * @returns {number} Index representing the current anchor property if
68350          * achoring indexing has been initialized. If anchor indexing has not been
68351          * initialized or has been terminated undefined will be returned.
68352          * @ignore
68353          */
68354         get anchorIndex() {
68355             return this._anchorIndex;
68356         }
68357         /**
68358          * Get inverted property.
68359          *
68360          * @returns {boolean} Boolean determining whether the rect geometry is
68361          * inverted. For spherical the rect geometrye may be inverted.
68362          * @ignore
68363          */
68364         get inverted() {
68365             return this._inverted;
68366         }
68367         /**
68368          * Get rect property.
68369          *
68370          * @returns {Array<number>} Array representing the top-left and bottom-right
68371          * corners of the rectangle in basic coordinates.
68372          */
68373         get rect() {
68374             return this._rect;
68375         }
68376         /**
68377          * Initialize anchor indexing to enable setting opposite vertex.
68378          *
68379          * @param {number} [index] - The index of the vertex to use as anchor.
68380          *
68381          * @throws {GeometryTagError} If anchor indexing has already been initialized.
68382          * @throws {GeometryTagError} If index is not valid (0 to 3).
68383          * @ignore
68384          */
68385         initializeAnchorIndexing(index) {
68386             if (this._anchorIndex !== undefined) {
68387                 throw new GeometryTagError("Anchor indexing is already initialized.");
68388             }
68389             if (index < 0 || index > 3) {
68390                 throw new GeometryTagError(`Invalid anchor index: ${index}.`);
68391             }
68392             this._anchorIndex = index === undefined ? 0 : index;
68393         }
68394         /**
68395          * Terminate anchor indexing to disable setting pposite vertex.
68396          * @ignore
68397          */
68398         terminateAnchorIndexing() {
68399             this._anchorIndex = undefined;
68400         }
68401         /**
68402          * Set the value of the vertex opposite to the anchor in the polygon
68403          * representation of the rectangle.
68404          *
68405          * @description Setting the opposite vertex may change the anchor index.
68406          *
68407          * @param {Array<number>} opposite - The new value of the vertex opposite to the anchor.
68408          * @param {Transform} transform - The transform of the image related to the rectangle.
68409          *
68410          * @throws {GeometryTagError} When anchor indexing has not been initialized.
68411          * @ignore
68412          */
68413         setOppositeVertex2d(opposite, transform) {
68414             if (this._anchorIndex === undefined) {
68415                 throw new GeometryTagError("Anchor indexing needs to be initialized.");
68416             }
68417             const changed = [
68418                 Math.max(0, Math.min(1, opposite[0])),
68419                 Math.max(0, Math.min(1, opposite[1])),
68420             ];
68421             const original = this._rect.slice();
68422             const anchor = this._anchorIndex === 0 ? [original[0], original[3]] :
68423                 this._anchorIndex === 1 ? [original[0], original[1]] :
68424                     this._anchorIndex === 2 ? [original[2], original[1]] :
68425                         [original[2], original[3]];
68426             if (isSpherical(transform.cameraType)) {
68427                 const deltaX = this._anchorIndex < 2 ?
68428                     changed[0] - original[2] :
68429                     changed[0] - original[0];
68430                 if (!this._inverted && this._anchorIndex < 2 && changed[0] < 0.25 && original[2] > 0.75 && deltaX < -0.5) {
68431                     // right side passes boundary rightward
68432                     this._inverted = true;
68433                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68434                 }
68435                 else if (!this._inverted && this._anchorIndex >= 2 && changed[0] < 0.25 && original[2] > 0.75 && deltaX < -0.5) {
68436                     // left side passes right side and boundary rightward
68437                     this._inverted = true;
68438                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68439                 }
68440                 else if (this._inverted && this._anchorIndex >= 2 && changed[0] < 0.25 && original[0] > 0.75 && deltaX < -0.5) {
68441                     this._inverted = false;
68442                     if (anchor[0] > changed[0]) {
68443                         // left side passes boundary rightward
68444                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68445                     }
68446                     else {
68447                         // left side passes right side and boundary rightward
68448                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68449                     }
68450                 }
68451                 else if (!this._inverted && this._anchorIndex >= 2 && changed[0] > 0.75 && original[0] < 0.25 && deltaX > 0.5) {
68452                     // left side passes boundary leftward
68453                     this._inverted = true;
68454                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68455                 }
68456                 else if (!this._inverted && this._anchorIndex < 2 && changed[0] > 0.75 && original[0] < 0.25 && deltaX > 0.5) {
68457                     // right side passes left side and boundary leftward
68458                     this._inverted = true;
68459                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68460                 }
68461                 else if (this._inverted && this._anchorIndex < 2 && changed[0] > 0.75 && original[2] < 0.25 && deltaX > 0.5) {
68462                     this._inverted = false;
68463                     if (anchor[0] > changed[0]) {
68464                         // right side passes boundary leftward
68465                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68466                     }
68467                     else {
68468                         // right side passes left side and boundary leftward
68469                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68470                     }
68471                 }
68472                 else if (this._inverted && this._anchorIndex < 2 && changed[0] > original[0]) {
68473                     // inverted and right side passes left side completing a loop
68474                     this._inverted = false;
68475                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68476                 }
68477                 else if (this._inverted && this._anchorIndex >= 2 && changed[0] < original[2]) {
68478                     // inverted and left side passes right side completing a loop
68479                     this._inverted = false;
68480                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68481                 }
68482                 else if (this._inverted) {
68483                     // if still inverted only top and bottom can switch
68484                     if (this._anchorIndex < 2) {
68485                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
68486                     }
68487                     else {
68488                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
68489                     }
68490                 }
68491                 else {
68492                     // if still not inverted treat as non spherical
68493                     if (anchor[0] <= changed[0] && anchor[1] > changed[1]) {
68494                         this._anchorIndex = 0;
68495                     }
68496                     else if (anchor[0] <= changed[0] && anchor[1] <= changed[1]) {
68497                         this._anchorIndex = 1;
68498                     }
68499                     else if (anchor[0] > changed[0] && anchor[1] <= changed[1]) {
68500                         this._anchorIndex = 2;
68501                     }
68502                     else {
68503                         this._anchorIndex = 3;
68504                     }
68505                 }
68506                 const rect = [];
68507                 if (this._anchorIndex === 0) {
68508                     rect[0] = anchor[0];
68509                     rect[1] = changed[1];
68510                     rect[2] = changed[0];
68511                     rect[3] = anchor[1];
68512                 }
68513                 else if (this._anchorIndex === 1) {
68514                     rect[0] = anchor[0];
68515                     rect[1] = anchor[1];
68516                     rect[2] = changed[0];
68517                     rect[3] = changed[1];
68518                 }
68519                 else if (this._anchorIndex === 2) {
68520                     rect[0] = changed[0];
68521                     rect[1] = anchor[1];
68522                     rect[2] = anchor[0];
68523                     rect[3] = changed[1];
68524                 }
68525                 else {
68526                     rect[0] = changed[0];
68527                     rect[1] = changed[1];
68528                     rect[2] = anchor[0];
68529                     rect[3] = anchor[1];
68530                 }
68531                 if (!this._inverted && rect[0] > rect[2] ||
68532                     this._inverted && rect[0] < rect[2]) {
68533                     rect[0] = original[0];
68534                     rect[2] = original[2];
68535                 }
68536                 if (rect[1] > rect[3]) {
68537                     rect[1] = original[1];
68538                     rect[3] = original[3];
68539                 }
68540                 this._rect[0] = rect[0];
68541                 this._rect[1] = rect[1];
68542                 this._rect[2] = rect[2];
68543                 this._rect[3] = rect[3];
68544             }
68545             else {
68546                 if (anchor[0] <= changed[0] && anchor[1] > changed[1]) {
68547                     this._anchorIndex = 0;
68548                 }
68549                 else if (anchor[0] <= changed[0] && anchor[1] <= changed[1]) {
68550                     this._anchorIndex = 1;
68551                 }
68552                 else if (anchor[0] > changed[0] && anchor[1] <= changed[1]) {
68553                     this._anchorIndex = 2;
68554                 }
68555                 else {
68556                     this._anchorIndex = 3;
68557                 }
68558                 const rect = [];
68559                 if (this._anchorIndex === 0) {
68560                     rect[0] = anchor[0];
68561                     rect[1] = changed[1];
68562                     rect[2] = changed[0];
68563                     rect[3] = anchor[1];
68564                 }
68565                 else if (this._anchorIndex === 1) {
68566                     rect[0] = anchor[0];
68567                     rect[1] = anchor[1];
68568                     rect[2] = changed[0];
68569                     rect[3] = changed[1];
68570                 }
68571                 else if (this._anchorIndex === 2) {
68572                     rect[0] = changed[0];
68573                     rect[1] = anchor[1];
68574                     rect[2] = anchor[0];
68575                     rect[3] = changed[1];
68576                 }
68577                 else {
68578                     rect[0] = changed[0];
68579                     rect[1] = changed[1];
68580                     rect[2] = anchor[0];
68581                     rect[3] = anchor[1];
68582                 }
68583                 if (rect[0] > rect[2]) {
68584                     rect[0] = original[0];
68585                     rect[2] = original[2];
68586                 }
68587                 if (rect[1] > rect[3]) {
68588                     rect[1] = original[1];
68589                     rect[3] = original[3];
68590                 }
68591                 this._rect[0] = rect[0];
68592                 this._rect[1] = rect[1];
68593                 this._rect[2] = rect[2];
68594                 this._rect[3] = rect[3];
68595             }
68596             this._notifyChanged$.next(this);
68597         }
68598         /**
68599          * Set the value of a vertex in the polygon representation of the rectangle.
68600          *
68601          * @description The polygon is defined to have the first vertex at the
68602          * bottom-left corner with the rest of the vertices following in clockwise order.
68603          *
68604          * @param {number} index - The index of the vertex to be set.
68605          * @param {Array<number>} value - The new value of the vertex.
68606          * @param {Transform} transform - The transform of the image related to the rectangle.
68607          * @ignore
68608          */
68609         setVertex2d(index, value, transform) {
68610             let original = this._rect.slice();
68611             let changed = [
68612                 Math.max(0, Math.min(1, value[0])),
68613                 Math.max(0, Math.min(1, value[1])),
68614             ];
68615             let rect = [];
68616             if (index === 0) {
68617                 rect[0] = changed[0];
68618                 rect[1] = original[1];
68619                 rect[2] = original[2];
68620                 rect[3] = changed[1];
68621             }
68622             else if (index === 1) {
68623                 rect[0] = changed[0];
68624                 rect[1] = changed[1];
68625                 rect[2] = original[2];
68626                 rect[3] = original[3];
68627             }
68628             else if (index === 2) {
68629                 rect[0] = original[0];
68630                 rect[1] = changed[1];
68631                 rect[2] = changed[0];
68632                 rect[3] = original[3];
68633             }
68634             else if (index === 3) {
68635                 rect[0] = original[0];
68636                 rect[1] = original[1];
68637                 rect[2] = changed[0];
68638                 rect[3] = changed[1];
68639             }
68640             if (isSpherical(transform.cameraType)) {
68641                 let passingBoundaryLeftward = index < 2 && changed[0] > 0.75 && original[0] < 0.25 ||
68642                     index >= 2 && this._inverted && changed[0] > 0.75 && original[2] < 0.25;
68643                 let passingBoundaryRightward = index < 2 && this._inverted && changed[0] < 0.25 && original[0] > 0.75 ||
68644                     index >= 2 && changed[0] < 0.25 && original[2] > 0.75;
68645                 if (passingBoundaryLeftward || passingBoundaryRightward) {
68646                     this._inverted = !this._inverted;
68647                 }
68648                 else {
68649                     if (rect[0] - original[0] < -0.25) {
68650                         rect[0] = original[0];
68651                     }
68652                     if (rect[2] - original[2] > 0.25) {
68653                         rect[2] = original[2];
68654                     }
68655                 }
68656                 if (!this._inverted && rect[0] > rect[2] ||
68657                     this._inverted && rect[0] < rect[2]) {
68658                     rect[0] = original[0];
68659                     rect[2] = original[2];
68660                 }
68661             }
68662             else {
68663                 if (rect[0] > rect[2]) {
68664                     rect[0] = original[0];
68665                     rect[2] = original[2];
68666                 }
68667             }
68668             if (rect[1] > rect[3]) {
68669                 rect[1] = original[1];
68670                 rect[3] = original[3];
68671             }
68672             this._rect[0] = rect[0];
68673             this._rect[1] = rect[1];
68674             this._rect[2] = rect[2];
68675             this._rect[3] = rect[3];
68676             this._notifyChanged$.next(this);
68677         }
68678         /** @ignore */
68679         setCentroid2d(value, transform) {
68680             let original = this._rect.slice();
68681             let x0 = original[0];
68682             let x1 = this._inverted ? original[2] + 1 : original[2];
68683             let y0 = original[1];
68684             let y1 = original[3];
68685             let centerX = x0 + (x1 - x0) / 2;
68686             let centerY = y0 + (y1 - y0) / 2;
68687             let translationX = 0;
68688             if (isSpherical(transform.cameraType)) {
68689                 translationX = this._inverted ? value[0] + 1 - centerX : value[0] - centerX;
68690             }
68691             else {
68692                 let minTranslationX = -x0;
68693                 let maxTranslationX = 1 - x1;
68694                 translationX = Math.max(minTranslationX, Math.min(maxTranslationX, value[0] - centerX));
68695             }
68696             let minTranslationY = -y0;
68697             let maxTranslationY = 1 - y1;
68698             let translationY = Math.max(minTranslationY, Math.min(maxTranslationY, value[1] - centerY));
68699             this._rect[0] = original[0] + translationX;
68700             this._rect[1] = original[1] + translationY;
68701             this._rect[2] = original[2] + translationX;
68702             this._rect[3] = original[3] + translationY;
68703             if (this._rect[0] < 0) {
68704                 this._rect[0] += 1;
68705                 this._inverted = !this._inverted;
68706             }
68707             else if (this._rect[0] > 1) {
68708                 this._rect[0] -= 1;
68709                 this._inverted = !this._inverted;
68710             }
68711             if (this._rect[2] < 0) {
68712                 this._rect[2] += 1;
68713                 this._inverted = !this._inverted;
68714             }
68715             else if (this._rect[2] > 1) {
68716                 this._rect[2] -= 1;
68717                 this._inverted = !this._inverted;
68718             }
68719             this._notifyChanged$.next(this);
68720         }
68721         /**
68722          * Get the 3D coordinates for the vertices of the rectangle with
68723          * interpolated points along the lines.
68724          *
68725          * @param {Transform} transform - The transform of the image related to
68726          * the rectangle.
68727          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates
68728          * representing the rectangle.
68729          * @ignore
68730          */
68731         getPoints3d(transform) {
68732             return this._getPoints2d()
68733                 .map((point) => {
68734                 return transform.unprojectBasic(point, 200);
68735             });
68736         }
68737         /**
68738          * Get the coordinates of a vertex from the polygon representation of the geometry.
68739          *
68740          * @description The first vertex represents the bottom-left corner with the rest of
68741          * the vertices following in clockwise order. The method shifts the right side
68742          * coordinates of the rectangle by one unit to ensure that the vertices are ordered
68743          * clockwise.
68744          *
68745          * @param {number} index - Vertex index.
68746          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
68747          * @ignore
68748          */
68749         getVertex2d(index) {
68750             return this._rectToVertices2d(this._rect)[index];
68751         }
68752         /**
68753          * Get the coordinates of a vertex from the polygon representation of the geometry.
68754          *
68755          * @description The first vertex represents the bottom-left corner with the rest of
68756          * the vertices following in clockwise order. The coordinates will not be shifted
68757          * so they may not appear in clockwise order when layed out on the plane.
68758          *
68759          * @param {number} index - Vertex index.
68760          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
68761          * @ignore
68762          */
68763         getNonAdjustedVertex2d(index) {
68764             return this._rectToNonAdjustedVertices2d(this._rect)[index];
68765         }
68766         /**
68767          * Get a vertex from the polygon representation of the 3D coordinates for the
68768          * vertices of the geometry.
68769          *
68770          * @description The first vertex represents the bottom-left corner with the rest of
68771          * the vertices following in clockwise order.
68772          *
68773          * @param {number} index - Vertex index.
68774          * @param {Transform} transform - The transform of the image related to the geometry.
68775          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates representing
68776          * the vertices of the geometry.
68777          * @ignore
68778          */
68779         getVertex3d(index, transform) {
68780             return transform.unprojectBasic(this._rectToVertices2d(this._rect)[index], 200);
68781         }
68782         /**
68783          * Get a polygon representation of the 2D basic coordinates for the vertices of the rectangle.
68784          *
68785          * @description The first vertex represents the bottom-left corner with the rest of
68786          * the vertices following in clockwise order.
68787          *
68788          * @returns {Array<Array<number>>} Polygon array of 2D basic coordinates representing
68789          * the rectangle vertices.
68790          * @ignore
68791          */
68792         getVertices2d() {
68793             return this._rectToVertices2d(this._rect);
68794         }
68795         /**
68796          * Get a polygon representation of the 3D coordinates for the vertices of the rectangle.
68797          *
68798          * @description The first vertex represents the bottom-left corner with the rest of
68799          * the vertices following in clockwise order.
68800          *
68801          * @param {Transform} transform - The transform of the image related to the rectangle.
68802          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates representing
68803          * the rectangle vertices.
68804          * @ignore
68805          */
68806         getVertices3d(transform) {
68807             return this._rectToVertices2d(this._rect)
68808                 .map((vertex) => {
68809                 return transform.unprojectBasic(vertex, 200);
68810             });
68811         }
68812         /** @ignore */
68813         getCentroid2d() {
68814             const rect = this._rect;
68815             const x0 = rect[0];
68816             const x1 = this._inverted ? rect[2] + 1 : rect[2];
68817             const y0 = rect[1];
68818             const y1 = rect[3];
68819             const centroidX = (x0 + x1) / 2;
68820             const centroidY = (y0 + y1) / 2;
68821             return [centroidX, centroidY];
68822         }
68823         /** @ignore */
68824         getCentroid3d(transform) {
68825             const centroid2d = this.getCentroid2d();
68826             return transform.unprojectBasic(centroid2d, 200);
68827         }
68828         /**
68829          * @ignore
68830          */
68831         getPoleOfInaccessibility2d() {
68832             return this._getPoleOfInaccessibility2d(this._rectToVertices2d(this._rect));
68833         }
68834         /** @ignore */
68835         getPoleOfInaccessibility3d(transform) {
68836             let pole2d = this._getPoleOfInaccessibility2d(this._rectToVertices2d(this._rect));
68837             return transform.unprojectBasic(pole2d, 200);
68838         }
68839         /** @ignore */
68840         getTriangles3d(transform) {
68841             return isSpherical(transform.cameraType) ?
68842                 [] :
68843                 this._triangulate(this._project(this._getPoints2d(), transform), this.getPoints3d(transform));
68844         }
68845         /**
68846          * Check if a particular bottom-right value is valid according to the current
68847          * rectangle coordinates.
68848          *
68849          * @param {Array<number>} bottomRight - The bottom-right coordinates to validate
68850          * @returns {boolean} Value indicating whether the provided bottom-right coordinates
68851          * are valid.
68852          * @ignore
68853          */
68854         validate(bottomRight) {
68855             let rect = this._rect;
68856             if (!this._inverted && bottomRight[0] < rect[0] ||
68857                 bottomRight[0] - rect[2] > 0.25 ||
68858                 bottomRight[1] < rect[1]) {
68859                 return false;
68860             }
68861             return true;
68862         }
68863         /**
68864          * Get the 2D coordinates for the vertices of the rectangle with
68865          * interpolated points along the lines.
68866          *
68867          * @returns {Array<Array<number>>} Polygon array of 2D basic coordinates
68868          * representing the rectangle.
68869          */
68870         _getPoints2d() {
68871             let vertices2d = this._rectToVertices2d(this._rect);
68872             let sides = vertices2d.length - 1;
68873             let sections = 10;
68874             let points2d = [];
68875             for (let i = 0; i < sides; ++i) {
68876                 let startX = vertices2d[i][0];
68877                 let startY = vertices2d[i][1];
68878                 let endX = vertices2d[i + 1][0];
68879                 let endY = vertices2d[i + 1][1];
68880                 let intervalX = (endX - startX) / (sections - 1);
68881                 let intervalY = (endY - startY) / (sections - 1);
68882                 for (let j = 0; j < sections; ++j) {
68883                     let point = [
68884                         startX + j * intervalX,
68885                         startY + j * intervalY,
68886                     ];
68887                     points2d.push(point);
68888                 }
68889             }
68890             return points2d;
68891         }
68892         /**
68893          * Convert the top-left, bottom-right representation of a rectangle to a polygon
68894          * representation of the vertices starting at the bottom-left corner going
68895          * clockwise.
68896          *
68897          * @description The method shifts the right side coordinates of the rectangle
68898          * by one unit to ensure that the vertices are ordered clockwise.
68899          *
68900          * @param {Array<number>} rect - Top-left, bottom-right representation of a
68901          * rectangle.
68902          * @returns {Array<Array<number>>} Polygon representation of the vertices of the
68903          * rectangle.
68904          */
68905         _rectToVertices2d(rect) {
68906             return [
68907                 [rect[0], rect[3]],
68908                 [rect[0], rect[1]],
68909                 [this._inverted ? rect[2] + 1 : rect[2], rect[1]],
68910                 [this._inverted ? rect[2] + 1 : rect[2], rect[3]],
68911                 [rect[0], rect[3]],
68912             ];
68913         }
68914         /**
68915          * Convert the top-left, bottom-right representation of a rectangle to a polygon
68916          * representation of the vertices starting at the bottom-left corner going
68917          * clockwise.
68918          *
68919          * @description The first vertex represents the bottom-left corner with the rest of
68920          * the vertices following in clockwise order. The coordinates will not be shifted
68921          * to ensure that the vertices are ordered clockwise when layed out on the plane.
68922          *
68923          * @param {Array<number>} rect - Top-left, bottom-right representation of a
68924          * rectangle.
68925          * @returns {Array<Array<number>>} Polygon representation of the vertices of the
68926          * rectangle.
68927          */
68928         _rectToNonAdjustedVertices2d(rect) {
68929             return [
68930                 [rect[0], rect[3]],
68931                 [rect[0], rect[1]],
68932                 [rect[2], rect[1]],
68933                 [rect[2], rect[3]],
68934                 [rect[0], rect[3]],
68935             ];
68936         }
68937     }
68938
68939     class ExtremePointCreateTag extends CreateTag {
68940         constructor(geometry, options, transform, viewportCoords) {
68941             super(geometry, transform, viewportCoords);
68942             this._options = {
68943                 color: options.color == null ? 0xFFFFFF : options.color,
68944                 indicateCompleter: options.indicateCompleter == null ? true : options.indicateCompleter,
68945             };
68946             this._rectGeometry = new RectGeometry(this._geometry.getRect2d(transform));
68947             this._createGlObjects();
68948         }
68949         create() {
68950             if (this._geometry.points.length < 3) {
68951                 return;
68952             }
68953             this._geometry.removePoint2d(this._geometry.points.length - 1);
68954             this._created$.next(this);
68955         }
68956         dispose() {
68957             super.dispose();
68958             this._disposeObjects();
68959         }
68960         getDOMObjects(camera, size) {
68961             const container = {
68962                 offsetHeight: size.height, offsetWidth: size.width,
68963             };
68964             const vNodes = [];
68965             const points2d = this._geometry.getPoints2d();
68966             const length = points2d.length;
68967             for (let index = 0; index < length - 1; index++) {
68968                 const nonModifiedIndex = index;
68969                 const [pointX, pointY] = points2d[index];
68970                 const pointCanvas = this._viewportCoords.basicToCanvasSafe(pointX, pointY, container, this._transform, camera);
68971                 if (!pointCanvas) {
68972                     continue;
68973                 }
68974                 const abort = (e) => {
68975                     e.stopPropagation();
68976                     this._aborted$.next(this);
68977                 };
68978                 const remove = (e) => {
68979                     e.stopPropagation();
68980                     this._geometry.removePoint2d(nonModifiedIndex);
68981                 };
68982                 const transform = this._canvasToTransform(pointCanvas);
68983                 const completerProperties = {
68984                     onclick: index === 0 && length < 3 ? abort : remove,
68985                     style: { transform: transform },
68986                 };
68987                 vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
68988                 const background = this._colorToBackground(this._options.color);
68989                 const pointProperties = {
68990                     style: {
68991                         background: background,
68992                         transform: transform,
68993                     },
68994                 };
68995                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
68996             }
68997             if (length > 2 && this._options.indicateCompleter === true) {
68998                 const [centroidX, centroidY] = this._geometry.getCentroid2d(this._transform);
68999                 const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidX, centroidY, container, this._transform, camera);
69000                 if (!!centroidCanvas) {
69001                     const complete = (e) => {
69002                         e.stopPropagation();
69003                         this._geometry.removePoint2d(this._geometry.points.length - 1);
69004                         this._created$.next(this);
69005                     };
69006                     const transform = this._canvasToTransform(centroidCanvas);
69007                     const completerProperties = {
69008                         onclick: complete,
69009                         style: { transform: transform },
69010                     };
69011                     vNodes.push(virtualDom.h("div.mapillary-tag-completer.mapillary-tag-larger", completerProperties, []));
69012                     const pointProperties = {
69013                         style: {
69014                             background: this._colorToBackground(this._options.color),
69015                             transform: transform,
69016                         },
69017                     };
69018                     vNodes.push(virtualDom.h("div.mapillary-tag-vertex.mapillary-tag-larger", pointProperties, []));
69019                     const dotProperties = {
69020                         style: {
69021                             transform: transform,
69022                         },
69023                     };
69024                     vNodes.push(virtualDom.h("div.mapillary-tag-dot", dotProperties, []));
69025                 }
69026             }
69027             return vNodes;
69028         }
69029         _onGeometryChanged() {
69030             this._disposeObjects();
69031             this._rectGeometry = new RectGeometry(this._geometry.getRect2d(this._transform));
69032             this._createGlObjects();
69033         }
69034         _createGlObjects() {
69035             this._glObjects = [];
69036             const polygon3d = this._rectGeometry.getPoints3d(this._transform);
69037             this._outline = this._createOutine(polygon3d, this._options.color);
69038             this._glObjects.push(this._outline);
69039         }
69040         _disposeObjects() {
69041             this._disposeLine(this._outline);
69042             this._outline = null;
69043             this._glObjects = null;
69044         }
69045     }
69046
69047     /**
69048      * @class PolygonGeometry
69049      *
69050      * @classdesc Represents a polygon geometry in the 2D basic image coordinate system.
69051      * All polygons and holes provided to the constructor needs to be closed.
69052      *
69053      * @example
69054      * ```js
69055      * var basicPolygon = [[0.5, 0.3], [0.7, 0.3], [0.6, 0.5], [0.5, 0.3]];
69056      * var polygonGeometry = new PolygonGeometry(basicPolygon);
69057      * ```
69058      */
69059     class PolygonGeometry extends VertexGeometry {
69060         /**
69061          * Create a polygon geometry.
69062          *
69063          * @constructor
69064          * @param {Array<Array<number>>} polygon - Array of polygon vertices. Must be closed.
69065          * @param {Array<Array<Array<number>>>} [holes] - Array of arrays of hole vertices.
69066          * Each array of holes vertices must be closed.
69067          *
69068          * @throws {GeometryTagError} Polygon coordinates must be valid basic coordinates.
69069          */
69070         constructor(polygon, holes) {
69071             super();
69072             let polygonLength = polygon.length;
69073             if (polygonLength < 3) {
69074                 throw new GeometryTagError("A polygon must have three or more positions.");
69075             }
69076             if (polygon[0][0] !== polygon[polygonLength - 1][0] ||
69077                 polygon[0][1] !== polygon[polygonLength - 1][1]) {
69078                 throw new GeometryTagError("First and last positions must be equivalent.");
69079             }
69080             this._polygon = [];
69081             for (let vertex of polygon) {
69082                 if (vertex[0] < 0 || vertex[0] > 1 ||
69083                     vertex[1] < 0 || vertex[1] > 1) {
69084                     throw new GeometryTagError("Basic coordinates of polygon must be on the interval [0, 1].");
69085                 }
69086                 this._polygon.push(vertex.slice());
69087             }
69088             this._holes = [];
69089             if (holes == null) {
69090                 return;
69091             }
69092             for (let i = 0; i < holes.length; i++) {
69093                 let hole = holes[i];
69094                 let holeLength = hole.length;
69095                 if (holeLength < 3) {
69096                     throw new GeometryTagError("A polygon hole must have three or more positions.");
69097                 }
69098                 if (hole[0][0] !== hole[holeLength - 1][0] ||
69099                     hole[0][1] !== hole[holeLength - 1][1]) {
69100                     throw new GeometryTagError("First and last positions of hole must be equivalent.");
69101                 }
69102                 this._holes.push([]);
69103                 for (let vertex of hole) {
69104                     if (vertex[0] < 0 || vertex[0] > 1 ||
69105                         vertex[1] < 0 || vertex[1] > 1) {
69106                         throw new GeometryTagError("Basic coordinates of hole must be on the interval [0, 1].");
69107                     }
69108                     this._holes[i].push(vertex.slice());
69109                 }
69110             }
69111         }
69112         /**
69113          * Get polygon property.
69114          * @returns {Array<Array<number>>} Closed 2d polygon.
69115          */
69116         get polygon() {
69117             return this._polygon;
69118         }
69119         /**
69120          * Get holes property.
69121          * @returns {Array<Array<Array<number>>>} Holes of 2d polygon.
69122          */
69123         get holes() {
69124             return this._holes;
69125         }
69126         /**
69127          * Add a vertex to the polygon by appending it after the last vertex.
69128          *
69129          * @param {Array<number>} vertex - Vertex to add.
69130          * @ignore
69131          */
69132         addVertex2d(vertex) {
69133             let clamped = [
69134                 Math.max(0, Math.min(1, vertex[0])),
69135                 Math.max(0, Math.min(1, vertex[1])),
69136             ];
69137             this._polygon.splice(this._polygon.length - 1, 0, clamped);
69138             this._notifyChanged$.next(this);
69139         }
69140         /**
69141          * Get the coordinates of a vertex from the polygon representation of the geometry.
69142          *
69143          * @param {number} index - Vertex index.
69144          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
69145          * @ignore
69146          */
69147         getVertex2d(index) {
69148             return this._polygon[index].slice();
69149         }
69150         /**
69151          * Remove a vertex from the polygon.
69152          *
69153          * @param {number} index - The index of the vertex to remove.
69154          * @ignore
69155          */
69156         removeVertex2d(index) {
69157             if (index < 0 ||
69158                 index >= this._polygon.length ||
69159                 this._polygon.length < 4) {
69160                 throw new GeometryTagError("Index for removed vertex must be valid.");
69161             }
69162             if (index > 0 && index < this._polygon.length - 1) {
69163                 this._polygon.splice(index, 1);
69164             }
69165             else {
69166                 this._polygon.splice(0, 1);
69167                 this._polygon.pop();
69168                 let closing = this._polygon[0].slice();
69169                 this._polygon.push(closing);
69170             }
69171             this._notifyChanged$.next(this);
69172         }
69173         /** @ignore */
69174         setVertex2d(index, value, transform) {
69175             let changed = [
69176                 Math.max(0, Math.min(1, value[0])),
69177                 Math.max(0, Math.min(1, value[1])),
69178             ];
69179             if (index === 0 || index === this._polygon.length - 1) {
69180                 this._polygon[0] = changed.slice();
69181                 this._polygon[this._polygon.length - 1] = changed.slice();
69182             }
69183             else {
69184                 this._polygon[index] = changed.slice();
69185             }
69186             this._notifyChanged$.next(this);
69187         }
69188         /** @ignore */
69189         setCentroid2d(value, transform) {
69190             let xs = this._polygon.map((point) => { return point[0]; });
69191             let ys = this._polygon.map((point) => { return point[1]; });
69192             let minX = Math.min.apply(Math, xs);
69193             let maxX = Math.max.apply(Math, xs);
69194             let minY = Math.min.apply(Math, ys);
69195             let maxY = Math.max.apply(Math, ys);
69196             let centroid = this.getCentroid2d();
69197             let minTranslationX = -minX;
69198             let maxTranslationX = 1 - maxX;
69199             let minTranslationY = -minY;
69200             let maxTranslationY = 1 - maxY;
69201             let translationX = Math.max(minTranslationX, Math.min(maxTranslationX, value[0] - centroid[0]));
69202             let translationY = Math.max(minTranslationY, Math.min(maxTranslationY, value[1] - centroid[1]));
69203             for (let point of this._polygon) {
69204                 point[0] += translationX;
69205                 point[1] += translationY;
69206             }
69207             this._notifyChanged$.next(this);
69208         }
69209         /** @ignore */
69210         getPoints3d(transform) {
69211             return this._getPoints3d(this._subsample(this._polygon), transform);
69212         }
69213         /** @ignore */
69214         getVertex3d(index, transform) {
69215             return transform.unprojectBasic(this._polygon[index], 200);
69216         }
69217         /** @ignore */
69218         getVertices2d() {
69219             return this._polygon.slice();
69220         }
69221         /** @ignore */
69222         getVertices3d(transform) {
69223             return this._getPoints3d(this._polygon, transform);
69224         }
69225         /**
69226          * Get a polygon representation of the 3D coordinates for the vertices of each hole
69227          * of the geometry. Line segments between vertices will possibly be subsampled
69228          * resulting in a larger number of points than the total number of vertices.
69229          *
69230          * @param {Transform} transform - The transform of the image related to the geometry.
69231          * @returns {Array<Array<Array<number>>>} Array of hole polygons in 3D world coordinates
69232          * representing the vertices of each hole of the geometry.
69233          * @ignore
69234          */
69235         getHolePoints3d(transform) {
69236             return this._holes
69237                 .map((hole2d) => {
69238                 return this._getPoints3d(this._subsample(hole2d), transform);
69239             });
69240         }
69241         /**
69242          * Get a polygon representation of the 3D coordinates for the vertices of each hole
69243          * of the geometry.
69244          *
69245          * @param {Transform} transform - The transform of the image related to the geometry.
69246          * @returns {Array<Array<Array<number>>>} Array of hole polygons in 3D world coordinates
69247          * representing the vertices of each hole of the geometry.
69248          * @ignore
69249          */
69250         getHoleVertices3d(transform) {
69251             return this._holes
69252                 .map((hole2d) => {
69253                 return this._getPoints3d(hole2d, transform);
69254             });
69255         }
69256         /** @ignore */
69257         getCentroid2d() {
69258             let polygon = this._polygon;
69259             let area = 0;
69260             let centroidX = 0;
69261             let centroidY = 0;
69262             for (let i = 0; i < polygon.length - 1; i++) {
69263                 let xi = polygon[i][0];
69264                 let yi = polygon[i][1];
69265                 let xi1 = polygon[i + 1][0];
69266                 let yi1 = polygon[i + 1][1];
69267                 let a = xi * yi1 - xi1 * yi;
69268                 area += a;
69269                 centroidX += (xi + xi1) * a;
69270                 centroidY += (yi + yi1) * a;
69271             }
69272             area /= 2;
69273             centroidX /= 6 * area;
69274             centroidY /= 6 * area;
69275             return [centroidX, centroidY];
69276         }
69277         /** @ignore */
69278         getCentroid3d(transform) {
69279             let centroid2d = this.getCentroid2d();
69280             return transform.unprojectBasic(centroid2d, 200);
69281         }
69282         /** @ignore */
69283         get3dDomainTriangles3d(transform) {
69284             return this._triangulate(this._project(this._polygon, transform), this.getVertices3d(transform), this._holes
69285                 .map((hole2d) => {
69286                 return this._project(hole2d, transform);
69287             }), this.getHoleVertices3d(transform));
69288         }
69289         /** @ignore */
69290         getTriangles3d(transform) {
69291             if (isSpherical(transform.cameraType)) {
69292                 return this._triangulateSpherical(this._polygon.slice(), this.holes.slice(), transform);
69293             }
69294             const points2d = this._project(this._subsample(this._polygon), transform);
69295             const points3d = this.getPoints3d(transform);
69296             const holes2d = this._holes
69297                 .map((hole) => {
69298                 return this._project(this._subsample(hole), transform);
69299             });
69300             const holes3d = this.getHolePoints3d(transform);
69301             return this._triangulate(points2d, points3d, holes2d, holes3d);
69302         }
69303         /** @ignore */
69304         getPoleOfInaccessibility2d() {
69305             return this._getPoleOfInaccessibility2d(this._polygon.slice());
69306         }
69307         /** @ignore */
69308         getPoleOfInaccessibility3d(transform) {
69309             let pole2d = this._getPoleOfInaccessibility2d(this._polygon.slice());
69310             return transform.unprojectBasic(pole2d, 200);
69311         }
69312         _getPoints3d(points2d, transform) {
69313             return points2d
69314                 .map((point) => {
69315                 return transform.unprojectBasic(point, 200);
69316             });
69317         }
69318     }
69319
69320     class OutlineCreateTag extends CreateTag {
69321         constructor(geometry, options, transform, viewportCoords) {
69322             super(geometry, transform, viewportCoords);
69323             this._options = { color: options.color == null ? 0xFFFFFF : options.color };
69324             this._createGlObjects();
69325         }
69326         create() {
69327             if (this._geometry instanceof RectGeometry) {
69328                 this._created$.next(this);
69329             }
69330             else if (this._geometry instanceof PolygonGeometry) {
69331                 const polygonGeometry = this._geometry;
69332                 polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2);
69333                 this._created$.next(this);
69334             }
69335         }
69336         dispose() {
69337             super.dispose();
69338             this._disposeLine(this._outline);
69339             this._disposeObjects();
69340         }
69341         getDOMObjects(camera, size) {
69342             const vNodes = [];
69343             const container = {
69344                 offsetHeight: size.height, offsetWidth: size.width,
69345             };
69346             const abort = (e) => {
69347                 e.stopPropagation();
69348                 this._aborted$.next(this);
69349             };
69350             if (this._geometry instanceof RectGeometry) {
69351                 const anchorIndex = this._geometry.anchorIndex;
69352                 const vertexIndex = anchorIndex === undefined ? 1 : anchorIndex;
69353                 const [basicX, basicY] = this._geometry.getVertex2d(vertexIndex);
69354                 const canvasPoint = this._viewportCoords.basicToCanvasSafe(basicX, basicY, container, this._transform, camera);
69355                 if (canvasPoint != null) {
69356                     const background = this._colorToBackground(this._options.color);
69357                     const transform = this._canvasToTransform(canvasPoint);
69358                     const pointProperties = {
69359                         style: { background: background, transform: transform },
69360                     };
69361                     const completerProperties = {
69362                         onclick: abort,
69363                         style: { transform: transform },
69364                     };
69365                     vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
69366                     vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
69367                 }
69368             }
69369             else if (this._geometry instanceof PolygonGeometry) {
69370                 const polygonGeometry = this._geometry;
69371                 const [firstVertexBasicX, firstVertexBasicY] = polygonGeometry.getVertex2d(0);
69372                 const firstVertexCanvas = this._viewportCoords.basicToCanvasSafe(firstVertexBasicX, firstVertexBasicY, container, this._transform, camera);
69373                 if (firstVertexCanvas != null) {
69374                     const firstOnclick = polygonGeometry.polygon.length > 4 ?
69375                         (e) => {
69376                             e.stopPropagation();
69377                             polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2);
69378                             this._created$.next(this);
69379                         } :
69380                         abort;
69381                     const transform = this._canvasToTransform(firstVertexCanvas);
69382                     const completerProperties = {
69383                         onclick: firstOnclick,
69384                         style: { transform: transform },
69385                     };
69386                     const firstClass = polygonGeometry.polygon.length > 4 ?
69387                         "mapillary-tag-completer" :
69388                         "mapillary-tag-interactor";
69389                     vNodes.push(virtualDom.h("div." + firstClass, completerProperties, []));
69390                 }
69391                 if (polygonGeometry.polygon.length > 3) {
69392                     const [lastVertexBasicX, lastVertexBasicY] = polygonGeometry.getVertex2d(polygonGeometry.polygon.length - 3);
69393                     const lastVertexCanvas = this._viewportCoords.basicToCanvasSafe(lastVertexBasicX, lastVertexBasicY, container, this._transform, camera);
69394                     if (lastVertexCanvas != null) {
69395                         const remove = (e) => {
69396                             e.stopPropagation();
69397                             polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 3);
69398                         };
69399                         const transform = this._canvasToTransform(lastVertexCanvas);
69400                         const completerProperties = {
69401                             onclick: remove,
69402                             style: { transform: transform },
69403                         };
69404                         vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
69405                     }
69406                 }
69407                 const verticesBasic = polygonGeometry.polygon.slice();
69408                 verticesBasic.splice(-2, 2);
69409                 for (const vertexBasic of verticesBasic) {
69410                     const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasic[0], vertexBasic[1], container, this._transform, camera);
69411                     if (vertexCanvas != null) {
69412                         const background = this._colorToBackground(this._options.color);
69413                         const transform = this._canvasToTransform(vertexCanvas);
69414                         const pointProperties = {
69415                             style: {
69416                                 background: background,
69417                                 transform: transform,
69418                             },
69419                         };
69420                         vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
69421                     }
69422                 }
69423             }
69424             return vNodes;
69425         }
69426         addPoint(point) {
69427             if (this._geometry instanceof RectGeometry) {
69428                 const rectGeometry = this._geometry;
69429                 if (!rectGeometry.validate(point)) {
69430                     return;
69431                 }
69432                 this._created$.next(this);
69433             }
69434             else if (this._geometry instanceof PolygonGeometry) {
69435                 const polygonGeometry = this._geometry;
69436                 polygonGeometry.addVertex2d(point);
69437             }
69438         }
69439         _onGeometryChanged() {
69440             this._disposeLine(this._outline);
69441             this._disposeObjects();
69442             this._createGlObjects();
69443         }
69444         _disposeObjects() {
69445             this._outline = null;
69446             this._glObjects = [];
69447         }
69448         _createGlObjects() {
69449             const polygon3d = this._geometry instanceof RectGeometry ?
69450                 this._geometry.getPoints3d(this._transform) :
69451                 this._geometry.getVertices3d(this._transform);
69452             this._outline = this._createOutine(polygon3d, this._options.color);
69453             this._glObjects = [this._outline];
69454         }
69455     }
69456
69457     class TagCreator {
69458         constructor(component, navigator) {
69459             this._component = component;
69460             this._navigator = navigator;
69461             this._tagOperation$ = new Subject();
69462             this._createPoints$ = new Subject();
69463             this._createPolygon$ = new Subject();
69464             this._createRect$ = new Subject();
69465             this._delete$ = new Subject();
69466             this._tag$ = this._tagOperation$.pipe(scan((tag, operation) => {
69467                 return operation(tag);
69468             }, null), share());
69469             this._replayedTag$ = this._tag$.pipe(publishReplay(1), refCount());
69470             this._replayedTag$.subscribe();
69471             this._createPoints$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
69472                 return () => {
69473                     const geometry = new PointsGeometry([
69474                         [coord[0], coord[1]],
69475                         [coord[0], coord[1]],
69476                     ]);
69477                     return new ExtremePointCreateTag(geometry, {
69478                         color: conf.createColor,
69479                         indicateCompleter: conf.indicatePointsCompleter,
69480                     }, transform);
69481                 };
69482             }))
69483                 .subscribe(this._tagOperation$);
69484             this._createRect$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
69485                 return () => {
69486                     const geometry = new RectGeometry([
69487                         coord[0],
69488                         coord[1],
69489                         coord[0],
69490                         coord[1],
69491                     ]);
69492                     return new OutlineCreateTag(geometry, { color: conf.createColor }, transform);
69493                 };
69494             }))
69495                 .subscribe(this._tagOperation$);
69496             this._createPolygon$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
69497                 return () => {
69498                     const geometry = new PolygonGeometry([
69499                         [coord[0], coord[1]],
69500                         [coord[0], coord[1]],
69501                         [coord[0], coord[1]],
69502                     ]);
69503                     return new OutlineCreateTag(geometry, { color: conf.createColor }, transform);
69504                 };
69505             }))
69506                 .subscribe(this._tagOperation$);
69507             this._delete$.pipe(map(() => {
69508                 return () => {
69509                     return null;
69510                 };
69511             }))
69512                 .subscribe(this._tagOperation$);
69513         }
69514         get createRect$() {
69515             return this._createRect$;
69516         }
69517         get createPolygon$() {
69518             return this._createPolygon$;
69519         }
69520         get createPoints$() {
69521             return this._createPoints$;
69522         }
69523         get delete$() {
69524             return this._delete$;
69525         }
69526         get tag$() {
69527             return this._tag$;
69528         }
69529         get replayedTag$() {
69530             return this._replayedTag$;
69531         }
69532     }
69533
69534     class TagDOMRenderer {
69535         render(tags, createTag, atlas, camera, size) {
69536             let vNodes = [];
69537             for (const tag of tags) {
69538                 vNodes = vNodes.concat(tag.getDOMObjects(atlas, camera, size));
69539             }
69540             if (createTag != null) {
69541                 vNodes = vNodes.concat(createTag.getDOMObjects(camera, size));
69542             }
69543             return virtualDom.h("div.mapillary-tag-container", {}, vNodes);
69544         }
69545         clear() {
69546             return virtualDom.h("div", {}, []);
69547         }
69548     }
69549
69550     class TagScene {
69551         constructor(scene, raycaster) {
69552             this._createTag = null;
69553             this._needsRender = false;
69554             this._raycaster = !!raycaster ? raycaster : new Raycaster();
69555             this._scene = !!scene ? scene : new Scene();
69556             this._objectTags = {};
69557             this._retrievableObjects = [];
69558             this._tags = {};
69559         }
69560         get needsRender() {
69561             return this._needsRender;
69562         }
69563         add(tags) {
69564             for (let tag of tags) {
69565                 if (tag.tag.id in this._tags) {
69566                     this._remove(tag.tag.id);
69567                 }
69568                 this._add(tag);
69569             }
69570             this._needsRender = true;
69571         }
69572         addCreateTag(tag) {
69573             for (const object of tag.glObjects) {
69574                 this._scene.add(object);
69575             }
69576             this._createTag = { tag: tag, objects: tag.glObjects };
69577             this._needsRender = true;
69578         }
69579         clear() {
69580             for (const id of Object.keys(this._tags)) {
69581                 this._remove(id);
69582             }
69583             this._needsRender = false;
69584         }
69585         get(id) {
69586             return this.has(id) ? this._tags[id].tag : undefined;
69587         }
69588         has(id) {
69589             return id in this._tags;
69590         }
69591         hasCreateTag() {
69592             return this._createTag != null;
69593         }
69594         intersectObjects([viewportX, viewportY], camera) {
69595             this._raycaster.setFromCamera(new Vector2(viewportX, viewportY), camera);
69596             const intersects = this._raycaster.intersectObjects(this._retrievableObjects);
69597             const intersectedIds = [];
69598             for (const intersect of intersects) {
69599                 if (intersect.object.uuid in this._objectTags) {
69600                     intersectedIds.push(this._objectTags[intersect.object.uuid]);
69601                 }
69602             }
69603             return intersectedIds;
69604         }
69605         remove(ids) {
69606             for (const id of ids) {
69607                 this._remove(id);
69608             }
69609             this._needsRender = true;
69610         }
69611         removeAll() {
69612             for (const id of Object.keys(this._tags)) {
69613                 this._remove(id);
69614             }
69615             this._needsRender = true;
69616         }
69617         removeCreateTag() {
69618             if (this._createTag == null) {
69619                 return;
69620             }
69621             for (const object of this._createTag.objects) {
69622                 this._scene.remove(object);
69623             }
69624             this._createTag.tag.dispose();
69625             this._createTag = null;
69626             this._needsRender = true;
69627         }
69628         render(perspectiveCamera, renderer) {
69629             renderer.render(this._scene, perspectiveCamera);
69630             this._needsRender = false;
69631         }
69632         update() {
69633             this._needsRender = true;
69634         }
69635         updateCreateTagObjects(tag) {
69636             if (this._createTag.tag !== tag) {
69637                 throw new Error("Create tags do not have the same reference.");
69638             }
69639             for (let object of this._createTag.objects) {
69640                 this._scene.remove(object);
69641             }
69642             for (const object of tag.glObjects) {
69643                 this._scene.add(object);
69644             }
69645             this._createTag.objects = tag.glObjects;
69646             this._needsRender = true;
69647         }
69648         updateObjects(tag) {
69649             const id = tag.tag.id;
69650             if (this._tags[id].tag !== tag) {
69651                 throw new Error("Tags do not have the same reference.");
69652             }
69653             const tagObjects = this._tags[id];
69654             this._removeObjects(tagObjects);
69655             delete this._tags[id];
69656             this._add(tag);
69657             this._needsRender = true;
69658         }
69659         _add(tag) {
69660             const id = tag.tag.id;
69661             const tagObjects = { tag: tag, objects: [], retrievableObjects: [] };
69662             this._tags[id] = tagObjects;
69663             for (const object of tag.getGLObjects()) {
69664                 tagObjects.objects.push(object);
69665                 this._scene.add(object);
69666             }
69667             for (const retrievableObject of tag.getRetrievableObjects()) {
69668                 tagObjects.retrievableObjects.push(retrievableObject);
69669                 this._retrievableObjects.push(retrievableObject);
69670                 this._objectTags[retrievableObject.uuid] = tag.tag.id;
69671             }
69672         }
69673         _remove(id) {
69674             const tagObjects = this._tags[id];
69675             this._removeObjects(tagObjects);
69676             tagObjects.tag.dispose();
69677             delete this._tags[id];
69678         }
69679         _removeObjects(tagObjects) {
69680             for (const object of tagObjects.objects) {
69681                 this._scene.remove(object);
69682             }
69683             for (const retrievableObject of tagObjects.retrievableObjects) {
69684                 const index = this._retrievableObjects.indexOf(retrievableObject);
69685                 if (index !== -1) {
69686                     this._retrievableObjects.splice(index, 1);
69687                 }
69688             }
69689         }
69690     }
69691
69692     /**
69693      * Enumeration for tag modes
69694      * @enum {number}
69695      * @readonly
69696      * @description Modes for the interaction in the tag component.
69697      */
69698     exports.TagMode = void 0;
69699     (function (TagMode) {
69700         /**
69701          * Disables creating tags.
69702          */
69703         TagMode[TagMode["Default"] = 0] = "Default";
69704         /**
69705          * Create a point geometry through a click.
69706          */
69707         TagMode[TagMode["CreatePoint"] = 1] = "CreatePoint";
69708         /**
69709          * Create a points geometry through clicks.
69710          */
69711         TagMode[TagMode["CreatePoints"] = 2] = "CreatePoints";
69712         /**
69713          * Create a polygon geometry through clicks.
69714          */
69715         TagMode[TagMode["CreatePolygon"] = 3] = "CreatePolygon";
69716         /**
69717          * Create a rect geometry through clicks.
69718          */
69719         TagMode[TagMode["CreateRect"] = 4] = "CreateRect";
69720         /**
69721          * Create a rect geometry through drag.
69722          *
69723          * @description Claims the mouse which results in mouse handlers like
69724          * drag pan and scroll zoom becoming inactive.
69725          */
69726         TagMode[TagMode["CreateRectDrag"] = 5] = "CreateRectDrag";
69727     })(exports.TagMode || (exports.TagMode = {}));
69728
69729     var TagOperation;
69730     (function (TagOperation) {
69731         TagOperation[TagOperation["None"] = 0] = "None";
69732         TagOperation[TagOperation["Centroid"] = 1] = "Centroid";
69733         TagOperation[TagOperation["Vertex"] = 2] = "Vertex";
69734     })(TagOperation || (TagOperation = {}));
69735
69736     class RenderTag {
69737         constructor(tag, transform, viewportCoords) {
69738             this._tag = tag;
69739             this._transform = transform;
69740             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
69741             this._glObjectsChanged$ = new Subject();
69742             this._interact$ = new Subject();
69743         }
69744         get glObjectsChanged$() {
69745             return this._glObjectsChanged$;
69746         }
69747         get interact$() {
69748             return this._interact$;
69749         }
69750         get tag() {
69751             return this._tag;
69752         }
69753     }
69754
69755     class OutlineRenderTagBase extends RenderTag {
69756         constructor(tag, transform) {
69757             super(tag, transform);
69758             this._geometryChangedSubscription = this._tag.geometry.changed$
69759                 .subscribe(() => {
69760                 this._onGeometryChanged();
69761             });
69762             this._changedSubscription = this._tag.changed$
69763                 .subscribe(() => {
69764                 const glObjectsChanged = this._onTagChanged();
69765                 if (glObjectsChanged) {
69766                     this._glObjectsChanged$.next(this);
69767                 }
69768             });
69769         }
69770         dispose() {
69771             this._changedSubscription.unsubscribe();
69772             this._geometryChangedSubscription.unsubscribe();
69773         }
69774         _colorToCss(color) {
69775             return "#" + ("000000" + color.toString(16)).substr(-6);
69776         }
69777         _createFill() {
69778             let triangles = this._getTriangles();
69779             let positions = new Float32Array(triangles);
69780             let geometry = new BufferGeometry();
69781             geometry.setAttribute("position", new BufferAttribute(positions, 3));
69782             geometry.computeBoundingSphere();
69783             let material = new MeshBasicMaterial({ side: DoubleSide, transparent: true });
69784             this._updateFillMaterial(material);
69785             return new Mesh(geometry, material);
69786         }
69787         _createLine(points3d) {
69788             let positions = this._getLinePositions(points3d);
69789             let geometry = new BufferGeometry();
69790             geometry.setAttribute("position", new BufferAttribute(positions, 3));
69791             geometry.computeBoundingSphere();
69792             let material = new LineBasicMaterial();
69793             this._updateLineBasicMaterial(material);
69794             const line = new Line(geometry, material);
69795             line.renderOrder = 1;
69796             return line;
69797         }
69798         _createOutline() {
69799             return this._createLine(this._getPoints3d());
69800         }
69801         _disposeFill() {
69802             if (this._fill == null) {
69803                 return;
69804             }
69805             this._fill.geometry.dispose();
69806             this._fill.material.dispose();
69807             this._fill = null;
69808         }
69809         _disposeOutline() {
69810             if (this._outline == null) {
69811                 return;
69812             }
69813             this._outline.geometry.dispose();
69814             this._outline.material.dispose();
69815             this._outline = null;
69816         }
69817         _getLinePositions(points3d) {
69818             let length = points3d.length;
69819             let positions = new Float32Array(length * 3);
69820             for (let i = 0; i < length; ++i) {
69821                 let index = 3 * i;
69822                 let position = points3d[i];
69823                 positions[index + 0] = position[0];
69824                 positions[index + 1] = position[1];
69825                 positions[index + 2] = position[2];
69826             }
69827             return positions;
69828         }
69829         _interact(operation, cursor, vertexIndex) {
69830             return (e) => {
69831                 let offsetX = e.offsetX - e.target.offsetWidth / 2;
69832                 let offsetY = e.offsetY - e.target.offsetHeight / 2;
69833                 this._interact$.next({
69834                     cursor: cursor,
69835                     offsetX: offsetX,
69836                     offsetY: offsetY,
69837                     operation: operation,
69838                     tag: this._tag,
69839                     vertexIndex: vertexIndex,
69840                 });
69841             };
69842         }
69843         _updateFillGeometry() {
69844             let triangles = this._getTriangles();
69845             let positions = new Float32Array(triangles);
69846             let geometry = this._fill.geometry;
69847             let attribute = geometry.getAttribute("position");
69848             if (attribute.array.length === positions.length) {
69849                 attribute.set(positions);
69850                 attribute.needsUpdate = true;
69851             }
69852             else {
69853                 geometry.deleteAttribute("position");
69854                 geometry.setAttribute("position", new BufferAttribute(positions, 3));
69855             }
69856             geometry.computeBoundingSphere();
69857         }
69858         _updateLine(line, points3d) {
69859             let positions = this._getLinePositions(points3d);
69860             let geometry = line.geometry;
69861             let attribute = geometry.getAttribute("position");
69862             attribute.set(positions);
69863             attribute.needsUpdate = true;
69864             geometry.computeBoundingSphere();
69865         }
69866         _updateOulineGeometry() {
69867             this._updateLine(this._outline, this._getPoints3d());
69868         }
69869     }
69870
69871     /**
69872      * @class OutlineRenderTag
69873      * @classdesc Tag visualizing the properties of an OutlineTag.
69874      */
69875     class ExtremePointRenderTag extends OutlineRenderTagBase {
69876         constructor(tag, transform) {
69877             super(tag, transform);
69878             this._rectGeometry = new RectGeometry(this._tag.geometry.getRect2d(transform));
69879             this._fill = !isSpherical(transform.cameraType) ?
69880                 this._createFill() : null;
69881             this._outline = this._tag.lineWidth >= 1 ?
69882                 this._createOutline() :
69883                 null;
69884         }
69885         dispose() {
69886             super.dispose();
69887             this._disposeFill();
69888             this._disposeOutline();
69889         }
69890         getDOMObjects(atlas, camera, size) {
69891             const vNodes = [];
69892             const container = {
69893                 offsetHeight: size.height, offsetWidth: size.width,
69894             };
69895             if (!this._tag.editable) {
69896                 return vNodes;
69897             }
69898             const lineColor = this._colorToCss(this._tag.lineColor);
69899             const points2d = this._tag.geometry.getPoints2d();
69900             for (let i = 0; i < points2d.length; i++) {
69901                 const [vertexBasicX, vertexBasicY] = points2d[i];
69902                 const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasicX, vertexBasicY, container, this._transform, camera);
69903                 if (vertexCanvas == null) {
69904                     continue;
69905                 }
69906                 const cursor = "crosshair";
69907                 const interact = this._interact(TagOperation.Vertex, cursor, i);
69908                 const vertexCanvasX = Math.round(vertexCanvas[0]);
69909                 const vertexCanvasY = Math.round(vertexCanvas[1]);
69910                 const transform = `translate(-50%, -50%) translate(${vertexCanvasX}px,${vertexCanvasY}px)`;
69911                 const properties = {
69912                     onpointerdown: interact,
69913                     style: { background: lineColor, transform: transform, cursor: cursor },
69914                 };
69915                 vNodes.push(virtualDom.h("div.mapillary-tag-resizer", properties, []));
69916                 if (!this._tag.indicateVertices) {
69917                     continue;
69918                 }
69919                 const pointProperties = {
69920                     style: { background: lineColor, transform: transform },
69921                 };
69922                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
69923             }
69924             return vNodes;
69925         }
69926         getGLObjects() {
69927             const glObjects = [];
69928             if (this._fill != null) {
69929                 glObjects.push(this._fill);
69930             }
69931             if (this._outline != null) {
69932                 glObjects.push(this._outline);
69933             }
69934             return glObjects;
69935         }
69936         getRetrievableObjects() {
69937             return this._fill != null ? [this._fill] : [];
69938         }
69939         _onGeometryChanged() {
69940             this._rectGeometry = new RectGeometry(this._tag.geometry.getRect2d(this._transform));
69941             if (this._fill != null) {
69942                 this._updateFillGeometry();
69943             }
69944             if (this._outline != null) {
69945                 this._updateOulineGeometry();
69946             }
69947         }
69948         _onTagChanged() {
69949             let glObjectsChanged = false;
69950             if (this._fill != null) {
69951                 this._updateFillMaterial(this._fill.material);
69952             }
69953             if (this._outline == null) {
69954                 if (this._tag.lineWidth >= 1) {
69955                     this._outline = this._createOutline();
69956                     glObjectsChanged = true;
69957                 }
69958             }
69959             else {
69960                 this._updateOutlineMaterial();
69961             }
69962             return glObjectsChanged;
69963         }
69964         _getPoints3d() {
69965             return this._rectGeometry.getPoints3d(this._transform);
69966         }
69967         _getTriangles() {
69968             return this._rectGeometry.getTriangles3d(this._transform);
69969         }
69970         _updateFillMaterial(material) {
69971             material.color = new Color(this._tag.fillColor);
69972             material.opacity = this._tag.fillOpacity;
69973             material.needsUpdate = true;
69974         }
69975         _updateLineBasicMaterial(material) {
69976             material.color = new Color(this._tag.lineColor);
69977             material.linewidth = Math.max(this._tag.lineWidth, 1);
69978             material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
69979             material.opacity = this._tag.lineOpacity;
69980             material.transparent = this._tag.lineOpacity < 1;
69981             material.needsUpdate = true;
69982         }
69983         _updateOutlineMaterial() {
69984             let material = this._outline.material;
69985             this._updateLineBasicMaterial(material);
69986         }
69987     }
69988
69989     /**
69990      * @class Tag
69991      * @abstract
69992      * @classdesc Abstract class representing the basic functionality of for a tag.
69993      */
69994     class Tag extends EventEmitter {
69995         /**
69996          * Create a tag.
69997          *
69998          * @constructor
69999          * @param {string} id
70000          * @param {Geometry} geometry
70001          */
70002         constructor(id, geometry) {
70003             super();
70004             this._id = id;
70005             this._geometry = geometry;
70006             this._notifyChanged$ = new Subject();
70007             this._notifyChanged$
70008                 .subscribe((t) => {
70009                 const type = "tag";
70010                 const event = {
70011                     target: this,
70012                     type,
70013                 };
70014                 this.fire(type, event);
70015             });
70016             this._geometry.changed$
70017                 .subscribe((g) => {
70018                 const type = "geometry";
70019                 const event = {
70020                     target: this,
70021                     type,
70022                 };
70023                 this.fire(type, event);
70024             });
70025         }
70026         /**
70027          * Get id property.
70028          * @returns {string}
70029          */
70030         get id() {
70031             return this._id;
70032         }
70033         /**
70034          * Get geometry property.
70035          * @returns {Geometry} The geometry of the tag.
70036          */
70037         get geometry() {
70038             return this._geometry;
70039         }
70040         /**
70041          * Get changed observable.
70042          * @returns {Observable<Tag>}
70043          * @ignore
70044          */
70045         get changed$() {
70046             return this._notifyChanged$;
70047         }
70048         /**
70049          * Get geometry changed observable.
70050          * @returns {Observable<Tag>}
70051          * @ignore
70052          */
70053         get geometryChanged$() {
70054             return this._geometry.changed$.pipe(map(() => {
70055                 return this;
70056             }), share());
70057         }
70058         fire(type, event) {
70059             super.fire(type, event);
70060         }
70061         off(type, handler) {
70062             super.off(type, handler);
70063         }
70064         on(type, handler) {
70065             super.on(type, handler);
70066         }
70067     }
70068
70069     /**
70070      * @class ExtremePointTag
70071      *
70072      * @classdesc Tag holding properties for visualizing a extreme points
70073      * and their outline.
70074      *
70075      * @example
70076      * ```js
70077      * var geometry = new PointsGeometry([[0.3, 0.3], [0.5, 0.4]]);
70078      * var tag = new ExtremePointTag(
70079      *     "id-1",
70080      *     geometry
70081      *     { editable: true, lineColor: 0xff0000 });
70082      *
70083      * tagComponent.add([tag]);
70084      * ```
70085      */
70086     class ExtremePointTag extends Tag {
70087         /**
70088          * Create an extreme point tag.
70089          *
70090          * @override
70091          * @constructor
70092          * @param {string} id - Unique identifier of the tag.
70093          * @param {PointsGeometry} geometry - Geometry defining points of tag.
70094          * @param {ExtremePointTagOptions} options - Options defining the visual appearance and
70095          * behavior of the extreme point tag.
70096          */
70097         constructor(id, geometry, options) {
70098             super(id, geometry);
70099             options = !!options ? options : {};
70100             this._editable = options.editable == null ? false : options.editable;
70101             this._fillColor = options.fillColor == null ? 0xFFFFFF : options.fillColor;
70102             this._fillOpacity = options.fillOpacity == null ? 0.0 : options.fillOpacity;
70103             this._indicateVertices = options.indicateVertices == null ? true : options.indicateVertices;
70104             this._lineColor = options.lineColor == null ? 0xFFFFFF : options.lineColor;
70105             this._lineOpacity = options.lineOpacity == null ? 1 : options.lineOpacity;
70106             this._lineWidth = options.lineWidth == null ? 1 : options.lineWidth;
70107         }
70108         /**
70109          * Get editable property.
70110          * @returns {boolean} Value indicating if tag is editable.
70111          */
70112         get editable() {
70113             return this._editable;
70114         }
70115         /**
70116          * Set editable property.
70117          * @param {boolean}
70118          *
70119          * @fires changed
70120          */
70121         set editable(value) {
70122             this._editable = value;
70123             this._notifyChanged$.next(this);
70124         }
70125         /**
70126          * Get fill color property.
70127          * @returns {number}
70128          */
70129         get fillColor() {
70130             return this._fillColor;
70131         }
70132         /**
70133          * Set fill color property.
70134          * @param {number}
70135          *
70136          * @fires changed
70137          */
70138         set fillColor(value) {
70139             this._fillColor = value;
70140             this._notifyChanged$.next(this);
70141         }
70142         /**
70143          * Get fill opacity property.
70144          * @returns {number}
70145          */
70146         get fillOpacity() {
70147             return this._fillOpacity;
70148         }
70149         /**
70150          * Set fill opacity property.
70151          * @param {number}
70152          *
70153          * @fires changed
70154          */
70155         set fillOpacity(value) {
70156             this._fillOpacity = value;
70157             this._notifyChanged$.next(this);
70158         }
70159         /** @inheritdoc */
70160         get geometry() {
70161             return this._geometry;
70162         }
70163         /**
70164          * Get indicate vertices property.
70165          * @returns {boolean} Value indicating if vertices should be indicated
70166          * when tag is editable.
70167          */
70168         get indicateVertices() {
70169             return this._indicateVertices;
70170         }
70171         /**
70172          * Set indicate vertices property.
70173          * @param {boolean}
70174          *
70175          * @fires changed
70176          */
70177         set indicateVertices(value) {
70178             this._indicateVertices = value;
70179             this._notifyChanged$.next(this);
70180         }
70181         /**
70182          * Get line color property.
70183          * @returns {number}
70184          */
70185         get lineColor() {
70186             return this._lineColor;
70187         }
70188         /**
70189          * Set line color property.
70190          * @param {number}
70191          *
70192          * @fires changed
70193          */
70194         set lineColor(value) {
70195             this._lineColor = value;
70196             this._notifyChanged$.next(this);
70197         }
70198         /**
70199          * Get line opacity property.
70200          * @returns {number}
70201          */
70202         get lineOpacity() {
70203             return this._lineOpacity;
70204         }
70205         /**
70206          * Set line opacity property.
70207          * @param {number}
70208          *
70209          * @fires changed
70210          */
70211         set lineOpacity(value) {
70212             this._lineOpacity = value;
70213             this._notifyChanged$.next(this);
70214         }
70215         /**
70216          * Get line width property.
70217          * @returns {number}
70218          */
70219         get lineWidth() {
70220             return this._lineWidth;
70221         }
70222         /**
70223          * Set line width property.
70224          * @param {number}
70225          *
70226          * @fires changed
70227          */
70228         set lineWidth(value) {
70229             this._lineWidth = value;
70230             this._notifyChanged$.next(this);
70231         }
70232         /**
70233          * Set options for tag.
70234          *
70235          * @description Sets all the option properties provided and keeps
70236          * the rest of the values as is.
70237          *
70238          * @param {ExtremePointTagOptions} options - Extreme point tag options
70239          *
70240          * @fires changed
70241          */
70242         setOptions(options) {
70243             this._editable = options.editable == null ? this._editable : options.editable;
70244             this._indicateVertices = options.indicateVertices == null ? this._indicateVertices : options.indicateVertices;
70245             this._lineColor = options.lineColor == null ? this._lineColor : options.lineColor;
70246             this._lineWidth = options.lineWidth == null ? this._lineWidth : options.lineWidth;
70247             this._fillColor = options.fillColor == null ? this._fillColor : options.fillColor;
70248             this._fillOpacity = options.fillOpacity == null ? this._fillOpacity : options.fillOpacity;
70249             this._notifyChanged$.next(this);
70250         }
70251     }
70252
70253     /**
70254      * Enumeration for tag domains.
70255      * @enum {number}
70256      * @readonly
70257      * @description Defines where lines between two vertices are treated
70258      * as straight.
70259      *
70260      * Only applicable for polygons. For rectangles lines between
70261      * vertices are always treated as straight in the distorted 2D
70262      * projection and bended in the undistorted 3D space.
70263      */
70264     exports.TagDomain = void 0;
70265     (function (TagDomain) {
70266         /**
70267          * Treats lines between two vertices as straight in the
70268          * distorted 2D projection, i.e. on the image. If the image
70269          * is distorted this will result in bended lines when rendered
70270          * in the undistorted 3D space.
70271          */
70272         TagDomain[TagDomain["TwoDimensional"] = 0] = "TwoDimensional";
70273         /**
70274          * Treats lines as straight in the undistorted 3D space. If the
70275          * image is distorted this will result in bended lines when rendered
70276          * on the distorted 2D projection of the image.
70277          */
70278         TagDomain[TagDomain["ThreeDimensional"] = 1] = "ThreeDimensional";
70279     })(exports.TagDomain || (exports.TagDomain = {}));
70280
70281     /**
70282      * @class OutlineRenderTag
70283      * @classdesc Tag visualizing the properties of an OutlineTag.
70284      */
70285     class OutlineRenderTag extends OutlineRenderTagBase {
70286         constructor(tag, transform) {
70287             super(tag, transform);
70288             this._fill = !isSpherical(transform.cameraType) ?
70289                 this._createFill() :
70290                 tag.domain === exports.TagDomain.TwoDimensional &&
70291                     tag.geometry instanceof PolygonGeometry ?
70292                     this._createFill() :
70293                     null;
70294             this._holes = this._tag.lineWidth >= 1 ?
70295                 this._createHoles() :
70296                 [];
70297             this._outline = this._tag.lineWidth >= 1 ?
70298                 this._createOutline() :
70299                 null;
70300         }
70301         dispose() {
70302             super.dispose();
70303             this._disposeFill();
70304             this._disposeHoles();
70305             this._disposeOutline();
70306         }
70307         getDOMObjects(atlas, camera, size) {
70308             const vNodes = [];
70309             const isRect = this._tag.geometry instanceof RectGeometry;
70310             const isPerspective = !isSpherical(this._transform.cameraType);
70311             const container = {
70312                 offsetHeight: size.height, offsetWidth: size.width,
70313             };
70314             if (this._tag.icon != null && (isRect || isPerspective)) {
70315                 const [iconBasicX, iconBasicY] = this._tag.geometry instanceof RectGeometry ?
70316                     this._tag.geometry.getVertex2d(this._tag.iconIndex) :
70317                     this._tag.geometry.getPoleOfInaccessibility2d();
70318                 const iconCanvas = this._viewportCoords.basicToCanvasSafe(iconBasicX, iconBasicY, container, this._transform, camera);
70319                 if (iconCanvas != null) {
70320                     const interact = () => {
70321                         this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: this._tag });
70322                     };
70323                     if (atlas.loaded) {
70324                         const sprite = atlas.getDOMSprite(this._tag.icon, this._tag.iconFloat);
70325                         const iconCanvasX = Math.round(iconCanvas[0]);
70326                         const iconCanvasY = Math.round(iconCanvas[1]);
70327                         const transform = `translate(${iconCanvasX}px,${iconCanvasY}px)`;
70328                         const click = (e) => {
70329                             e.stopPropagation();
70330                             this._tag.click$.next(this._tag);
70331                         };
70332                         const properties = {
70333                             onclick: click,
70334                             onpointerdown: interact,
70335                             style: { transform: transform },
70336                         };
70337                         vNodes.push(virtualDom.h("div.mapillary-tag-symbol", properties, [sprite]));
70338                     }
70339                 }
70340             }
70341             else if (this._tag.text != null && (isRect || isPerspective)) {
70342                 const [textBasicX, textBasicY] = this._tag.geometry instanceof RectGeometry ?
70343                     this._tag.geometry.getVertex2d(3) :
70344                     this._tag.geometry.getPoleOfInaccessibility2d();
70345                 const textCanvas = this._viewportCoords.basicToCanvasSafe(textBasicX, textBasicY, container, this._transform, camera);
70346                 if (textCanvas != null) {
70347                     const textCanvasX = Math.round(textCanvas[0]);
70348                     const textCanvasY = Math.round(textCanvas[1]);
70349                     const transform = this._tag.geometry instanceof RectGeometry ?
70350                         `translate(${textCanvasX}px,${textCanvasY}px)` :
70351                         `translate(-50%, -50%) translate(${textCanvasX}px,${textCanvasY}px)`;
70352                     const interact = () => {
70353                         this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: this._tag });
70354                     };
70355                     const properties = {
70356                         onpointerdown: interact,
70357                         style: {
70358                             color: this._colorToCss(this._tag.textColor),
70359                             transform: transform,
70360                         },
70361                         textContent: this._tag.text,
70362                     };
70363                     vNodes.push(virtualDom.h("span.mapillary-tag-symbol", properties, []));
70364                 }
70365             }
70366             if (!this._tag.editable) {
70367                 return vNodes;
70368             }
70369             const lineColor = this._colorToCss(this._tag.lineColor);
70370             if (this._tag.geometry instanceof RectGeometry) {
70371                 const [centroidBasicX, centroidBasicY] = this._tag.geometry.getCentroid2d();
70372                 const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidBasicX, centroidBasicY, container, this._transform, camera);
70373                 if (centroidCanvas != null) {
70374                     const interact = this._interact(TagOperation.Centroid, "move");
70375                     const centroidCanvasX = Math.round(centroidCanvas[0]);
70376                     const centroidCanvasY = Math.round(centroidCanvas[1]);
70377                     const transform = `translate(-50%, -50%) translate(${centroidCanvasX}px,${centroidCanvasY}px)`;
70378                     const properties = {
70379                         onpointerdown: interact,
70380                         style: { background: lineColor, transform: transform },
70381                     };
70382                     vNodes.push(virtualDom.h("div.mapillary-tag-mover", properties, []));
70383                 }
70384             }
70385             const vertices2d = this._tag.geometry.getVertices2d();
70386             for (let i = 0; i < vertices2d.length - 1; i++) {
70387                 if (isRect &&
70388                     ((this._tag.icon != null && i === this._tag.iconIndex) ||
70389                         (this._tag.icon == null && this._tag.text != null && i === 3))) {
70390                     continue;
70391                 }
70392                 const [vertexBasicX, vertexBasicY] = vertices2d[i];
70393                 const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasicX, vertexBasicY, container, this._transform, camera);
70394                 if (vertexCanvas == null) {
70395                     continue;
70396                 }
70397                 const cursor = isRect ?
70398                     i % 2 === 0 ? "nesw-resize" : "nwse-resize" :
70399                     "crosshair";
70400                 const interact = this._interact(TagOperation.Vertex, cursor, i);
70401                 const vertexCanvasX = Math.round(vertexCanvas[0]);
70402                 const vertexCanvasY = Math.round(vertexCanvas[1]);
70403                 const transform = `translate(-50%, -50%) translate(${vertexCanvasX}px,${vertexCanvasY}px)`;
70404                 const properties = {
70405                     onpointerdown: interact,
70406                     style: { background: lineColor, transform: transform, cursor: cursor },
70407                 };
70408                 vNodes.push(virtualDom.h("div.mapillary-tag-resizer", properties, []));
70409                 if (!this._tag.indicateVertices) {
70410                     continue;
70411                 }
70412                 const pointProperties = {
70413                     style: { background: lineColor, transform: transform },
70414                 };
70415                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
70416             }
70417             return vNodes;
70418         }
70419         getGLObjects() {
70420             const glObjects = [];
70421             if (this._fill != null) {
70422                 glObjects.push(this._fill);
70423             }
70424             for (const hole of this._holes) {
70425                 glObjects.push(hole);
70426             }
70427             if (this._outline != null) {
70428                 glObjects.push(this._outline);
70429             }
70430             return glObjects;
70431         }
70432         getRetrievableObjects() {
70433             return this._fill != null ? [this._fill] : [];
70434         }
70435         _onGeometryChanged() {
70436             if (this._fill != null) {
70437                 this._updateFillGeometry();
70438             }
70439             if (this._holes.length > 0) {
70440                 this._updateHoleGeometries();
70441             }
70442             if (this._outline != null) {
70443                 this._updateOulineGeometry();
70444             }
70445         }
70446         _onTagChanged() {
70447             let glObjectsChanged = false;
70448             if (this._fill != null) {
70449                 this._updateFillMaterial(this._fill.material);
70450             }
70451             if (this._outline == null) {
70452                 if (this._tag.lineWidth >= 1) {
70453                     this._holes = this._createHoles();
70454                     this._outline = this._createOutline();
70455                     glObjectsChanged = true;
70456                 }
70457             }
70458             else {
70459                 this._updateHoleMaterials();
70460                 this._updateOutlineMaterial();
70461             }
70462             return glObjectsChanged;
70463         }
70464         _getPoints3d() {
70465             return this._in3dDomain() ?
70466                 this._tag.geometry.getVertices3d(this._transform) :
70467                 this._tag.geometry.getPoints3d(this._transform);
70468         }
70469         _getTriangles() {
70470             return this._in3dDomain() ?
70471                 this._tag.geometry.get3dDomainTriangles3d(this._transform) :
70472                 this._tag.geometry.getTriangles3d(this._transform);
70473         }
70474         _updateFillMaterial(material) {
70475             material.color = new Color(this._tag.fillColor);
70476             material.opacity = this._tag.fillOpacity;
70477             material.needsUpdate = true;
70478         }
70479         _updateLineBasicMaterial(material) {
70480             material.color = new Color(this._tag.lineColor);
70481             material.linewidth = Math.max(this._tag.lineWidth, 1);
70482             material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
70483             material.opacity = this._tag.lineOpacity;
70484             material.transparent = this._tag.lineOpacity < 1;
70485             material.needsUpdate = true;
70486         }
70487         _createHoles() {
70488             let holes = [];
70489             if (this._tag.geometry instanceof PolygonGeometry) {
70490                 let holes3d = this._getHoles3d();
70491                 for (let holePoints3d of holes3d) {
70492                     let hole = this._createLine(holePoints3d);
70493                     holes.push(hole);
70494                 }
70495             }
70496             return holes;
70497         }
70498         _disposeHoles() {
70499             for (let hole of this._holes) {
70500                 hole.geometry.dispose();
70501                 hole.material.dispose();
70502             }
70503             this._holes = [];
70504         }
70505         _getHoles3d() {
70506             const polygonGeometry = this._tag.geometry;
70507             return this._in3dDomain() ?
70508                 polygonGeometry.getHoleVertices3d(this._transform) :
70509                 polygonGeometry.getHolePoints3d(this._transform);
70510         }
70511         _in3dDomain() {
70512             return this._tag.geometry instanceof PolygonGeometry && this._tag.domain === exports.TagDomain.ThreeDimensional;
70513         }
70514         _updateHoleGeometries() {
70515             let holes3d = this._getHoles3d();
70516             if (holes3d.length !== this._holes.length) {
70517                 throw new Error("Changing the number of holes is not supported.");
70518             }
70519             for (let i = 0; i < this._holes.length; i++) {
70520                 let holePoints3d = holes3d[i];
70521                 let hole = this._holes[i];
70522                 this._updateLine(hole, holePoints3d);
70523             }
70524         }
70525         _updateHoleMaterials() {
70526             for (const hole of this._holes) {
70527                 this._updateLineBasicMaterial(hole.material);
70528             }
70529         }
70530         _updateOutlineMaterial() {
70531             this._updateLineBasicMaterial(this._outline.material);
70532         }
70533     }
70534
70535     /**
70536      * Enumeration for alignments
70537      * @enum {number}
70538      * @readonly
70539      */
70540     exports.Alignment = void 0;
70541     (function (Alignment) {
70542         /**
70543          * Align to bottom
70544          */
70545         Alignment[Alignment["Bottom"] = 0] = "Bottom";
70546         /**
70547          * Align to bottom left
70548          */
70549         Alignment[Alignment["BottomLeft"] = 1] = "BottomLeft";
70550         /**
70551          * Align to bottom right
70552          */
70553         Alignment[Alignment["BottomRight"] = 2] = "BottomRight";
70554         /**
70555          * Align to center
70556          */
70557         Alignment[Alignment["Center"] = 3] = "Center";
70558         /**
70559          * Align to left
70560          */
70561         Alignment[Alignment["Left"] = 4] = "Left";
70562         /**
70563          * Align to right
70564          */
70565         Alignment[Alignment["Right"] = 5] = "Right";
70566         /**
70567          * Align to top
70568          */
70569         Alignment[Alignment["Top"] = 6] = "Top";
70570         /**
70571          * Align to top left
70572          */
70573         Alignment[Alignment["TopLeft"] = 7] = "TopLeft";
70574         /**
70575          * Align to top right
70576          */
70577         Alignment[Alignment["TopRight"] = 8] = "TopRight";
70578     })(exports.Alignment || (exports.Alignment = {}));
70579
70580     /**
70581      * @class OutlineTag
70582      *
70583      * @classdesc Tag holding properties for visualizing a geometry outline.
70584      *
70585      * @example
70586      * ```js
70587      * var geometry = new RectGeometry([0.3, 0.3, 0.5, 0.4]);
70588      * var tag = new OutlineTag(
70589      *     "id-1",
70590      *     geometry
70591      *     { editable: true, lineColor: 0xff0000 });
70592      *
70593      * tagComponent.add([tag]);
70594      * ```
70595      */
70596     class OutlineTag extends Tag {
70597         /**
70598          * Create an outline tag.
70599          *
70600          * @override
70601          * @constructor
70602          * @param {string} id - Unique identifier of the tag.
70603          * @param {VertexGeometry} geometry - Geometry defining vertices of tag.
70604          * @param {OutlineTagOptions} options - Options defining the visual appearance and
70605          * behavior of the outline tag.
70606          */
70607         constructor(id, geometry, options) {
70608             super(id, geometry);
70609             options = !!options ? options : {};
70610             const domain = options.domain != null && geometry instanceof PolygonGeometry ?
70611                 options.domain : exports.TagDomain.TwoDimensional;
70612             const twoDimensionalPolygon = this._twoDimensionalPolygon(domain, geometry);
70613             this._domain = domain;
70614             this._editable = options.editable == null || twoDimensionalPolygon ? false : options.editable;
70615             this._fillColor = options.fillColor == null ? 0xFFFFFF : options.fillColor;
70616             this._fillOpacity = options.fillOpacity == null ? 0.0 : options.fillOpacity;
70617             this._icon = options.icon === undefined ? null : options.icon;
70618             this._iconFloat = options.iconFloat == null ? exports.Alignment.Center : options.iconFloat;
70619             this._iconIndex = options.iconIndex == null ? 3 : options.iconIndex;
70620             this._indicateVertices = options.indicateVertices == null ? true : options.indicateVertices;
70621             this._lineColor = options.lineColor == null ? 0xFFFFFF : options.lineColor;
70622             this._lineOpacity = options.lineOpacity == null ? 1 : options.lineOpacity;
70623             this._lineWidth = options.lineWidth == null ? 1 : options.lineWidth;
70624             this._text = options.text === undefined ? null : options.text;
70625             this._textColor = options.textColor == null ? 0xFFFFFF : options.textColor;
70626             this._click$ = new Subject();
70627             this._click$
70628                 .subscribe(() => {
70629                 const type = "click";
70630                 const event = {
70631                     target: this,
70632                     type,
70633                 };
70634                 this.fire(type, event);
70635             });
70636         }
70637         /**
70638          * Click observable.
70639          *
70640          * @description An observable emitting the tag when the icon of the
70641          * tag has been clicked.
70642          *
70643          * @returns {Observable<Tag>}
70644          */
70645         get click$() {
70646             return this._click$;
70647         }
70648         /**
70649          * Get domain property.
70650          *
70651          * @description Readonly property that can only be set in constructor.
70652          *
70653          * @returns Value indicating the domain of the tag.
70654          */
70655         get domain() {
70656             return this._domain;
70657         }
70658         /**
70659          * Get editable property.
70660          * @returns {boolean} Value indicating if tag is editable.
70661          */
70662         get editable() {
70663             return this._editable;
70664         }
70665         /**
70666          * Set editable property.
70667          * @param {boolean}
70668          *
70669          * @fires changed
70670          */
70671         set editable(value) {
70672             if (this._twoDimensionalPolygon(this._domain, this._geometry)) {
70673                 return;
70674             }
70675             this._editable = value;
70676             this._notifyChanged$.next(this);
70677         }
70678         /**
70679          * Get fill color property.
70680          * @returns {number}
70681          */
70682         get fillColor() {
70683             return this._fillColor;
70684         }
70685         /**
70686          * Set fill color property.
70687          * @param {number}
70688          *
70689          * @fires changed
70690          */
70691         set fillColor(value) {
70692             this._fillColor = value;
70693             this._notifyChanged$.next(this);
70694         }
70695         /**
70696          * Get fill opacity property.
70697          * @returns {number}
70698          */
70699         get fillOpacity() {
70700             return this._fillOpacity;
70701         }
70702         /**
70703          * Set fill opacity property.
70704          * @param {number}
70705          *
70706          * @fires changed
70707          */
70708         set fillOpacity(value) {
70709             this._fillOpacity = value;
70710             this._notifyChanged$.next(this);
70711         }
70712         /** @inheritdoc */
70713         get geometry() {
70714             return this._geometry;
70715         }
70716         /**
70717          * Get icon property.
70718          * @returns {string}
70719          */
70720         get icon() {
70721             return this._icon;
70722         }
70723         /**
70724          * Set icon property.
70725          * @param {string}
70726          *
70727          * @fires changed
70728          */
70729         set icon(value) {
70730             this._icon = value;
70731             this._notifyChanged$.next(this);
70732         }
70733         /**
70734          * Get icon float property.
70735          * @returns {Alignment}
70736          */
70737         get iconFloat() {
70738             return this._iconFloat;
70739         }
70740         /**
70741          * Set icon float property.
70742          * @param {Alignment}
70743          *
70744          * @fires changed
70745          */
70746         set iconFloat(value) {
70747             this._iconFloat = value;
70748             this._notifyChanged$.next(this);
70749         }
70750         /**
70751          * Get icon index property.
70752          * @returns {number}
70753          */
70754         get iconIndex() {
70755             return this._iconIndex;
70756         }
70757         /**
70758          * Set icon index property.
70759          * @param {number}
70760          *
70761          * @fires changed
70762          */
70763         set iconIndex(value) {
70764             this._iconIndex = value;
70765             this._notifyChanged$.next(this);
70766         }
70767         /**
70768          * Get indicate vertices property.
70769          * @returns {boolean} Value indicating if vertices should be indicated
70770          * when tag is editable.
70771          */
70772         get indicateVertices() {
70773             return this._indicateVertices;
70774         }
70775         /**
70776          * Set indicate vertices property.
70777          * @param {boolean}
70778          *
70779          * @fires changed
70780          */
70781         set indicateVertices(value) {
70782             this._indicateVertices = value;
70783             this._notifyChanged$.next(this);
70784         }
70785         /**
70786          * Get line color property.
70787          * @returns {number}
70788          */
70789         get lineColor() {
70790             return this._lineColor;
70791         }
70792         /**
70793          * Set line color property.
70794          * @param {number}
70795          *
70796          * @fires changed
70797          */
70798         set lineColor(value) {
70799             this._lineColor = value;
70800             this._notifyChanged$.next(this);
70801         }
70802         /**
70803          * Get line opacity property.
70804          * @returns {number}
70805          */
70806         get lineOpacity() {
70807             return this._lineOpacity;
70808         }
70809         /**
70810          * Set line opacity property.
70811          * @param {number}
70812          *
70813          * @fires changed
70814          */
70815         set lineOpacity(value) {
70816             this._lineOpacity = value;
70817             this._notifyChanged$.next(this);
70818         }
70819         /**
70820          * Get line width property.
70821          * @returns {number}
70822          */
70823         get lineWidth() {
70824             return this._lineWidth;
70825         }
70826         /**
70827          * Set line width property.
70828          * @param {number}
70829          *
70830          * @fires changed
70831          */
70832         set lineWidth(value) {
70833             this._lineWidth = value;
70834             this._notifyChanged$.next(this);
70835         }
70836         /**
70837          * Get text property.
70838          * @returns {string}
70839          */
70840         get text() {
70841             return this._text;
70842         }
70843         /**
70844          * Set text property.
70845          * @param {string}
70846          *
70847          * @fires changed
70848          */
70849         set text(value) {
70850             this._text = value;
70851             this._notifyChanged$.next(this);
70852         }
70853         /**
70854          * Get text color property.
70855          * @returns {number}
70856          */
70857         get textColor() {
70858             return this._textColor;
70859         }
70860         /**
70861          * Set text color property.
70862          * @param {number}
70863          *
70864          * @fires changed
70865          */
70866         set textColor(value) {
70867             this._textColor = value;
70868             this._notifyChanged$.next(this);
70869         }
70870         fire(type, event) {
70871             super.fire(type, event);
70872         }
70873         off(type, handler) {
70874             super.off(type, handler);
70875         }
70876         on(type, handler) {
70877             super.on(type, handler);
70878         }
70879         /**
70880          * Set options for tag.
70881          *
70882          * @description Sets all the option properties provided and keeps
70883          * the rest of the values as is.
70884          *
70885          * @param {OutlineTagOptions} options - Outline tag options
70886          *
70887          * @fires changed
70888          */
70889         setOptions(options) {
70890             const twoDimensionalPolygon = this._twoDimensionalPolygon(this._domain, this._geometry);
70891             this._editable = twoDimensionalPolygon || options.editable == null ? this._editable : options.editable;
70892             this._icon = options.icon === undefined ? this._icon : options.icon;
70893             this._iconFloat = options.iconFloat == null ? this._iconFloat : options.iconFloat;
70894             this._iconIndex = options.iconIndex == null ? this._iconIndex : options.iconIndex;
70895             this._indicateVertices = options.indicateVertices == null ? this._indicateVertices : options.indicateVertices;
70896             this._lineColor = options.lineColor == null ? this._lineColor : options.lineColor;
70897             this._lineWidth = options.lineWidth == null ? this._lineWidth : options.lineWidth;
70898             this._fillColor = options.fillColor == null ? this._fillColor : options.fillColor;
70899             this._fillOpacity = options.fillOpacity == null ? this._fillOpacity : options.fillOpacity;
70900             this._text = options.text === undefined ? this._text : options.text;
70901             this._textColor = options.textColor == null ? this._textColor : options.textColor;
70902             this._notifyChanged$.next(this);
70903         }
70904         _twoDimensionalPolygon(domain, geometry) {
70905             return domain !== exports.TagDomain.ThreeDimensional && geometry instanceof PolygonGeometry;
70906         }
70907     }
70908
70909     /**
70910      * @class SpotRenderTag
70911      * @classdesc Tag visualizing the properties of a SpotTag.
70912      */
70913     class SpotRenderTag extends RenderTag {
70914         dispose() { }
70915         getDOMObjects(atlas, camera, size) {
70916             const tag = this._tag;
70917             const container = {
70918                 offsetHeight: size.height, offsetWidth: size.width,
70919             };
70920             const vNodes = [];
70921             const [centroidBasicX, centroidBasicY] = tag.geometry.getCentroid2d();
70922             const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidBasicX, centroidBasicY, container, this._transform, camera);
70923             if (centroidCanvas != null) {
70924                 const interactNone = (e) => {
70925                     this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: tag });
70926                 };
70927                 const canvasX = Math.round(centroidCanvas[0]);
70928                 const canvasY = Math.round(centroidCanvas[1]);
70929                 if (tag.icon != null) {
70930                     if (atlas.loaded) {
70931                         const sprite = atlas.getDOMSprite(tag.icon, exports.Alignment.Bottom);
70932                         const iconTransform = `translate(${canvasX}px,${canvasY + 8}px)`;
70933                         const properties = {
70934                             onpointerdown: interactNone,
70935                             style: {
70936                                 pointerEvents: "all",
70937                                 transform: iconTransform,
70938                             },
70939                         };
70940                         vNodes.push(virtualDom.h("div", properties, [sprite]));
70941                     }
70942                 }
70943                 else if (tag.text != null) {
70944                     const textTransform = `translate(-50%,0%) translate(${canvasX}px,${canvasY + 8}px)`;
70945                     const properties = {
70946                         onpointerdown: interactNone,
70947                         style: {
70948                             color: this._colorToCss(tag.textColor),
70949                             transform: textTransform,
70950                         },
70951                         textContent: tag.text,
70952                     };
70953                     vNodes.push(virtualDom.h("span.mapillary-tag-symbol", properties, []));
70954                 }
70955                 const interact = this._interact(TagOperation.Centroid, tag, "move");
70956                 const background = this._colorToCss(tag.color);
70957                 const transform = `translate(-50%,-50%) translate(${canvasX}px,${canvasY}px)`;
70958                 if (tag.editable) {
70959                     let interactorProperties = {
70960                         onpointerdown: interact,
70961                         style: {
70962                             background: background,
70963                             transform: transform,
70964                         },
70965                     };
70966                     vNodes.push(virtualDom.h("div.mapillary-tag-spot-interactor", interactorProperties, []));
70967                 }
70968                 const pointProperties = {
70969                     style: {
70970                         background: background,
70971                         transform: transform,
70972                     },
70973                 };
70974                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
70975             }
70976             return vNodes;
70977         }
70978         getGLObjects() { return []; }
70979         getRetrievableObjects() { return []; }
70980         _colorToCss(color) {
70981             return "#" + ("000000" + color.toString(16)).substr(-6);
70982         }
70983         _interact(operation, tag, cursor, vertexIndex) {
70984             return (e) => {
70985                 const offsetX = e.offsetX - e.target.offsetWidth / 2;
70986                 const offsetY = e.offsetY - e.target.offsetHeight / 2;
70987                 this._interact$.next({
70988                     cursor: cursor,
70989                     offsetX: offsetX,
70990                     offsetY: offsetY,
70991                     operation: operation,
70992                     tag: tag,
70993                     vertexIndex: vertexIndex,
70994                 });
70995             };
70996         }
70997     }
70998
70999     /**
71000      * @class SpotTag
71001      *
71002      * @classdesc Tag holding properties for visualizing the centroid of a geometry.
71003      *
71004      * @example
71005      * ```js
71006      * var geometry = new PointGeometry([0.3, 0.3]);
71007      * var tag = new SpotTag(
71008      *     "id-1",
71009      *     geometry
71010      *     { editable: true, color: 0xff0000 });
71011      *
71012      * tagComponent.add([tag]);
71013      * ```
71014      */
71015     class SpotTag extends Tag {
71016         /**
71017          * Create a spot tag.
71018          *
71019          * @override
71020          * @constructor
71021          * @param {string} id
71022          * @param {Geometry} geometry
71023          * @param {IOutlineTagOptions} options - Options defining the visual appearance and
71024          * behavior of the spot tag.
71025          */
71026         constructor(id, geometry, options) {
71027             super(id, geometry);
71028             options = !!options ? options : {};
71029             this._color = options.color == null ? 0xFFFFFF : options.color;
71030             this._editable = options.editable == null ? false : options.editable;
71031             this._icon = options.icon === undefined ? null : options.icon;
71032             this._text = options.text === undefined ? null : options.text;
71033             this._textColor = options.textColor == null ? 0xFFFFFF : options.textColor;
71034         }
71035         /**
71036          * Get color property.
71037          * @returns {number} The color of the spot as a hexagonal number;
71038          */
71039         get color() {
71040             return this._color;
71041         }
71042         /**
71043          * Set color property.
71044          * @param {number}
71045          *
71046          * @fires changed
71047          */
71048         set color(value) {
71049             this._color = value;
71050             this._notifyChanged$.next(this);
71051         }
71052         /**
71053          * Get editable property.
71054          * @returns {boolean} Value indicating if tag is editable.
71055          */
71056         get editable() {
71057             return this._editable;
71058         }
71059         /**
71060          * Set editable property.
71061          * @param {boolean}
71062          *
71063          * @fires changed
71064          */
71065         set editable(value) {
71066             this._editable = value;
71067             this._notifyChanged$.next(this);
71068         }
71069         /**
71070          * Get icon property.
71071          * @returns {string}
71072          */
71073         get icon() {
71074             return this._icon;
71075         }
71076         /**
71077          * Set icon property.
71078          * @param {string}
71079          *
71080          * @fires changed
71081          */
71082         set icon(value) {
71083             this._icon = value;
71084             this._notifyChanged$.next(this);
71085         }
71086         /**
71087          * Get text property.
71088          * @returns {string}
71089          */
71090         get text() {
71091             return this._text;
71092         }
71093         /**
71094          * Set text property.
71095          * @param {string}
71096          *
71097          * @fires changed
71098          */
71099         set text(value) {
71100             this._text = value;
71101             this._notifyChanged$.next(this);
71102         }
71103         /**
71104          * Get text color property.
71105          * @returns {number}
71106          */
71107         get textColor() {
71108             return this._textColor;
71109         }
71110         /**
71111          * Set text color property.
71112          * @param {number}
71113          *
71114          * @fires changed
71115          */
71116         set textColor(value) {
71117             this._textColor = value;
71118             this._notifyChanged$.next(this);
71119         }
71120         /**
71121          * Set options for tag.
71122          *
71123          * @description Sets all the option properties provided and keps
71124          * the rest of the values as is.
71125          *
71126          * @param {SpotTagOptions} options - Spot tag options
71127          *
71128          * @fires changed
71129          */
71130         setOptions(options) {
71131             this._color = options.color == null ? this._color : options.color;
71132             this._editable = options.editable == null ? this._editable : options.editable;
71133             this._icon = options.icon === undefined ? this._icon : options.icon;
71134             this._text = options.text === undefined ? this._text : options.text;
71135             this._textColor = options.textColor == null ? this._textColor : options.textColor;
71136             this._notifyChanged$.next(this);
71137         }
71138     }
71139
71140     class TagSet {
71141         constructor() {
71142             this._active = false;
71143             this._hash = {};
71144             this._hashDeactivated = {};
71145             this._notifyChanged$ = new Subject();
71146         }
71147         get active() {
71148             return this._active;
71149         }
71150         get changed$() {
71151             return this._notifyChanged$;
71152         }
71153         activate(transform) {
71154             if (this._active) {
71155                 return;
71156             }
71157             for (const id in this._hashDeactivated) {
71158                 if (!this._hashDeactivated.hasOwnProperty(id)) {
71159                     continue;
71160                 }
71161                 const tag = this._hashDeactivated[id];
71162                 this._add(tag, transform);
71163             }
71164             this._hashDeactivated = {};
71165             this._active = true;
71166             this._notifyChanged$.next(this);
71167         }
71168         deactivate() {
71169             if (!this._active) {
71170                 return;
71171             }
71172             for (const id in this._hash) {
71173                 if (!this._hash.hasOwnProperty(id)) {
71174                     continue;
71175                 }
71176                 this._hashDeactivated[id] = this._hash[id].tag;
71177             }
71178             this._hash = {};
71179             this._active = false;
71180         }
71181         add(tags, transform) {
71182             this._assertActivationState(true);
71183             for (const tag of tags) {
71184                 this._add(tag, transform);
71185             }
71186             this._notifyChanged$.next(this);
71187         }
71188         addDeactivated(tags) {
71189             this._assertActivationState(false);
71190             for (const tag of tags) {
71191                 if (!(tag instanceof OutlineTag ||
71192                     tag instanceof SpotTag ||
71193                     tag instanceof ExtremePointTag)) {
71194                     throw new Error("Tag type not supported");
71195                 }
71196                 this._hashDeactivated[tag.id] = tag;
71197             }
71198         }
71199         get(id) {
71200             return this.has(id) ? this._hash[id] : undefined;
71201         }
71202         getAll() {
71203             const hash = this._hash;
71204             return Object.keys(hash)
71205                 .map((id) => {
71206                 return hash[id];
71207             });
71208         }
71209         getAllDeactivated() {
71210             const hashDeactivated = this._hashDeactivated;
71211             return Object.keys(hashDeactivated)
71212                 .map((id) => {
71213                 return hashDeactivated[id];
71214             });
71215         }
71216         getDeactivated(id) {
71217             return this.hasDeactivated(id) ? this._hashDeactivated[id] : undefined;
71218         }
71219         has(id) {
71220             return id in this._hash;
71221         }
71222         hasDeactivated(id) {
71223             return id in this._hashDeactivated;
71224         }
71225         remove(ids) {
71226             this._assertActivationState(true);
71227             const hash = this._hash;
71228             for (const id of ids) {
71229                 if (!(id in hash)) {
71230                     continue;
71231                 }
71232                 delete hash[id];
71233             }
71234             this._notifyChanged$.next(this);
71235         }
71236         removeAll() {
71237             this._assertActivationState(true);
71238             this._hash = {};
71239             this._notifyChanged$.next(this);
71240         }
71241         removeAllDeactivated() {
71242             this._assertActivationState(false);
71243             this._hashDeactivated = {};
71244         }
71245         removeDeactivated(ids) {
71246             this._assertActivationState(false);
71247             const hashDeactivated = this._hashDeactivated;
71248             for (const id of ids) {
71249                 if (!(id in hashDeactivated)) {
71250                     continue;
71251                 }
71252                 delete hashDeactivated[id];
71253             }
71254         }
71255         _add(tag, transform) {
71256             if (tag instanceof OutlineTag) {
71257                 this._hash[tag.id] = new OutlineRenderTag(tag, transform);
71258             }
71259             else if (tag instanceof SpotTag) {
71260                 this._hash[tag.id] = new SpotRenderTag(tag, transform);
71261             }
71262             else if (tag instanceof ExtremePointTag) {
71263                 this._hash[tag.id] = new ExtremePointRenderTag(tag, transform);
71264             }
71265             else {
71266                 throw new Error("Tag type not supported");
71267             }
71268         }
71269         _assertActivationState(should) {
71270             if (should !== this._active) {
71271                 throw new Error("Tag set not in correct state for operation.");
71272             }
71273         }
71274     }
71275
71276     /**
71277      * @class PointGeometry
71278      *
71279      * @classdesc Represents a point geometry in the 2D basic image coordinate system.
71280      *
71281      * @example
71282      * ```js
71283      * var basicPoint = [0.5, 0.7];
71284      * var pointGeometry = new PointGeometry(basicPoint);
71285      * ```
71286      */
71287     class PointGeometry extends Geometry {
71288         /**
71289          * Create a point geometry.
71290          *
71291          * @constructor
71292          * @param {Array<number>} point - An array representing the basic coordinates of
71293          * the point.
71294          *
71295          * @throws {GeometryTagError} Point coordinates must be valid basic coordinates.
71296          */
71297         constructor(point) {
71298             super();
71299             let x = point[0];
71300             let y = point[1];
71301             if (x < 0 || x > 1 || y < 0 || y > 1) {
71302                 throw new GeometryTagError("Basic coordinates must be on the interval [0, 1].");
71303             }
71304             this._point = point.slice();
71305         }
71306         /**
71307          * Get point property.
71308          * @returns {Array<number>} Array representing the basic coordinates of the point.
71309          */
71310         get point() {
71311             return this._point;
71312         }
71313         /**
71314          * Get the 2D basic coordinates for the centroid of the point, i.e. the 2D
71315          * basic coordinates of the point itself.
71316          *
71317          * @returns {Array<number>} 2D basic coordinates representing the centroid.
71318          * @ignore
71319          */
71320         getCentroid2d() {
71321             return this._point.slice();
71322         }
71323         /**
71324          * Get the 3D world coordinates for the centroid of the point, i.e. the 3D
71325          * world coordinates of the point itself.
71326          *
71327          * @param {Transform} transform - The transform of the image related to the point.
71328          * @returns {Array<number>} 3D world coordinates representing the centroid.
71329          * @ignore
71330          */
71331         getCentroid3d(transform) {
71332             return transform.unprojectBasic(this._point, 200);
71333         }
71334         /**
71335          * Set the centroid of the point, i.e. the point coordinates.
71336          *
71337          * @param {Array<number>} value - The new value of the centroid.
71338          * @param {Transform} transform - The transform of the image related to the point.
71339          * @ignore
71340          */
71341         setCentroid2d(value, transform) {
71342             let changed = [
71343                 Math.max(0, Math.min(1, value[0])),
71344                 Math.max(0, Math.min(1, value[1])),
71345             ];
71346             this._point[0] = changed[0];
71347             this._point[1] = changed[1];
71348             this._notifyChanged$.next(this);
71349         }
71350     }
71351
71352     class TagHandlerBase extends HandlerBase {
71353         constructor(component, container, navigator, viewportCoords) {
71354             super(component, container, navigator);
71355             this._name = `${this._component.name}-${this._getNameExtension()}`;
71356             this._viewportCoords = viewportCoords;
71357         }
71358         _getConfiguration(enable) {
71359             return {};
71360         }
71361         _mouseEventToBasic(event, element, camera, transform, offsetX, offsetY) {
71362             offsetX = offsetX != null ? offsetX : 0;
71363             offsetY = offsetY != null ? offsetY : 0;
71364             const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
71365             const basic = this._viewportCoords.canvasToBasic(canvasX - offsetX, canvasY - offsetY, element, transform, camera.perspective);
71366             return basic;
71367         }
71368     }
71369
71370     class CreateHandlerBase extends TagHandlerBase {
71371         constructor(component, container, navigator, viewportCoords, tagCreator) {
71372             super(component, container, navigator, viewportCoords);
71373             this._tagCreator = tagCreator;
71374             this._geometryCreated$ = new Subject();
71375         }
71376         get geometryCreated$() {
71377             return this._geometryCreated$;
71378         }
71379         _enable() {
71380             this._enableCreate();
71381             this._container.container.classList.add("component-tag-create");
71382         }
71383         _disable() {
71384             this._container.container.classList.remove("component-tag-create");
71385             this._disableCreate();
71386         }
71387         _validateBasic(basic) {
71388             const x = basic[0];
71389             const y = basic[1];
71390             return 0 <= x && x <= 1 && 0 <= y && y <= 1;
71391         }
71392         _mouseEventToBasic$(mouseEvent$) {
71393             return mouseEvent$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$), map(([event, camera, transform]) => {
71394                 return this._mouseEventToBasic(event, this._container.container, camera, transform);
71395             }));
71396         }
71397     }
71398
71399     class CreatePointHandler extends CreateHandlerBase {
71400         _enableCreate() {
71401             this._container.mouseService.deferPixels(this._name, 4);
71402             this._geometryCreatedSubscription = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe(filter(this._validateBasic), map((basic) => {
71403                 return new PointGeometry(basic);
71404             }))
71405                 .subscribe(this._geometryCreated$);
71406         }
71407         _disableCreate() {
71408             this._container.mouseService.undeferPixels(this._name);
71409             this._geometryCreatedSubscription.unsubscribe();
71410         }
71411         _getNameExtension() {
71412             return "create-point";
71413         }
71414     }
71415
71416     class CreateVertexHandler extends CreateHandlerBase {
71417         _enableCreate() {
71418             this._container.mouseService.deferPixels(this._name, 4);
71419             const transformChanged$ = this._navigator.stateService.currentTransform$.pipe(map(() => { }), publishReplay(1), refCount());
71420             this._deleteSubscription = transformChanged$.pipe(skip(1))
71421                 .subscribe(this._tagCreator.delete$);
71422             const basicClick$ = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe(share());
71423             this._createSubscription = transformChanged$.pipe(switchMap(() => {
71424                 return basicClick$.pipe(filter(this._validateBasic), take(1));
71425             }))
71426                 .subscribe(this._create$);
71427             this._setVertexSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71428                 return !!tag ?
71429                     combineLatest(of(tag), merge(this._container.mouseService.mouseMove$, this._container.mouseService.domMouseMove$), this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$) :
71430                     empty();
71431             }))
71432                 .subscribe(([tag, event, camera, transform]) => {
71433                 const basicPoint = this._mouseEventToBasic(event, this._container.container, camera, transform);
71434                 this._setVertex2d(tag, basicPoint, transform);
71435             });
71436             this._addPointSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71437                 return !!tag ?
71438                     combineLatest(of(tag), basicClick$) :
71439                     empty();
71440             }))
71441                 .subscribe(([tag, basicPoint]) => {
71442                 this._addPoint(tag, basicPoint);
71443             });
71444             this._geometryCreateSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71445                 return !!tag ?
71446                     tag.created$.pipe(map((t) => {
71447                         return t.geometry;
71448                     })) :
71449                     empty();
71450             }))
71451                 .subscribe(this._geometryCreated$);
71452         }
71453         _disableCreate() {
71454             this._container.mouseService.undeferPixels(this._name);
71455             this._tagCreator.delete$.next(null);
71456             this._addPointSubscription.unsubscribe();
71457             this._createSubscription.unsubscribe();
71458             this._deleteSubscription.unsubscribe();
71459             this._geometryCreateSubscription.unsubscribe();
71460             this._setVertexSubscription.unsubscribe();
71461         }
71462     }
71463
71464     class CreatePointsHandler extends CreateVertexHandler {
71465         get _create$() {
71466             return this._tagCreator.createPoints$;
71467         }
71468         _addPoint(tag, basicPoint) {
71469             tag.geometry.addPoint2d(basicPoint);
71470         }
71471         _getNameExtension() {
71472             return "create-points";
71473         }
71474         _setVertex2d(tag, basicPoint, transform) {
71475             tag.geometry.setPoint2d((tag.geometry).points.length - 1, basicPoint, transform);
71476         }
71477     }
71478
71479     class CreatePolygonHandler extends CreateVertexHandler {
71480         get _create$() {
71481             return this._tagCreator.createPolygon$;
71482         }
71483         _addPoint(tag, basicPoint) {
71484             tag.addPoint(basicPoint);
71485         }
71486         _getNameExtension() {
71487             return "create-polygon";
71488         }
71489         _setVertex2d(tag, basicPoint, transform) {
71490             tag.geometry.setVertex2d(tag.geometry.polygon.length - 2, basicPoint, transform);
71491         }
71492     }
71493
71494     class CreateRectHandler extends CreateVertexHandler {
71495         get _create$() {
71496             return this._tagCreator.createRect$;
71497         }
71498         _addPoint(tag, basicPoint) {
71499             const rectGeometry = tag.geometry;
71500             if (!rectGeometry.validate(basicPoint)) {
71501                 basicPoint = rectGeometry.getNonAdjustedVertex2d(3);
71502             }
71503             tag.addPoint(basicPoint);
71504         }
71505         _enable() {
71506             super._enable();
71507             this._initializeAnchorIndexingSubscription = this._tagCreator.tag$.pipe(filter((tag) => {
71508                 return !!tag;
71509             }))
71510                 .subscribe((tag) => {
71511                 tag.geometry.initializeAnchorIndexing();
71512             });
71513         }
71514         _disable() {
71515             super._disable();
71516             this._initializeAnchorIndexingSubscription.unsubscribe();
71517         }
71518         _getNameExtension() {
71519             return "create-rect";
71520         }
71521         _setVertex2d(tag, basicPoint, transform) {
71522             tag.geometry.setOppositeVertex2d(basicPoint, transform);
71523         }
71524     }
71525
71526     class CreateRectDragHandler extends CreateHandlerBase {
71527         _enableCreate() {
71528             this._container.mouseService.claimMouse(this._name, 2);
71529             this._deleteSubscription = this._navigator.stateService.currentTransform$.pipe(map((transform) => { return null; }), skip(1))
71530                 .subscribe(this._tagCreator.delete$);
71531             this._createSubscription = this._mouseEventToBasic$(this._container.mouseService.filtered$(this._name, this._container.mouseService.mouseDragStart$)).pipe(filter(this._validateBasic))
71532                 .subscribe(this._tagCreator.createRect$);
71533             this._initializeAnchorIndexingSubscription = this._tagCreator.tag$.pipe(filter((tag) => {
71534                 return !!tag;
71535             }))
71536                 .subscribe((tag) => {
71537                 tag.geometry.initializeAnchorIndexing();
71538             });
71539             const basicMouse$ = combineLatest(merge(this._container.mouseService.filtered$(this._name, this._container.mouseService.mouseMove$), this._container.mouseService.filtered$(this._name, this._container.mouseService.domMouseMove$)), this._container.renderService.renderCamera$).pipe(withLatestFrom(this._navigator.stateService.currentTransform$), map(([[event, camera], transform]) => {
71540                 return this._mouseEventToBasic(event, this._container.container, camera, transform);
71541             }));
71542             this._setVertexSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71543                 return !!tag ?
71544                     combineLatest(of(tag), basicMouse$, this._navigator.stateService.currentTransform$) :
71545                     empty();
71546             }))
71547                 .subscribe(([tag, basicPoint, transform]) => {
71548                 tag.geometry.setOppositeVertex2d(basicPoint, transform);
71549             });
71550             const basicMouseDragEnd$ = this._container.mouseService.mouseDragEnd$.pipe(withLatestFrom(this._mouseEventToBasic$(this._container.mouseService.filtered$(this._name, this._container.mouseService.mouseDrag$)).pipe(filter(this._validateBasic)), (event, basicPoint) => {
71551                 return basicPoint;
71552             }), share());
71553             this._addPointSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71554                 return !!tag ?
71555                     combineLatest(of(tag), basicMouseDragEnd$) :
71556                     empty();
71557             }))
71558                 .subscribe(([tag, basicPoint]) => {
71559                 const rectGeometry = tag.geometry;
71560                 if (!rectGeometry.validate(basicPoint)) {
71561                     basicPoint = rectGeometry.getNonAdjustedVertex2d(3);
71562                 }
71563                 tag.addPoint(basicPoint);
71564             });
71565             this._geometryCreatedSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
71566                 return !!tag ?
71567                     tag.created$.pipe(map((t) => {
71568                         return t.geometry;
71569                     })) :
71570                     empty();
71571             }))
71572                 .subscribe(this._geometryCreated$);
71573         }
71574         _disableCreate() {
71575             this._container.mouseService.unclaimMouse(this._name);
71576             this._tagCreator.delete$.next(null);
71577             this._addPointSubscription.unsubscribe();
71578             this._createSubscription.unsubscribe();
71579             this._deleteSubscription.unsubscribe();
71580             this._geometryCreatedSubscription.unsubscribe();
71581             this._initializeAnchorIndexingSubscription.unsubscribe();
71582             this._setVertexSubscription.unsubscribe();
71583         }
71584         _getNameExtension() {
71585             return "create-rect-drag";
71586         }
71587     }
71588
71589     class EditVertexHandler extends TagHandlerBase {
71590         constructor(component, container, navigator, viewportCoords, tagSet) {
71591             super(component, container, navigator, viewportCoords);
71592             this._tagSet = tagSet;
71593         }
71594         _enable() {
71595             const interaction$ = this._tagSet.changed$.pipe(map((tagSet) => {
71596                 return tagSet.getAll();
71597             }), switchMap((tags) => {
71598                 return from(tags).pipe(mergeMap((tag) => {
71599                     return tag.interact$;
71600                 }));
71601             }), switchMap((interaction) => {
71602                 return concat(of(interaction), this._container.mouseService.documentMouseUp$.pipe(map(() => {
71603                     return { offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: null };
71604                 }), first()));
71605             }), share());
71606             merge(this._container.mouseService.mouseMove$, this._container.mouseService.domMouseMove$).pipe(share());
71607             this._claimMouseSubscription = interaction$.pipe(switchMap((interaction) => {
71608                 return !!interaction.tag ? this._container.mouseService.domMouseDragStart$ : empty();
71609             }))
71610                 .subscribe(() => {
71611                 this._container.mouseService.claimMouse(this._name, 3);
71612             });
71613             this._cursorSubscription = interaction$.pipe(map((interaction) => {
71614                 return interaction.cursor;
71615             }), distinctUntilChanged())
71616                 .subscribe((cursor) => {
71617                 const interactionCursors = ["crosshair", "move", "nesw-resize", "nwse-resize"];
71618                 for (const interactionCursor of interactionCursors) {
71619                     this._container.container.classList.remove(`component-tag-edit-${interactionCursor}`);
71620                 }
71621                 if (!!cursor) {
71622                     this._container.container.classList.add(`component-tag-edit-${cursor}`);
71623                 }
71624             });
71625             this._unclaimMouseSubscription = this._container.mouseService
71626                 .filtered$(this._name, this._container.mouseService.domMouseDragEnd$)
71627                 .subscribe((e) => {
71628                 this._container.mouseService.unclaimMouse(this._name);
71629             });
71630             this._preventDefaultSubscription = interaction$.pipe(switchMap((interaction) => {
71631                 return !!interaction.tag ?
71632                     this._container.mouseService.documentMouseMove$ :
71633                     empty();
71634             }))
71635                 .subscribe((event) => {
71636                 event.preventDefault(); // prevent selection of content outside the viewer
71637             });
71638             this._updateGeometrySubscription = interaction$.pipe(switchMap((interaction) => {
71639                 if (interaction.operation === TagOperation.None || !interaction.tag) {
71640                     return empty();
71641                 }
71642                 const mouseDrag$ = this._container.mouseService
71643                     .filtered$(this._name, this._container.mouseService.domMouseDrag$).pipe(filter((event) => {
71644                     return this._viewportCoords.insideElement(event, this._container.container);
71645                 }));
71646                 return combineLatest(mouseDrag$, this._container.renderService.renderCamera$).pipe(withLatestFrom(of(interaction), this._navigator.stateService.currentTransform$, ([event, render], i, transform) => {
71647                     return [event, render, i, transform];
71648                 }));
71649             }))
71650                 .subscribe(([mouseEvent, renderCamera, interaction, transform]) => {
71651                 const basic = this._mouseEventToBasic(mouseEvent, this._container.container, renderCamera, transform, interaction.offsetX, interaction.offsetY);
71652                 const geometry = interaction.tag.geometry;
71653                 if (interaction.operation === TagOperation.Centroid) {
71654                     geometry.setCentroid2d(basic, transform);
71655                 }
71656                 else if (interaction.operation === TagOperation.Vertex) {
71657                     geometry.setVertex2d(interaction.vertexIndex, basic, transform);
71658                 }
71659             });
71660         }
71661         _disable() {
71662             this._claimMouseSubscription.unsubscribe();
71663             this._cursorSubscription.unsubscribe();
71664             this._preventDefaultSubscription.unsubscribe();
71665             this._unclaimMouseSubscription.unsubscribe();
71666             this._updateGeometrySubscription.unsubscribe();
71667         }
71668         _getNameExtension() {
71669             return "edit-vertex";
71670         }
71671     }
71672
71673     /**
71674      * @class TagComponent
71675      *
71676      * @classdesc Component for showing and editing tags with different
71677      * geometries composed from 2D basic image coordinates (see the
71678      * {@link Viewer} class documentation for more information about coordinate
71679      * systems).
71680      *
71681      * The `add` method is used for adding new tags or replacing
71682      * tags already in the set. Tags are removed by id.
71683      *
71684      * If a tag already in the set has the same
71685      * id as one of the tags added, the old tag will be removed and
71686      * the added tag will take its place.
71687      *
71688      * The tag component mode can be set to either be non interactive or
71689      * to be in creating mode of a certain geometry type.
71690      *
71691      * The tag properties can be updated at any time and the change will
71692      * be visibile immediately.
71693      *
71694      * Tags are only relevant to a single image because they are based on
71695      * 2D basic image coordinates. Tags related to a certain image should
71696      * be removed when the viewer is moved to another image.
71697      *
71698      * To retrive and use the tag component
71699      *
71700      * @example
71701      * ```js
71702      * var viewer = new Viewer({ component: { tag: true } }, ...);
71703      *
71704      * var tagComponent = viewer.getComponent("tag");
71705      * ```
71706      */
71707     class TagComponent extends Component {
71708         /** @ignore */
71709         constructor(name, container, navigator) {
71710             super(name, container, navigator);
71711             this._tagDomRenderer = new TagDOMRenderer();
71712             this._tagScene = new TagScene();
71713             this._tagSet = new TagSet();
71714             this._tagCreator = new TagCreator(this, navigator);
71715             this._viewportCoords = new ViewportCoords();
71716             this._createHandlers = {
71717                 "CreatePoint": new CreatePointHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
71718                 "CreatePoints": new CreatePointsHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
71719                 "CreatePolygon": new CreatePolygonHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
71720                 "CreateRect": new CreateRectHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
71721                 "CreateRectDrag": new CreateRectDragHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
71722                 "Default": undefined,
71723             };
71724             this._editVertexHandler =
71725                 new EditVertexHandler(this, container, navigator, this._viewportCoords, this._tagSet);
71726             this._renderTags$ = this._tagSet.changed$.pipe(map((tagSet) => {
71727                 const tags = tagSet.getAll();
71728                 // ensure that tags are always rendered in the same order
71729                 // to avoid hover tracking problems on first resize.
71730                 tags.sort((t1, t2) => {
71731                     const id1 = t1.tag.id;
71732                     const id2 = t2.tag.id;
71733                     if (id1 < id2) {
71734                         return -1;
71735                     }
71736                     if (id1 > id2) {
71737                         return 1;
71738                     }
71739                     return 0;
71740                 });
71741                 return tags;
71742             }), share());
71743             this._tagChanged$ = this._renderTags$.pipe(switchMap((tags) => {
71744                 return from(tags).pipe(mergeMap((tag) => {
71745                     return merge(tag.tag.changed$, tag.tag.geometryChanged$);
71746                 }));
71747             }), share());
71748             this._renderTagGLChanged$ = this._renderTags$.pipe(switchMap((tags) => {
71749                 return from(tags).pipe(mergeMap((tag) => {
71750                     return tag.glObjectsChanged$;
71751                 }));
71752             }), share());
71753             this._createGeometryChanged$ = this._tagCreator.tag$.pipe(switchMap((tag) => {
71754                 return tag != null ?
71755                     tag.geometryChanged$ :
71756                     empty();
71757             }), share());
71758             this._createGLObjectsChanged$ = this._tagCreator.tag$.pipe(switchMap((tag) => {
71759                 return tag != null ?
71760                     tag.glObjectsChanged$ :
71761                     empty();
71762             }), share());
71763             this._creatingConfiguration$ = this._configuration$.pipe(distinctUntilChanged((c1, c2) => {
71764                 return c1.mode === c2.mode;
71765             }, (configuration) => {
71766                 return {
71767                     createColor: configuration.createColor,
71768                     mode: configuration.mode,
71769                 };
71770             }), publishReplay(1), refCount());
71771             this._creatingConfiguration$
71772                 .subscribe((configuration) => {
71773                 const type = "tagmode";
71774                 const event = {
71775                     mode: configuration.mode,
71776                     target: this,
71777                     type,
71778                 };
71779                 this.fire(type, event);
71780             });
71781         }
71782         /**
71783          * Add tags to the tag set or replace tags in the tag set.
71784          *
71785          * @description If a tag already in the set has the same
71786          * id as one of the tags added, the old tag will be removed
71787          * the added tag will take its place.
71788          *
71789          * @param {Array<Tag>} tags - Tags to add.
71790          *
71791          * @example
71792          * ```js
71793          * tagComponent.add([tag1, tag2]);
71794          * ```
71795          */
71796         add(tags) {
71797             if (this._activated) {
71798                 this._navigator.stateService.currentTransform$.pipe(first())
71799                     .subscribe((transform) => {
71800                     this._tagSet.add(tags, transform);
71801                     const renderTags = tags
71802                         .map((tag) => {
71803                         return this._tagSet.get(tag.id);
71804                     });
71805                     this._tagScene.add(renderTags);
71806                 });
71807             }
71808             else {
71809                 this._tagSet.addDeactivated(tags);
71810             }
71811         }
71812         /**
71813          * Calculate the smallest rectangle containing all the points
71814          * in the points geometry.
71815          *
71816          * @description The result may be different depending on if the
71817          * current image is an spherical or not. If the
71818          * current image is an spherical the rectangle may
71819          * wrap the horizontal border of the image.
71820          *
71821          * @returns {Promise<Array<number>>} Promise to the rectangle
71822          * on the format specified for the {@link RectGeometry} in basic
71823          * coordinates.
71824          */
71825         calculateRect(geometry) {
71826             return new Promise((resolve, reject) => {
71827                 this._navigator.stateService.currentTransform$.pipe(first(), map((transform) => {
71828                     return geometry.getRect2d(transform);
71829                 }))
71830                     .subscribe((rect) => {
71831                     resolve(rect);
71832                 }, (error) => {
71833                     reject(error);
71834                 });
71835             });
71836         }
71837         /**
71838          * Force the creation of a geometry programatically using its
71839          * current vertices.
71840          *
71841          * @description The method only has an effect when the tag
71842          * mode is either of the following modes:
71843          *
71844          * {@link TagMode.CreatePoints}
71845          * {@link TagMode.CreatePolygon}
71846          * {@link TagMode.CreateRect}
71847          * {@link TagMode.CreateRectDrag}
71848          *
71849          * In the case of points or polygon creation, only the created
71850          * vertices are used, i.e. the mouse position is disregarded.
71851          *
71852          * In the case of rectangle creation the position of the mouse
71853          * at the time of the method call is used as one of the vertices
71854          * defining the rectangle.
71855          *
71856          * @fires geometrycreate
71857          *
71858          * @example
71859          * ```js
71860          * tagComponent.on("geometrycreate", function(geometry) {
71861          *     console.log(geometry);
71862          * });
71863          *
71864          * tagComponent.create();
71865          * ```
71866          */
71867         create() {
71868             this._tagCreator.replayedTag$.pipe(first(), filter((tag) => {
71869                 return !!tag;
71870             }))
71871                 .subscribe((tag) => {
71872                 tag.create();
71873             });
71874         }
71875         /**
71876          * Change the current tag mode.
71877          *
71878          * @description Change the tag mode to one of the create modes for creating new geometries.
71879          *
71880          * @param {TagMode} mode - New tag mode.
71881          *
71882          * @fires tagmode
71883          *
71884          * @example
71885          * ```js
71886          * tagComponent.changeMode(TagMode.CreateRect);
71887          * ```
71888          */
71889         changeMode(mode) {
71890             this.configure({ mode: mode });
71891         }
71892         fire(type, event) {
71893             super.fire(type, event);
71894         }
71895         /**
71896          * Returns the tag in the tag set with the specified id, or
71897          * undefined if the id matches no tag.
71898          *
71899          * @param {string} tagId - Id of the tag.
71900          *
71901          * @example
71902          * ```js
71903          * var tag = tagComponent.get("tagId");
71904          * ```
71905          */
71906         get(tagId) {
71907             if (this._activated) {
71908                 const renderTag = this._tagSet.get(tagId);
71909                 return renderTag !== undefined ? renderTag.tag : undefined;
71910             }
71911             else {
71912                 return this._tagSet.getDeactivated(tagId);
71913             }
71914         }
71915         /**
71916          * Returns an array of all tags.
71917          *
71918          * @example
71919          * ```js
71920          * var tags = tagComponent.getAll();
71921          * ```
71922          */
71923         getAll() {
71924             if (this.activated) {
71925                 return this._tagSet
71926                     .getAll()
71927                     .map((renderTag) => {
71928                     return renderTag.tag;
71929                 });
71930             }
71931             else {
71932                 return this._tagSet.getAllDeactivated();
71933             }
71934         }
71935         /**
71936          * Returns an array of tag ids for tags that contain the specified point.
71937          *
71938          * @description The pixel point must lie inside the polygon or rectangle
71939          * of an added tag for the tag id to be returned. Tag ids for
71940          * tags that do not have a fill will also be returned if the point is inside
71941          * the geometry of the tag. Tags with point geometries can not be retrieved.
71942          *
71943          * No tag ids will be returned for polygons rendered in cropped spherical or
71944          * rectangles rendered in spherical.
71945          *
71946          * Notice that the pixelPoint argument requires x, y coordinates from pixel space.
71947          *
71948          * With this function, you can use the coordinates provided by mouse
71949          * events to get information out of the tag component.
71950          *
71951          * If no tag at exist the pixel point, an empty array will be returned.
71952          *
71953          * @param {Array<number>} pixelPoint - Pixel coordinates on the viewer element.
71954          * @returns {Promise<Array<string>>} Promise to the ids of the tags that
71955          * contain the specified pixel point.
71956          *
71957          * @example
71958          * ```js
71959          * tagComponent.getTagIdsAt([100, 100])
71960          *     .then((tagIds) => { console.log(tagIds); });
71961          * ```
71962          */
71963         getTagIdsAt(pixelPoint) {
71964             return new Promise((resolve, reject) => {
71965                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
71966                     const viewport = this._viewportCoords
71967                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
71968                     const ids = this._tagScene.intersectObjects(viewport, render.perspective);
71969                     return ids;
71970                 }))
71971                     .subscribe((ids) => {
71972                     resolve(ids);
71973                 }, (error) => {
71974                     reject(error);
71975                 });
71976             });
71977         }
71978         /**
71979          * Check if a tag exist in the tag set.
71980          *
71981          * @param {string} tagId - Id of the tag.
71982          *
71983          * @example
71984          * ```js
71985          * var tagExists = tagComponent.has("tagId");
71986          * ```
71987          */
71988         has(tagId) {
71989             return this._activated ? this._tagSet.has(tagId) : this._tagSet.hasDeactivated(tagId);
71990         }
71991         off(type, handler) {
71992             super.off(type, handler);
71993         }
71994         on(type, handler) {
71995             super.on(type, handler);
71996         }
71997         /**
71998          * Remove tags with the specified ids from the tag set.
71999          *
72000          * @param {Array<string>} tagIds - Ids for tags to remove.
72001          *
72002          * @example
72003          * ```js
72004          * tagComponent.remove(["id-1", "id-2"]);
72005          * ```
72006          */
72007         remove(tagIds) {
72008             if (this._activated) {
72009                 this._tagSet.remove(tagIds);
72010                 this._tagScene.remove(tagIds);
72011             }
72012             else {
72013                 this._tagSet.removeDeactivated(tagIds);
72014             }
72015         }
72016         /**
72017          * Remove all tags from the tag set.
72018          *
72019          * @example
72020          * ```js
72021          * tagComponent.removeAll();
72022          * ```
72023          */
72024         removeAll() {
72025             if (this._activated) {
72026                 this._tagSet.removeAll();
72027                 this._tagScene.removeAll();
72028             }
72029             else {
72030                 this._tagSet.removeAllDeactivated();
72031             }
72032         }
72033         _activate() {
72034             this._editVertexHandler.enable();
72035             const handlerGeometryCreated$ = from(Object.keys(this._createHandlers)).pipe(map((key) => {
72036                 return this._createHandlers[key];
72037             }), filter((handler) => {
72038                 return !!handler;
72039             }), mergeMap((handler) => {
72040                 return handler.geometryCreated$;
72041             }), share());
72042             const subs = this._subscriptions;
72043             subs.push(handlerGeometryCreated$
72044                 .subscribe((geometry) => {
72045                 const type = "geometrycreate";
72046                 const event = {
72047                     geometry,
72048                     target: this,
72049                     type,
72050                 };
72051                 this.fire(type, event);
72052             }));
72053             subs.push(this._tagCreator.tag$.pipe(skipWhile((tag) => {
72054                 return tag == null;
72055             }), distinctUntilChanged())
72056                 .subscribe((tag) => {
72057                 const type = tag != null ?
72058                     "tagcreatestart" :
72059                     "tagcreateend";
72060                 const event = {
72061                     target: this,
72062                     type,
72063                 };
72064                 this.fire(type, event);
72065             }));
72066             subs.push(handlerGeometryCreated$
72067                 .subscribe(() => {
72068                 this.changeMode(exports.TagMode.Default);
72069             }));
72070             subs.push(this._creatingConfiguration$
72071                 .subscribe((configuration) => {
72072                 this._disableCreateHandlers();
72073                 const mode = exports.TagMode[configuration.mode];
72074                 const handler = this._createHandlers[mode];
72075                 if (!!handler) {
72076                     handler.enable();
72077                 }
72078             }));
72079             subs.push(this._renderTags$
72080                 .subscribe(() => {
72081                 const type = "tags";
72082                 const event = {
72083                     target: this,
72084                     type,
72085                 };
72086                 this.fire(type, event);
72087             }));
72088             subs.push(this._tagCreator.tag$.pipe(switchMap((tag) => {
72089                 return tag != null ?
72090                     tag.aborted$.pipe(map(() => { return null; })) :
72091                     empty();
72092             }))
72093                 .subscribe(() => { this.changeMode(exports.TagMode.Default); }));
72094             subs.push(this._tagCreator.tag$
72095                 .subscribe((tag) => {
72096                 if (this._tagScene.hasCreateTag()) {
72097                     this._tagScene.removeCreateTag();
72098                 }
72099                 if (tag != null) {
72100                     this._tagScene.addCreateTag(tag);
72101                 }
72102             }));
72103             subs.push(this._createGLObjectsChanged$
72104                 .subscribe((tag) => {
72105                 this._tagScene.updateCreateTagObjects(tag);
72106             }));
72107             subs.push(this._renderTagGLChanged$
72108                 .subscribe((tag) => {
72109                 this._tagScene.updateObjects(tag);
72110             }));
72111             subs.push(this._tagChanged$
72112                 .subscribe(() => {
72113                 this._tagScene.update();
72114             }));
72115             subs.push(combineLatest(this._renderTags$.pipe(startWith([]), tap(() => {
72116                 this._container.domRenderer.render$.next({
72117                     name: this._name,
72118                     vNode: this._tagDomRenderer.clear(),
72119                 });
72120             })), this._container.renderService.renderCamera$, this._container.spriteService.spriteAtlas$, this._container.renderService.size$, this._tagChanged$.pipe(startWith(null)), merge(this._tagCreator.tag$, this._createGeometryChanged$).pipe(startWith(null))).pipe(map(([renderTags, rc, atlas, size, , ct]) => {
72121                 return {
72122                     name: this._name,
72123                     vNode: this._tagDomRenderer.render(renderTags, ct, atlas, rc.perspective, size),
72124                 };
72125             }))
72126                 .subscribe(this._container.domRenderer.render$));
72127             subs.push(this._navigator.stateService.currentState$.pipe(map((frame) => {
72128                 const tagScene = this._tagScene;
72129                 return {
72130                     name: this._name,
72131                     renderer: {
72132                         frameId: frame.id,
72133                         needsRender: tagScene.needsRender,
72134                         render: tagScene.render.bind(tagScene),
72135                         pass: RenderPass.Opaque,
72136                     },
72137                 };
72138             }))
72139                 .subscribe(this._container.glRenderer.render$));
72140             this._navigator.stateService.currentTransform$.pipe(first())
72141                 .subscribe((transform) => {
72142                 this._tagSet.activate(transform);
72143                 this._tagScene.add(this._tagSet.getAll());
72144             });
72145         }
72146         _deactivate() {
72147             this._editVertexHandler.disable();
72148             this._disableCreateHandlers();
72149             this._tagScene.clear();
72150             this._tagSet.deactivate();
72151             this._tagCreator.delete$.next(null);
72152             this._subscriptions.unsubscribe();
72153             this._container.container.classList.remove("component-tag-create");
72154         }
72155         _getDefaultConfiguration() {
72156             return {
72157                 createColor: 0xFFFFFF,
72158                 indicatePointsCompleter: true,
72159                 mode: exports.TagMode.Default,
72160             };
72161         }
72162         _disableCreateHandlers() {
72163             const createHandlers = this._createHandlers;
72164             for (const key in createHandlers) {
72165                 if (!createHandlers.hasOwnProperty(key)) {
72166                     continue;
72167                 }
72168                 const handler = createHandlers[key];
72169                 if (!!handler) {
72170                     handler.disable();
72171                 }
72172             }
72173         }
72174     }
72175     /** @inheritdoc */
72176     TagComponent.componentName = "tag";
72177
72178     /**
72179      * @class ZoomComponent
72180      *
72181      * @classdesc Component rendering UI elements used for zooming.
72182      *
72183      * @example
72184      * ```js
72185      * var viewer = new Viewer({ ... });
72186      *
72187      * var zoomComponent = viewer.getComponent("zoom");
72188      * zoomComponent.configure({ size: ComponentSize.Small });
72189      * ```
72190      */
72191     class ZoomComponent extends Component {
72192         constructor(name, container, navigator) {
72193             super(name, container, navigator);
72194             this._viewportCoords = new ViewportCoords();
72195             this._zoomDelta$ = new Subject();
72196         }
72197         _activate() {
72198             const subs = this._subscriptions;
72199             subs.push(combineLatest(this._navigator.stateService.currentState$, this._navigator.stateService.state$, this._configuration$, this._container.renderService.size$).pipe(map(([frame, state, configuration, size]) => {
72200                 const zoom = frame.state.zoom;
72201                 const zoomInIcon = virtualDom.h("div.mapillary-zoom-in-icon", []);
72202                 const zoomInButton = zoom >= 3 || state === State.Waiting ?
72203                     virtualDom.h("div.mapillary-zoom-in-button-inactive", [zoomInIcon]) :
72204                     virtualDom.h("div.mapillary-zoom-in-button", { onclick: () => { this._zoomDelta$.next(1); } }, [zoomInIcon]);
72205                 const zoomOutIcon = virtualDom.h("div.mapillary-zoom-out-icon", []);
72206                 const zoomOutButton = zoom <= 0 || state === State.Waiting ?
72207                     virtualDom.h("div.mapillary-zoom-out-button-inactive", [zoomOutIcon]) :
72208                     virtualDom.h("div.mapillary-zoom-out-button", { onclick: () => { this._zoomDelta$.next(-1); } }, [zoomOutIcon]);
72209                 const compact = configuration.size === exports.ComponentSize.Small ||
72210                     configuration.size === exports.ComponentSize.Automatic && size.width < 640 ?
72211                     ".mapillary-zoom-compact" : "";
72212                 return {
72213                     name: this._name,
72214                     vNode: virtualDom.h("div.mapillary-zoom-container" + compact, { oncontextmenu: (event) => { event.preventDefault(); } }, [zoomInButton, zoomOutButton]),
72215                 };
72216             }))
72217                 .subscribe(this._container.domRenderer.render$));
72218             subs.push(this._zoomDelta$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
72219                 .subscribe(([zoomDelta, render, transform]) => {
72220                 const unprojected = this._viewportCoords.unprojectFromViewport(0, 0, render.perspective);
72221                 const reference = transform.projectBasic(unprojected.toArray());
72222                 this._navigator.stateService.zoomIn(zoomDelta, reference);
72223             }));
72224         }
72225         _deactivate() {
72226             this._subscriptions.unsubscribe();
72227         }
72228         _getDefaultConfiguration() {
72229             return { size: exports.ComponentSize.Automatic };
72230         }
72231     }
72232     ZoomComponent.componentName = "zoom";
72233
72234     class ImageFallbackComponent extends Component {
72235         constructor(name, container, navigator, dom) {
72236             super(name, container, navigator);
72237             this._canvasId = `${container.id}-${this._name}`;
72238             this._dom = !!dom ? dom : new DOM();
72239         }
72240         _activate() {
72241             const canvasSize$ = this._container.domRenderer.element$.pipe(map(() => {
72242                 return this._dom.document.getElementById(this._canvasId);
72243             }), filter((canvas) => {
72244                 return !!canvas;
72245             }), map((canvas) => {
72246                 const adaptableDomRenderer = canvas.parentElement;
72247                 const width = adaptableDomRenderer.offsetWidth;
72248                 const height = adaptableDomRenderer.offsetHeight;
72249                 return [canvas, { height: height, width: width }];
72250             }), distinctUntilChanged((s1, s2) => {
72251                 return s1.height === s2.height && s1.width === s2.width;
72252             }, ([, size]) => {
72253                 return size;
72254             }));
72255             this._subscriptions.push(combineLatest(canvasSize$, this._navigator.stateService.currentImage$)
72256                 .subscribe(([[canvas, size], image]) => {
72257                 canvas.width = size.width;
72258                 canvas.height = size.height;
72259                 canvas
72260                     .getContext("2d")
72261                     .drawImage(image.image, 0, 0, size.width, size.height);
72262             }));
72263             this._container.domRenderer.renderAdaptive$.next({ name: this._name, vNode: virtualDom.h(`canvas#${this._canvasId}`, []) });
72264         }
72265         _deactivate() {
72266             this._subscriptions.unsubscribe();
72267         }
72268         _getDefaultConfiguration() {
72269             return {};
72270         }
72271     }
72272     ImageFallbackComponent.componentName = "imagefallback";
72273
72274     /**
72275      * @class NavigationFallbackComponent
72276      *
72277      * @classdesc Fallback navigation component for environments without WebGL support.
72278      *
72279      * Replaces the functionality in the Direction and Sequence components.
72280      */
72281     class NavigationFallbackComponent extends Component {
72282         /** @ignore */
72283         constructor(name, container, navigator) {
72284             super(name, container, navigator);
72285             this._seqNames = {};
72286             this._seqNames[exports.NavigationDirection[exports.NavigationDirection.Prev]] = "-prev";
72287             this._seqNames[exports.NavigationDirection[exports.NavigationDirection.Next]] = "-next";
72288             this._spaTopNames = {};
72289             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.TurnLeft]] = "-turn-left";
72290             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepLeft]] = "-left";
72291             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepForward]] = "-forward";
72292             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepRight]] = "-right";
72293             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.TurnRight]] = "-turn-right";
72294             this._spaBottomNames = {};
72295             this._spaBottomNames[exports.NavigationDirection[exports.NavigationDirection.TurnU]] = "-turn-around";
72296             this._spaBottomNames[exports.NavigationDirection[exports.NavigationDirection.StepBackward]] = "-backward";
72297         }
72298         _activate() {
72299             this._subscriptions.push(combineLatest(this._navigator.stateService.currentImage$, this._configuration$).pipe(switchMap(([image, configuration]) => {
72300                 const sequenceEdges$ = configuration.sequence ?
72301                     image.sequenceEdges$.pipe(map((status) => {
72302                         return status.edges
72303                             .map((edge) => {
72304                             return edge.data.direction;
72305                         });
72306                     })) :
72307                     of([]);
72308                 const spatialEdges$ = !isSpherical(image.cameraType) &&
72309                     configuration.spatial ?
72310                     image.spatialEdges$.pipe(map((status) => {
72311                         return status.edges
72312                             .map((edge) => {
72313                             return edge.data.direction;
72314                         });
72315                     })) :
72316                     of([]);
72317                 return combineLatest(sequenceEdges$, spatialEdges$).pipe(map(([seq, spa]) => {
72318                     return seq.concat(spa);
72319                 }));
72320             }), map((edgeDirections) => {
72321                 const seqs = this._createArrowRow(this._seqNames, edgeDirections);
72322                 const spaTops = this._createArrowRow(this._spaTopNames, edgeDirections);
72323                 const spaBottoms = this._createArrowRow(this._spaBottomNames, edgeDirections);
72324                 const seqContainer = virtualDom.h(`div.mapillary-navigation-sequence`, seqs);
72325                 const spaTopContainer = virtualDom.h(`div.NavigationSpatialTop`, spaTops);
72326                 const spaBottomContainer = virtualDom.h(`div.mapillary-navigation-spatial-bottom`, spaBottoms);
72327                 const spaContainer = virtualDom.h(`div.mapillary-navigation-spatial`, [spaTopContainer, spaBottomContainer]);
72328                 return { name: this._name, vNode: virtualDom.h(`div.NavigationContainer`, [seqContainer, spaContainer]) };
72329             }))
72330                 .subscribe(this._container.domRenderer.render$));
72331         }
72332         _deactivate() {
72333             this._subscriptions.unsubscribe();
72334         }
72335         _getDefaultConfiguration() {
72336             return { sequence: true, spatial: true };
72337         }
72338         _createArrowRow(arrowNames, edgeDirections) {
72339             const arrows = [];
72340             for (const arrowName in arrowNames) {
72341                 if (!(arrowNames.hasOwnProperty(arrowName))) {
72342                     continue;
72343                 }
72344                 const direction = exports.NavigationDirection[arrowName];
72345                 if (edgeDirections.indexOf(direction) !== -1) {
72346                     arrows.push(this._createVNode(direction, arrowNames[arrowName], "visible"));
72347                 }
72348                 else {
72349                     arrows.push(this._createVNode(direction, arrowNames[arrowName], "hidden"));
72350                 }
72351             }
72352             return arrows;
72353         }
72354         _createVNode(direction, name, visibility) {
72355             return virtualDom.h(`span.mapillary-navigation-button.mapillary-navigation${name}`, {
72356                 onclick: () => {
72357                     this._navigator.moveDir$(direction)
72358                         .subscribe(undefined, (error) => {
72359                         if (!(error instanceof CancelMapillaryError)) {
72360                             console.error(error);
72361                         }
72362                     });
72363                 },
72364                 style: {
72365                     visibility: visibility,
72366                 },
72367             }, []);
72368         }
72369     }
72370     NavigationFallbackComponent.componentName = "navigationfallback";
72371
72372     /*! pako 2.0.3 https://github.com/nodeca/pako @license (MIT AND Zlib) */
72373     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
72374     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
72375     //
72376     // This software is provided 'as-is', without any express or implied
72377     // warranty. In no event will the authors be held liable for any damages
72378     // arising from the use of this software.
72379     //
72380     // Permission is granted to anyone to use this software for any purpose,
72381     // including commercial applications, and to alter it and redistribute it
72382     // freely, subject to the following restrictions:
72383     //
72384     // 1. The origin of this software must not be misrepresented; you must not
72385     //   claim that you wrote the original software. If you use this software
72386     //   in a product, an acknowledgment in the product documentation would be
72387     //   appreciated but is not required.
72388     // 2. Altered source versions must be plainly marked as such, and must not be
72389     //   misrepresented as being the original software.
72390     // 3. This notice may not be removed or altered from any source distribution.
72391
72392     /* eslint-disable space-unary-ops */
72393
72394     /* Public constants ==========================================================*/
72395     /* ===========================================================================*/
72396
72397
72398     //const Z_FILTERED          = 1;
72399     //const Z_HUFFMAN_ONLY      = 2;
72400     //const Z_RLE               = 3;
72401     const Z_FIXED               = 4;
72402     //const Z_DEFAULT_STRATEGY  = 0;
72403
72404     /* Possible values of the data_type field (though see inflate()) */
72405     const Z_BINARY              = 0;
72406     const Z_TEXT                = 1;
72407     //const Z_ASCII             = 1; // = Z_TEXT
72408     const Z_UNKNOWN             = 2;
72409
72410     /*============================================================================*/
72411
72412
72413     function zero(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }
72414
72415     // From zutil.h
72416
72417     const STORED_BLOCK = 0;
72418     const STATIC_TREES = 1;
72419     const DYN_TREES    = 2;
72420     /* The three kinds of block type */
72421
72422     const MIN_MATCH    = 3;
72423     const MAX_MATCH    = 258;
72424     /* The minimum and maximum match lengths */
72425
72426     // From deflate.h
72427     /* ===========================================================================
72428      * Internal compression state.
72429      */
72430
72431     const LENGTH_CODES  = 29;
72432     /* number of length codes, not counting the special END_BLOCK code */
72433
72434     const LITERALS      = 256;
72435     /* number of literal bytes 0..255 */
72436
72437     const L_CODES       = LITERALS + 1 + LENGTH_CODES;
72438     /* number of Literal or Length codes, including the END_BLOCK code */
72439
72440     const D_CODES       = 30;
72441     /* number of distance codes */
72442
72443     const BL_CODES      = 19;
72444     /* number of codes used to transfer the bit lengths */
72445
72446     const HEAP_SIZE     = 2 * L_CODES + 1;
72447     /* maximum heap size */
72448
72449     const MAX_BITS      = 15;
72450     /* All codes must not exceed MAX_BITS bits */
72451
72452     const Buf_size      = 16;
72453     /* size of bit buffer in bi_buf */
72454
72455
72456     /* ===========================================================================
72457      * Constants
72458      */
72459
72460     const MAX_BL_BITS = 7;
72461     /* Bit length codes must not exceed MAX_BL_BITS bits */
72462
72463     const END_BLOCK   = 256;
72464     /* end of block literal code */
72465
72466     const REP_3_6     = 16;
72467     /* repeat previous bit length 3-6 times (2 bits of repeat count) */
72468
72469     const REPZ_3_10   = 17;
72470     /* repeat a zero length 3-10 times  (3 bits of repeat count) */
72471
72472     const REPZ_11_138 = 18;
72473     /* repeat a zero length 11-138 times  (7 bits of repeat count) */
72474
72475     /* eslint-disable comma-spacing,array-bracket-spacing */
72476     const extra_lbits =   /* extra bits for each length code */
72477       new Uint8Array([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]);
72478
72479     const extra_dbits =   /* extra bits for each distance code */
72480       new Uint8Array([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]);
72481
72482     const extra_blbits =  /* extra bits for each bit length code */
72483       new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]);
72484
72485     const bl_order =
72486       new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);
72487     /* eslint-enable comma-spacing,array-bracket-spacing */
72488
72489     /* The lengths of the bit length codes are sent in order of decreasing
72490      * probability, to avoid transmitting the lengths for unused bit length codes.
72491      */
72492
72493     /* ===========================================================================
72494      * Local data. These are initialized only once.
72495      */
72496
72497     // We pre-fill arrays with 0 to avoid uninitialized gaps
72498
72499     const DIST_CODE_LEN = 512; /* see definition of array dist_code below */
72500
72501     // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
72502     const static_ltree  = new Array((L_CODES + 2) * 2);
72503     zero(static_ltree);
72504     /* The static literal tree. Since the bit lengths are imposed, there is no
72505      * need for the L_CODES extra codes used during heap construction. However
72506      * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
72507      * below).
72508      */
72509
72510     const static_dtree  = new Array(D_CODES * 2);
72511     zero(static_dtree);
72512     /* The static distance tree. (Actually a trivial tree since all codes use
72513      * 5 bits.)
72514      */
72515
72516     const _dist_code    = new Array(DIST_CODE_LEN);
72517     zero(_dist_code);
72518     /* Distance codes. The first 256 values correspond to the distances
72519      * 3 .. 258, the last 256 values correspond to the top 8 bits of
72520      * the 15 bit distances.
72521      */
72522
72523     const _length_code  = new Array(MAX_MATCH - MIN_MATCH + 1);
72524     zero(_length_code);
72525     /* length code for each normalized match length (0 == MIN_MATCH) */
72526
72527     const base_length   = new Array(LENGTH_CODES);
72528     zero(base_length);
72529     /* First normalized length for each code (0 = MIN_MATCH) */
72530
72531     const base_dist     = new Array(D_CODES);
72532     zero(base_dist);
72533     /* First normalized distance for each code (0 = distance of 1) */
72534
72535
72536     function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
72537
72538       this.static_tree  = static_tree;  /* static tree or NULL */
72539       this.extra_bits   = extra_bits;   /* extra bits for each code or NULL */
72540       this.extra_base   = extra_base;   /* base index for extra_bits */
72541       this.elems        = elems;        /* max number of elements in the tree */
72542       this.max_length   = max_length;   /* max bit length for the codes */
72543
72544       // show if `static_tree` has data or dummy - needed for monomorphic objects
72545       this.has_stree    = static_tree && static_tree.length;
72546     }
72547
72548
72549     let static_l_desc;
72550     let static_d_desc;
72551     let static_bl_desc;
72552
72553
72554     function TreeDesc(dyn_tree, stat_desc) {
72555       this.dyn_tree = dyn_tree;     /* the dynamic tree */
72556       this.max_code = 0;            /* largest code with non zero frequency */
72557       this.stat_desc = stat_desc;   /* the corresponding static tree */
72558     }
72559
72560
72561
72562     const d_code = (dist) => {
72563
72564       return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
72565     };
72566
72567
72568     /* ===========================================================================
72569      * Output a short LSB first on the stream.
72570      * IN assertion: there is enough room in pendingBuf.
72571      */
72572     const put_short = (s, w) => {
72573     //    put_byte(s, (uch)((w) & 0xff));
72574     //    put_byte(s, (uch)((ush)(w) >> 8));
72575       s.pending_buf[s.pending++] = (w) & 0xff;
72576       s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
72577     };
72578
72579
72580     /* ===========================================================================
72581      * Send a value on a given number of bits.
72582      * IN assertion: length <= 16 and value fits in length bits.
72583      */
72584     const send_bits = (s, value, length) => {
72585
72586       if (s.bi_valid > (Buf_size - length)) {
72587         s.bi_buf |= (value << s.bi_valid) & 0xffff;
72588         put_short(s, s.bi_buf);
72589         s.bi_buf = value >> (Buf_size - s.bi_valid);
72590         s.bi_valid += length - Buf_size;
72591       } else {
72592         s.bi_buf |= (value << s.bi_valid) & 0xffff;
72593         s.bi_valid += length;
72594       }
72595     };
72596
72597
72598     const send_code = (s, c, tree) => {
72599
72600       send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
72601     };
72602
72603
72604     /* ===========================================================================
72605      * Reverse the first len bits of a code, using straightforward code (a faster
72606      * method would use a table)
72607      * IN assertion: 1 <= len <= 15
72608      */
72609     const bi_reverse = (code, len) => {
72610
72611       let res = 0;
72612       do {
72613         res |= code & 1;
72614         code >>>= 1;
72615         res <<= 1;
72616       } while (--len > 0);
72617       return res >>> 1;
72618     };
72619
72620
72621     /* ===========================================================================
72622      * Flush the bit buffer, keeping at most 7 bits in it.
72623      */
72624     const bi_flush = (s) => {
72625
72626       if (s.bi_valid === 16) {
72627         put_short(s, s.bi_buf);
72628         s.bi_buf = 0;
72629         s.bi_valid = 0;
72630
72631       } else if (s.bi_valid >= 8) {
72632         s.pending_buf[s.pending++] = s.bi_buf & 0xff;
72633         s.bi_buf >>= 8;
72634         s.bi_valid -= 8;
72635       }
72636     };
72637
72638
72639     /* ===========================================================================
72640      * Compute the optimal bit lengths for a tree and update the total bit length
72641      * for the current block.
72642      * IN assertion: the fields freq and dad are set, heap[heap_max] and
72643      *    above are the tree nodes sorted by increasing frequency.
72644      * OUT assertions: the field len is set to the optimal bit length, the
72645      *     array bl_count contains the frequencies for each bit length.
72646      *     The length opt_len is updated; static_len is also updated if stree is
72647      *     not null.
72648      */
72649     const gen_bitlen = (s, desc) =>
72650     //    deflate_state *s;
72651     //    tree_desc *desc;    /* the tree descriptor */
72652     {
72653       const tree            = desc.dyn_tree;
72654       const max_code        = desc.max_code;
72655       const stree           = desc.stat_desc.static_tree;
72656       const has_stree       = desc.stat_desc.has_stree;
72657       const extra           = desc.stat_desc.extra_bits;
72658       const base            = desc.stat_desc.extra_base;
72659       const max_length      = desc.stat_desc.max_length;
72660       let h;              /* heap index */
72661       let n, m;           /* iterate over the tree elements */
72662       let bits;           /* bit length */
72663       let xbits;          /* extra bits */
72664       let f;              /* frequency */
72665       let overflow = 0;   /* number of elements with bit length too large */
72666
72667       for (bits = 0; bits <= MAX_BITS; bits++) {
72668         s.bl_count[bits] = 0;
72669       }
72670
72671       /* In a first pass, compute the optimal bit lengths (which may
72672        * overflow in the case of the bit length tree).
72673        */
72674       tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */
72675
72676       for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
72677         n = s.heap[h];
72678         bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
72679         if (bits > max_length) {
72680           bits = max_length;
72681           overflow++;
72682         }
72683         tree[n * 2 + 1]/*.Len*/ = bits;
72684         /* We overwrite tree[n].Dad which is no longer needed */
72685
72686         if (n > max_code) { continue; } /* not a leaf node */
72687
72688         s.bl_count[bits]++;
72689         xbits = 0;
72690         if (n >= base) {
72691           xbits = extra[n - base];
72692         }
72693         f = tree[n * 2]/*.Freq*/;
72694         s.opt_len += f * (bits + xbits);
72695         if (has_stree) {
72696           s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
72697         }
72698       }
72699       if (overflow === 0) { return; }
72700
72701       // Trace((stderr,"\nbit length overflow\n"));
72702       /* This happens for example on obj2 and pic of the Calgary corpus */
72703
72704       /* Find the first bit length which could increase: */
72705       do {
72706         bits = max_length - 1;
72707         while (s.bl_count[bits] === 0) { bits--; }
72708         s.bl_count[bits]--;      /* move one leaf down the tree */
72709         s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
72710         s.bl_count[max_length]--;
72711         /* The brother of the overflow item also moves one step up,
72712          * but this does not affect bl_count[max_length]
72713          */
72714         overflow -= 2;
72715       } while (overflow > 0);
72716
72717       /* Now recompute all bit lengths, scanning in increasing frequency.
72718        * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
72719        * lengths instead of fixing only the wrong ones. This idea is taken
72720        * from 'ar' written by Haruhiko Okumura.)
72721        */
72722       for (bits = max_length; bits !== 0; bits--) {
72723         n = s.bl_count[bits];
72724         while (n !== 0) {
72725           m = s.heap[--h];
72726           if (m > max_code) { continue; }
72727           if (tree[m * 2 + 1]/*.Len*/ !== bits) {
72728             // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
72729             s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
72730             tree[m * 2 + 1]/*.Len*/ = bits;
72731           }
72732           n--;
72733         }
72734       }
72735     };
72736
72737
72738     /* ===========================================================================
72739      * Generate the codes for a given tree and bit counts (which need not be
72740      * optimal).
72741      * IN assertion: the array bl_count contains the bit length statistics for
72742      * the given tree and the field len is set for all tree elements.
72743      * OUT assertion: the field code is set for all tree elements of non
72744      *     zero code length.
72745      */
72746     const gen_codes = (tree, max_code, bl_count) =>
72747     //    ct_data *tree;             /* the tree to decorate */
72748     //    int max_code;              /* largest code with non zero frequency */
72749     //    ushf *bl_count;            /* number of codes at each bit length */
72750     {
72751       const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */
72752       let code = 0;              /* running code value */
72753       let bits;                  /* bit index */
72754       let n;                     /* code index */
72755
72756       /* The distribution counts are first used to generate the code values
72757        * without bit reversal.
72758        */
72759       for (bits = 1; bits <= MAX_BITS; bits++) {
72760         next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
72761       }
72762       /* Check that the bit counts in bl_count are consistent. The last code
72763        * must be all ones.
72764        */
72765       //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
72766       //        "inconsistent bit counts");
72767       //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
72768
72769       for (n = 0;  n <= max_code; n++) {
72770         let len = tree[n * 2 + 1]/*.Len*/;
72771         if (len === 0) { continue; }
72772         /* Now reverse the bits */
72773         tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);
72774
72775         //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
72776         //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
72777       }
72778     };
72779
72780
72781     /* ===========================================================================
72782      * Initialize the various 'constant' tables.
72783      */
72784     const tr_static_init = () => {
72785
72786       let n;        /* iterates over tree elements */
72787       let bits;     /* bit counter */
72788       let length;   /* length value */
72789       let code;     /* code value */
72790       let dist;     /* distance index */
72791       const bl_count = new Array(MAX_BITS + 1);
72792       /* number of codes at each bit length for an optimal tree */
72793
72794       // do check in _tr_init()
72795       //if (static_init_done) return;
72796
72797       /* For some embedded targets, global variables are not initialized: */
72798     /*#ifdef NO_INIT_GLOBAL_POINTERS
72799       static_l_desc.static_tree = static_ltree;
72800       static_l_desc.extra_bits = extra_lbits;
72801       static_d_desc.static_tree = static_dtree;
72802       static_d_desc.extra_bits = extra_dbits;
72803       static_bl_desc.extra_bits = extra_blbits;
72804     #endif*/
72805
72806       /* Initialize the mapping length (0..255) -> length code (0..28) */
72807       length = 0;
72808       for (code = 0; code < LENGTH_CODES - 1; code++) {
72809         base_length[code] = length;
72810         for (n = 0; n < (1 << extra_lbits[code]); n++) {
72811           _length_code[length++] = code;
72812         }
72813       }
72814       //Assert (length == 256, "tr_static_init: length != 256");
72815       /* Note that the length 255 (match length 258) can be represented
72816        * in two different ways: code 284 + 5 bits or code 285, so we
72817        * overwrite length_code[255] to use the best encoding:
72818        */
72819       _length_code[length - 1] = code;
72820
72821       /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
72822       dist = 0;
72823       for (code = 0; code < 16; code++) {
72824         base_dist[code] = dist;
72825         for (n = 0; n < (1 << extra_dbits[code]); n++) {
72826           _dist_code[dist++] = code;
72827         }
72828       }
72829       //Assert (dist == 256, "tr_static_init: dist != 256");
72830       dist >>= 7; /* from now on, all distances are divided by 128 */
72831       for (; code < D_CODES; code++) {
72832         base_dist[code] = dist << 7;
72833         for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
72834           _dist_code[256 + dist++] = code;
72835         }
72836       }
72837       //Assert (dist == 256, "tr_static_init: 256+dist != 512");
72838
72839       /* Construct the codes of the static literal tree */
72840       for (bits = 0; bits <= MAX_BITS; bits++) {
72841         bl_count[bits] = 0;
72842       }
72843
72844       n = 0;
72845       while (n <= 143) {
72846         static_ltree[n * 2 + 1]/*.Len*/ = 8;
72847         n++;
72848         bl_count[8]++;
72849       }
72850       while (n <= 255) {
72851         static_ltree[n * 2 + 1]/*.Len*/ = 9;
72852         n++;
72853         bl_count[9]++;
72854       }
72855       while (n <= 279) {
72856         static_ltree[n * 2 + 1]/*.Len*/ = 7;
72857         n++;
72858         bl_count[7]++;
72859       }
72860       while (n <= 287) {
72861         static_ltree[n * 2 + 1]/*.Len*/ = 8;
72862         n++;
72863         bl_count[8]++;
72864       }
72865       /* Codes 286 and 287 do not exist, but we must include them in the
72866        * tree construction to get a canonical Huffman tree (longest code
72867        * all ones)
72868        */
72869       gen_codes(static_ltree, L_CODES + 1, bl_count);
72870
72871       /* The static distance tree is trivial: */
72872       for (n = 0; n < D_CODES; n++) {
72873         static_dtree[n * 2 + 1]/*.Len*/ = 5;
72874         static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
72875       }
72876
72877       // Now data ready and we can init static trees
72878       static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
72879       static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS);
72880       static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0,         BL_CODES, MAX_BL_BITS);
72881
72882       //static_init_done = true;
72883     };
72884
72885
72886     /* ===========================================================================
72887      * Initialize a new block.
72888      */
72889     const init_block = (s) => {
72890
72891       let n; /* iterates over tree elements */
72892
72893       /* Initialize the trees. */
72894       for (n = 0; n < L_CODES;  n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
72895       for (n = 0; n < D_CODES;  n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
72896       for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }
72897
72898       s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
72899       s.opt_len = s.static_len = 0;
72900       s.last_lit = s.matches = 0;
72901     };
72902
72903
72904     /* ===========================================================================
72905      * Flush the bit buffer and align the output on a byte boundary
72906      */
72907     const bi_windup = (s) =>
72908     {
72909       if (s.bi_valid > 8) {
72910         put_short(s, s.bi_buf);
72911       } else if (s.bi_valid > 0) {
72912         //put_byte(s, (Byte)s->bi_buf);
72913         s.pending_buf[s.pending++] = s.bi_buf;
72914       }
72915       s.bi_buf = 0;
72916       s.bi_valid = 0;
72917     };
72918
72919     /* ===========================================================================
72920      * Copy a stored block, storing first the length and its
72921      * one's complement if requested.
72922      */
72923     const copy_block = (s, buf, len, header) =>
72924     //DeflateState *s;
72925     //charf    *buf;    /* the input data */
72926     //unsigned len;     /* its length */
72927     //int      header;  /* true if block header must be written */
72928     {
72929       bi_windup(s);        /* align on byte boundary */
72930
72931       if (header) {
72932         put_short(s, len);
72933         put_short(s, ~len);
72934       }
72935     //  while (len--) {
72936     //    put_byte(s, *buf++);
72937     //  }
72938       s.pending_buf.set(s.window.subarray(buf, buf + len), s.pending);
72939       s.pending += len;
72940     };
72941
72942     /* ===========================================================================
72943      * Compares to subtrees, using the tree depth as tie breaker when
72944      * the subtrees have equal frequency. This minimizes the worst case length.
72945      */
72946     const smaller = (tree, n, m, depth) => {
72947
72948       const _n2 = n * 2;
72949       const _m2 = m * 2;
72950       return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
72951              (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
72952     };
72953
72954     /* ===========================================================================
72955      * Restore the heap property by moving down the tree starting at node k,
72956      * exchanging a node with the smallest of its two sons if necessary, stopping
72957      * when the heap property is re-established (each father smaller than its
72958      * two sons).
72959      */
72960     const pqdownheap = (s, tree, k) =>
72961     //    deflate_state *s;
72962     //    ct_data *tree;  /* the tree to restore */
72963     //    int k;               /* node to move down */
72964     {
72965       const v = s.heap[k];
72966       let j = k << 1;  /* left son of k */
72967       while (j <= s.heap_len) {
72968         /* Set j to the smallest of the two sons: */
72969         if (j < s.heap_len &&
72970           smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
72971           j++;
72972         }
72973         /* Exit if v is smaller than both sons */
72974         if (smaller(tree, v, s.heap[j], s.depth)) { break; }
72975
72976         /* Exchange v with the smallest son */
72977         s.heap[k] = s.heap[j];
72978         k = j;
72979
72980         /* And continue down the tree, setting j to the left son of k */
72981         j <<= 1;
72982       }
72983       s.heap[k] = v;
72984     };
72985
72986
72987     // inlined manually
72988     // const SMALLEST = 1;
72989
72990     /* ===========================================================================
72991      * Send the block data compressed using the given Huffman trees
72992      */
72993     const compress_block = (s, ltree, dtree) =>
72994     //    deflate_state *s;
72995     //    const ct_data *ltree; /* literal tree */
72996     //    const ct_data *dtree; /* distance tree */
72997     {
72998       let dist;           /* distance of matched string */
72999       let lc;             /* match length or unmatched char (if dist == 0) */
73000       let lx = 0;         /* running index in l_buf */
73001       let code;           /* the code to send */
73002       let extra;          /* number of extra bits to send */
73003
73004       if (s.last_lit !== 0) {
73005         do {
73006           dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);
73007           lc = s.pending_buf[s.l_buf + lx];
73008           lx++;
73009
73010           if (dist === 0) {
73011             send_code(s, lc, ltree); /* send a literal byte */
73012             //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
73013           } else {
73014             /* Here, lc is the match length - MIN_MATCH */
73015             code = _length_code[lc];
73016             send_code(s, code + LITERALS + 1, ltree); /* send the length code */
73017             extra = extra_lbits[code];
73018             if (extra !== 0) {
73019               lc -= base_length[code];
73020               send_bits(s, lc, extra);       /* send the extra length bits */
73021             }
73022             dist--; /* dist is now the match distance - 1 */
73023             code = d_code(dist);
73024             //Assert (code < D_CODES, "bad d_code");
73025
73026             send_code(s, code, dtree);       /* send the distance code */
73027             extra = extra_dbits[code];
73028             if (extra !== 0) {
73029               dist -= base_dist[code];
73030               send_bits(s, dist, extra);   /* send the extra distance bits */
73031             }
73032           } /* literal or match pair ? */
73033
73034           /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
73035           //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
73036           //       "pendingBuf overflow");
73037
73038         } while (lx < s.last_lit);
73039       }
73040
73041       send_code(s, END_BLOCK, ltree);
73042     };
73043
73044
73045     /* ===========================================================================
73046      * Construct one Huffman tree and assigns the code bit strings and lengths.
73047      * Update the total bit length for the current block.
73048      * IN assertion: the field freq is set for all tree elements.
73049      * OUT assertions: the fields len and code are set to the optimal bit length
73050      *     and corresponding code. The length opt_len is updated; static_len is
73051      *     also updated if stree is not null. The field max_code is set.
73052      */
73053     const build_tree = (s, desc) =>
73054     //    deflate_state *s;
73055     //    tree_desc *desc; /* the tree descriptor */
73056     {
73057       const tree     = desc.dyn_tree;
73058       const stree    = desc.stat_desc.static_tree;
73059       const has_stree = desc.stat_desc.has_stree;
73060       const elems    = desc.stat_desc.elems;
73061       let n, m;          /* iterate over heap elements */
73062       let max_code = -1; /* largest code with non zero frequency */
73063       let node;          /* new node being created */
73064
73065       /* Construct the initial heap, with least frequent element in
73066        * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
73067        * heap[0] is not used.
73068        */
73069       s.heap_len = 0;
73070       s.heap_max = HEAP_SIZE;
73071
73072       for (n = 0; n < elems; n++) {
73073         if (tree[n * 2]/*.Freq*/ !== 0) {
73074           s.heap[++s.heap_len] = max_code = n;
73075           s.depth[n] = 0;
73076
73077         } else {
73078           tree[n * 2 + 1]/*.Len*/ = 0;
73079         }
73080       }
73081
73082       /* The pkzip format requires that at least one distance code exists,
73083        * and that at least one bit should be sent even if there is only one
73084        * possible code. So to avoid special checks later on we force at least
73085        * two codes of non zero frequency.
73086        */
73087       while (s.heap_len < 2) {
73088         node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
73089         tree[node * 2]/*.Freq*/ = 1;
73090         s.depth[node] = 0;
73091         s.opt_len--;
73092
73093         if (has_stree) {
73094           s.static_len -= stree[node * 2 + 1]/*.Len*/;
73095         }
73096         /* node is 0 or 1 so it does not have extra bits */
73097       }
73098       desc.max_code = max_code;
73099
73100       /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
73101        * establish sub-heaps of increasing lengths:
73102        */
73103       for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
73104
73105       /* Construct the Huffman tree by repeatedly combining the least two
73106        * frequent nodes.
73107        */
73108       node = elems;              /* next internal node of the tree */
73109       do {
73110         //pqremove(s, tree, n);  /* n = node of least frequency */
73111         /*** pqremove ***/
73112         n = s.heap[1/*SMALLEST*/];
73113         s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
73114         pqdownheap(s, tree, 1/*SMALLEST*/);
73115         /***/
73116
73117         m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
73118
73119         s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
73120         s.heap[--s.heap_max] = m;
73121
73122         /* Create a new node father of n and m */
73123         tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
73124         s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
73125         tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
73126
73127         /* and insert the new node in the heap */
73128         s.heap[1/*SMALLEST*/] = node++;
73129         pqdownheap(s, tree, 1/*SMALLEST*/);
73130
73131       } while (s.heap_len >= 2);
73132
73133       s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
73134
73135       /* At this point, the fields freq and dad are set. We can now
73136        * generate the bit lengths.
73137        */
73138       gen_bitlen(s, desc);
73139
73140       /* The field len is now set, we can generate the bit codes */
73141       gen_codes(tree, max_code, s.bl_count);
73142     };
73143
73144
73145     /* ===========================================================================
73146      * Scan a literal or distance tree to determine the frequencies of the codes
73147      * in the bit length tree.
73148      */
73149     const scan_tree = (s, tree, max_code) =>
73150     //    deflate_state *s;
73151     //    ct_data *tree;   /* the tree to be scanned */
73152     //    int max_code;    /* and its largest code of non zero frequency */
73153     {
73154       let n;                     /* iterates over all tree elements */
73155       let prevlen = -1;          /* last emitted length */
73156       let curlen;                /* length of current code */
73157
73158       let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
73159
73160       let count = 0;             /* repeat count of the current code */
73161       let max_count = 7;         /* max repeat count */
73162       let min_count = 4;         /* min repeat count */
73163
73164       if (nextlen === 0) {
73165         max_count = 138;
73166         min_count = 3;
73167       }
73168       tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
73169
73170       for (n = 0; n <= max_code; n++) {
73171         curlen = nextlen;
73172         nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
73173
73174         if (++count < max_count && curlen === nextlen) {
73175           continue;
73176
73177         } else if (count < min_count) {
73178           s.bl_tree[curlen * 2]/*.Freq*/ += count;
73179
73180         } else if (curlen !== 0) {
73181
73182           if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
73183           s.bl_tree[REP_3_6 * 2]/*.Freq*/++;
73184
73185         } else if (count <= 10) {
73186           s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;
73187
73188         } else {
73189           s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
73190         }
73191
73192         count = 0;
73193         prevlen = curlen;
73194
73195         if (nextlen === 0) {
73196           max_count = 138;
73197           min_count = 3;
73198
73199         } else if (curlen === nextlen) {
73200           max_count = 6;
73201           min_count = 3;
73202
73203         } else {
73204           max_count = 7;
73205           min_count = 4;
73206         }
73207       }
73208     };
73209
73210
73211     /* ===========================================================================
73212      * Send a literal or distance tree in compressed form, using the codes in
73213      * bl_tree.
73214      */
73215     const send_tree = (s, tree, max_code) =>
73216     //    deflate_state *s;
73217     //    ct_data *tree; /* the tree to be scanned */
73218     //    int max_code;       /* and its largest code of non zero frequency */
73219     {
73220       let n;                     /* iterates over all tree elements */
73221       let prevlen = -1;          /* last emitted length */
73222       let curlen;                /* length of current code */
73223
73224       let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
73225
73226       let count = 0;             /* repeat count of the current code */
73227       let max_count = 7;         /* max repeat count */
73228       let min_count = 4;         /* min repeat count */
73229
73230       /* tree[max_code+1].Len = -1; */  /* guard already set */
73231       if (nextlen === 0) {
73232         max_count = 138;
73233         min_count = 3;
73234       }
73235
73236       for (n = 0; n <= max_code; n++) {
73237         curlen = nextlen;
73238         nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
73239
73240         if (++count < max_count && curlen === nextlen) {
73241           continue;
73242
73243         } else if (count < min_count) {
73244           do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
73245
73246         } else if (curlen !== 0) {
73247           if (curlen !== prevlen) {
73248             send_code(s, curlen, s.bl_tree);
73249             count--;
73250           }
73251           //Assert(count >= 3 && count <= 6, " 3_6?");
73252           send_code(s, REP_3_6, s.bl_tree);
73253           send_bits(s, count - 3, 2);
73254
73255         } else if (count <= 10) {
73256           send_code(s, REPZ_3_10, s.bl_tree);
73257           send_bits(s, count - 3, 3);
73258
73259         } else {
73260           send_code(s, REPZ_11_138, s.bl_tree);
73261           send_bits(s, count - 11, 7);
73262         }
73263
73264         count = 0;
73265         prevlen = curlen;
73266         if (nextlen === 0) {
73267           max_count = 138;
73268           min_count = 3;
73269
73270         } else if (curlen === nextlen) {
73271           max_count = 6;
73272           min_count = 3;
73273
73274         } else {
73275           max_count = 7;
73276           min_count = 4;
73277         }
73278       }
73279     };
73280
73281
73282     /* ===========================================================================
73283      * Construct the Huffman tree for the bit lengths and return the index in
73284      * bl_order of the last bit length code to send.
73285      */
73286     const build_bl_tree = (s) => {
73287
73288       let max_blindex;  /* index of last bit length code of non zero freq */
73289
73290       /* Determine the bit length frequencies for literal and distance trees */
73291       scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
73292       scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
73293
73294       /* Build the bit length tree: */
73295       build_tree(s, s.bl_desc);
73296       /* opt_len now includes the length of the tree representations, except
73297        * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
73298        */
73299
73300       /* Determine the number of bit length codes to send. The pkzip format
73301        * requires that at least 4 bit length codes be sent. (appnote.txt says
73302        * 3 but the actual value used is 4.)
73303        */
73304       for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
73305         if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
73306           break;
73307         }
73308       }
73309       /* Update opt_len to include the bit length tree and counts */
73310       s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
73311       //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
73312       //        s->opt_len, s->static_len));
73313
73314       return max_blindex;
73315     };
73316
73317
73318     /* ===========================================================================
73319      * Send the header for a block using dynamic Huffman trees: the counts, the
73320      * lengths of the bit length codes, the literal tree and the distance tree.
73321      * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
73322      */
73323     const send_all_trees = (s, lcodes, dcodes, blcodes) =>
73324     //    deflate_state *s;
73325     //    int lcodes, dcodes, blcodes; /* number of codes for each tree */
73326     {
73327       let rank;                    /* index in bl_order */
73328
73329       //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
73330       //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
73331       //        "too many codes");
73332       //Tracev((stderr, "\nbl counts: "));
73333       send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
73334       send_bits(s, dcodes - 1,   5);
73335       send_bits(s, blcodes - 4,  4); /* not -3 as stated in appnote.txt */
73336       for (rank = 0; rank < blcodes; rank++) {
73337         //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
73338         send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
73339       }
73340       //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
73341
73342       send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
73343       //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
73344
73345       send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
73346       //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
73347     };
73348
73349
73350     /* ===========================================================================
73351      * Check if the data type is TEXT or BINARY, using the following algorithm:
73352      * - TEXT if the two conditions below are satisfied:
73353      *    a) There are no non-portable control characters belonging to the
73354      *       "black list" (0..6, 14..25, 28..31).
73355      *    b) There is at least one printable character belonging to the
73356      *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
73357      * - BINARY otherwise.
73358      * - The following partially-portable control characters form a
73359      *   "gray list" that is ignored in this detection algorithm:
73360      *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
73361      * IN assertion: the fields Freq of dyn_ltree are set.
73362      */
73363     const detect_data_type = (s) => {
73364       /* black_mask is the bit mask of black-listed bytes
73365        * set bits 0..6, 14..25, and 28..31
73366        * 0xf3ffc07f = binary 11110011111111111100000001111111
73367        */
73368       let black_mask = 0xf3ffc07f;
73369       let n;
73370
73371       /* Check for non-textual ("black-listed") bytes. */
73372       for (n = 0; n <= 31; n++, black_mask >>>= 1) {
73373         if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
73374           return Z_BINARY;
73375         }
73376       }
73377
73378       /* Check for textual ("white-listed") bytes. */
73379       if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
73380           s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
73381         return Z_TEXT;
73382       }
73383       for (n = 32; n < LITERALS; n++) {
73384         if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
73385           return Z_TEXT;
73386         }
73387       }
73388
73389       /* There are no "black-listed" or "white-listed" bytes:
73390        * this stream either is empty or has tolerated ("gray-listed") bytes only.
73391        */
73392       return Z_BINARY;
73393     };
73394
73395
73396     let static_init_done = false;
73397
73398     /* ===========================================================================
73399      * Initialize the tree data structures for a new zlib stream.
73400      */
73401     const _tr_init = (s) =>
73402     {
73403
73404       if (!static_init_done) {
73405         tr_static_init();
73406         static_init_done = true;
73407       }
73408
73409       s.l_desc  = new TreeDesc(s.dyn_ltree, static_l_desc);
73410       s.d_desc  = new TreeDesc(s.dyn_dtree, static_d_desc);
73411       s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
73412
73413       s.bi_buf = 0;
73414       s.bi_valid = 0;
73415
73416       /* Initialize the first block of the first file: */
73417       init_block(s);
73418     };
73419
73420
73421     /* ===========================================================================
73422      * Send a stored block
73423      */
73424     const _tr_stored_block = (s, buf, stored_len, last) =>
73425     //DeflateState *s;
73426     //charf *buf;       /* input block */
73427     //ulg stored_len;   /* length of input block */
73428     //int last;         /* one if this is the last block for a file */
73429     {
73430       send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3);    /* send block type */
73431       copy_block(s, buf, stored_len, true); /* with header */
73432     };
73433
73434
73435     /* ===========================================================================
73436      * Send one empty static block to give enough lookahead for inflate.
73437      * This takes 10 bits, of which 7 may remain in the bit buffer.
73438      */
73439     const _tr_align = (s) => {
73440       send_bits(s, STATIC_TREES << 1, 3);
73441       send_code(s, END_BLOCK, static_ltree);
73442       bi_flush(s);
73443     };
73444
73445
73446     /* ===========================================================================
73447      * Determine the best encoding for the current block: dynamic trees, static
73448      * trees or store, and output the encoded block to the zip file.
73449      */
73450     const _tr_flush_block = (s, buf, stored_len, last) =>
73451     //DeflateState *s;
73452     //charf *buf;       /* input block, or NULL if too old */
73453     //ulg stored_len;   /* length of input block */
73454     //int last;         /* one if this is the last block for a file */
73455     {
73456       let opt_lenb, static_lenb;  /* opt_len and static_len in bytes */
73457       let max_blindex = 0;        /* index of last bit length code of non zero freq */
73458
73459       /* Build the Huffman trees unless a stored block is forced */
73460       if (s.level > 0) {
73461
73462         /* Check if the file is binary or text */
73463         if (s.strm.data_type === Z_UNKNOWN) {
73464           s.strm.data_type = detect_data_type(s);
73465         }
73466
73467         /* Construct the literal and distance trees */
73468         build_tree(s, s.l_desc);
73469         // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
73470         //        s->static_len));
73471
73472         build_tree(s, s.d_desc);
73473         // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
73474         //        s->static_len));
73475         /* At this point, opt_len and static_len are the total bit lengths of
73476          * the compressed block data, excluding the tree representations.
73477          */
73478
73479         /* Build the bit length tree for the above two trees, and get the index
73480          * in bl_order of the last bit length code to send.
73481          */
73482         max_blindex = build_bl_tree(s);
73483
73484         /* Determine the best encoding. Compute the block lengths in bytes. */
73485         opt_lenb = (s.opt_len + 3 + 7) >>> 3;
73486         static_lenb = (s.static_len + 3 + 7) >>> 3;
73487
73488         // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
73489         //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
73490         //        s->last_lit));
73491
73492         if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
73493
73494       } else {
73495         // Assert(buf != (char*)0, "lost buf");
73496         opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
73497       }
73498
73499       if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
73500         /* 4: two words for the lengths */
73501
73502         /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
73503          * Otherwise we can't have processed more than WSIZE input bytes since
73504          * the last block flush, because compression would have been
73505          * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
73506          * transform a block into a stored block.
73507          */
73508         _tr_stored_block(s, buf, stored_len, last);
73509
73510       } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {
73511
73512         send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
73513         compress_block(s, static_ltree, static_dtree);
73514
73515       } else {
73516         send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
73517         send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
73518         compress_block(s, s.dyn_ltree, s.dyn_dtree);
73519       }
73520       // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
73521       /* The above check is made mod 2^32, for files larger than 512 MB
73522        * and uLong implemented on 32 bits.
73523        */
73524       init_block(s);
73525
73526       if (last) {
73527         bi_windup(s);
73528       }
73529       // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
73530       //       s->compressed_len-7*last));
73531     };
73532
73533     /* ===========================================================================
73534      * Save the match info and tally the frequency counts. Return true if
73535      * the current block must be flushed.
73536      */
73537     const _tr_tally = (s, dist, lc) =>
73538     //    deflate_state *s;
73539     //    unsigned dist;  /* distance of matched string */
73540     //    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
73541     {
73542       //let out_length, in_length, dcode;
73543
73544       s.pending_buf[s.d_buf + s.last_lit * 2]     = (dist >>> 8) & 0xff;
73545       s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
73546
73547       s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
73548       s.last_lit++;
73549
73550       if (dist === 0) {
73551         /* lc is the unmatched char */
73552         s.dyn_ltree[lc * 2]/*.Freq*/++;
73553       } else {
73554         s.matches++;
73555         /* Here, lc is the match length - MIN_MATCH */
73556         dist--;             /* dist = match distance - 1 */
73557         //Assert((ush)dist < (ush)MAX_DIST(s) &&
73558         //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
73559         //       (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
73560
73561         s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++;
73562         s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
73563       }
73564
73565     // (!) This block is disabled in zlib defaults,
73566     // don't enable it for binary compatibility
73567
73568     //#ifdef TRUNCATE_BLOCK
73569     //  /* Try to guess if it is profitable to stop the current block here */
73570     //  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
73571     //    /* Compute an upper bound for the compressed length */
73572     //    out_length = s.last_lit*8;
73573     //    in_length = s.strstart - s.block_start;
73574     //
73575     //    for (dcode = 0; dcode < D_CODES; dcode++) {
73576     //      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
73577     //    }
73578     //    out_length >>>= 3;
73579     //    //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
73580     //    //       s->last_lit, in_length, out_length,
73581     //    //       100L - out_length*100L/in_length));
73582     //    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
73583     //      return true;
73584     //    }
73585     //  }
73586     //#endif
73587
73588       return (s.last_lit === s.lit_bufsize - 1);
73589       /* We avoid equality with lit_bufsize because of wraparound at 64K
73590        * on 16 bit machines and because stored blocks are restricted to
73591        * 64K-1 bytes.
73592        */
73593     };
73594
73595     var _tr_init_1  = _tr_init;
73596     var _tr_stored_block_1 = _tr_stored_block;
73597     var _tr_flush_block_1  = _tr_flush_block;
73598     var _tr_tally_1 = _tr_tally;
73599     var _tr_align_1 = _tr_align;
73600
73601     var trees = {
73602         _tr_init: _tr_init_1,
73603         _tr_stored_block: _tr_stored_block_1,
73604         _tr_flush_block: _tr_flush_block_1,
73605         _tr_tally: _tr_tally_1,
73606         _tr_align: _tr_align_1
73607     };
73608
73609     // Note: adler32 takes 12% for level 0 and 2% for level 6.
73610     // It isn't worth it to make additional optimizations as in original.
73611     // Small size is preferable.
73612
73613     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73614     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73615     //
73616     // This software is provided 'as-is', without any express or implied
73617     // warranty. In no event will the authors be held liable for any damages
73618     // arising from the use of this software.
73619     //
73620     // Permission is granted to anyone to use this software for any purpose,
73621     // including commercial applications, and to alter it and redistribute it
73622     // freely, subject to the following restrictions:
73623     //
73624     // 1. The origin of this software must not be misrepresented; you must not
73625     //   claim that you wrote the original software. If you use this software
73626     //   in a product, an acknowledgment in the product documentation would be
73627     //   appreciated but is not required.
73628     // 2. Altered source versions must be plainly marked as such, and must not be
73629     //   misrepresented as being the original software.
73630     // 3. This notice may not be removed or altered from any source distribution.
73631
73632     const adler32 = (adler, buf, len, pos) => {
73633       let s1 = (adler & 0xffff) |0,
73634           s2 = ((adler >>> 16) & 0xffff) |0,
73635           n = 0;
73636
73637       while (len !== 0) {
73638         // Set limit ~ twice less than 5552, to keep
73639         // s2 in 31-bits, because we force signed ints.
73640         // in other case %= will fail.
73641         n = len > 2000 ? 2000 : len;
73642         len -= n;
73643
73644         do {
73645           s1 = (s1 + buf[pos++]) |0;
73646           s2 = (s2 + s1) |0;
73647         } while (--n);
73648
73649         s1 %= 65521;
73650         s2 %= 65521;
73651       }
73652
73653       return (s1 | (s2 << 16)) |0;
73654     };
73655
73656
73657     var adler32_1 = adler32;
73658
73659     // Note: we can't get significant speed boost here.
73660     // So write code to minimize size - no pregenerated tables
73661     // and array tools dependencies.
73662
73663     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73664     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73665     //
73666     // This software is provided 'as-is', without any express or implied
73667     // warranty. In no event will the authors be held liable for any damages
73668     // arising from the use of this software.
73669     //
73670     // Permission is granted to anyone to use this software for any purpose,
73671     // including commercial applications, and to alter it and redistribute it
73672     // freely, subject to the following restrictions:
73673     //
73674     // 1. The origin of this software must not be misrepresented; you must not
73675     //   claim that you wrote the original software. If you use this software
73676     //   in a product, an acknowledgment in the product documentation would be
73677     //   appreciated but is not required.
73678     // 2. Altered source versions must be plainly marked as such, and must not be
73679     //   misrepresented as being the original software.
73680     // 3. This notice may not be removed or altered from any source distribution.
73681
73682     // Use ordinary array, since untyped makes no boost here
73683     const makeTable = () => {
73684       let c, table = [];
73685
73686       for (var n = 0; n < 256; n++) {
73687         c = n;
73688         for (var k = 0; k < 8; k++) {
73689           c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
73690         }
73691         table[n] = c;
73692       }
73693
73694       return table;
73695     };
73696
73697     // Create table on load. Just 255 signed longs. Not a problem.
73698     const crcTable = new Uint32Array(makeTable());
73699
73700
73701     const crc32 = (crc, buf, len, pos) => {
73702       const t = crcTable;
73703       const end = pos + len;
73704
73705       crc ^= -1;
73706
73707       for (let i = pos; i < end; i++) {
73708         crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
73709       }
73710
73711       return (crc ^ (-1)); // >>> 0;
73712     };
73713
73714
73715     var crc32_1 = crc32;
73716
73717     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73718     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73719     //
73720     // This software is provided 'as-is', without any express or implied
73721     // warranty. In no event will the authors be held liable for any damages
73722     // arising from the use of this software.
73723     //
73724     // Permission is granted to anyone to use this software for any purpose,
73725     // including commercial applications, and to alter it and redistribute it
73726     // freely, subject to the following restrictions:
73727     //
73728     // 1. The origin of this software must not be misrepresented; you must not
73729     //   claim that you wrote the original software. If you use this software
73730     //   in a product, an acknowledgment in the product documentation would be
73731     //   appreciated but is not required.
73732     // 2. Altered source versions must be plainly marked as such, and must not be
73733     //   misrepresented as being the original software.
73734     // 3. This notice may not be removed or altered from any source distribution.
73735
73736     var messages = {
73737       2:      'need dictionary',     /* Z_NEED_DICT       2  */
73738       1:      'stream end',          /* Z_STREAM_END      1  */
73739       0:      '',                    /* Z_OK              0  */
73740       '-1':   'file error',          /* Z_ERRNO         (-1) */
73741       '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */
73742       '-3':   'data error',          /* Z_DATA_ERROR    (-3) */
73743       '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */
73744       '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */
73745       '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */
73746     };
73747
73748     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73749     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73750     //
73751     // This software is provided 'as-is', without any express or implied
73752     // warranty. In no event will the authors be held liable for any damages
73753     // arising from the use of this software.
73754     //
73755     // Permission is granted to anyone to use this software for any purpose,
73756     // including commercial applications, and to alter it and redistribute it
73757     // freely, subject to the following restrictions:
73758     //
73759     // 1. The origin of this software must not be misrepresented; you must not
73760     //   claim that you wrote the original software. If you use this software
73761     //   in a product, an acknowledgment in the product documentation would be
73762     //   appreciated but is not required.
73763     // 2. Altered source versions must be plainly marked as such, and must not be
73764     //   misrepresented as being the original software.
73765     // 3. This notice may not be removed or altered from any source distribution.
73766
73767     var constants = {
73768
73769       /* Allowed flush values; see deflate() and inflate() below for details */
73770       Z_NO_FLUSH:         0,
73771       Z_PARTIAL_FLUSH:    1,
73772       Z_SYNC_FLUSH:       2,
73773       Z_FULL_FLUSH:       3,
73774       Z_FINISH:           4,
73775       Z_BLOCK:            5,
73776       Z_TREES:            6,
73777
73778       /* Return codes for the compression/decompression functions. Negative values
73779       * are errors, positive values are used for special but normal events.
73780       */
73781       Z_OK:               0,
73782       Z_STREAM_END:       1,
73783       Z_NEED_DICT:        2,
73784       Z_ERRNO:           -1,
73785       Z_STREAM_ERROR:    -2,
73786       Z_DATA_ERROR:      -3,
73787       Z_MEM_ERROR:       -4,
73788       Z_BUF_ERROR:       -5,
73789       //Z_VERSION_ERROR: -6,
73790
73791       /* compression levels */
73792       Z_NO_COMPRESSION:         0,
73793       Z_BEST_SPEED:             1,
73794       Z_BEST_COMPRESSION:       9,
73795       Z_DEFAULT_COMPRESSION:   -1,
73796
73797
73798       Z_FILTERED:               1,
73799       Z_HUFFMAN_ONLY:           2,
73800       Z_RLE:                    3,
73801       Z_FIXED:                  4,
73802       Z_DEFAULT_STRATEGY:       0,
73803
73804       /* Possible values of the data_type field (though see inflate()) */
73805       Z_BINARY:                 0,
73806       Z_TEXT:                   1,
73807       //Z_ASCII:                1, // = Z_TEXT (deprecated)
73808       Z_UNKNOWN:                2,
73809
73810       /* The deflate compression method */
73811       Z_DEFLATED:               8
73812       //Z_NULL:                 null // Use -1 or null inline, depending on var type
73813     };
73814
73815     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73816     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73817     //
73818     // This software is provided 'as-is', without any express or implied
73819     // warranty. In no event will the authors be held liable for any damages
73820     // arising from the use of this software.
73821     //
73822     // Permission is granted to anyone to use this software for any purpose,
73823     // including commercial applications, and to alter it and redistribute it
73824     // freely, subject to the following restrictions:
73825     //
73826     // 1. The origin of this software must not be misrepresented; you must not
73827     //   claim that you wrote the original software. If you use this software
73828     //   in a product, an acknowledgment in the product documentation would be
73829     //   appreciated but is not required.
73830     // 2. Altered source versions must be plainly marked as such, and must not be
73831     //   misrepresented as being the original software.
73832     // 3. This notice may not be removed or altered from any source distribution.
73833
73834     const { _tr_init: _tr_init$1, _tr_stored_block: _tr_stored_block$1, _tr_flush_block: _tr_flush_block$1, _tr_tally: _tr_tally$1, _tr_align: _tr_align$1 } = trees;
73835
73836
73837
73838
73839     /* Public constants ==========================================================*/
73840     /* ===========================================================================*/
73841
73842     const {
73843       Z_NO_FLUSH, Z_PARTIAL_FLUSH, Z_FULL_FLUSH, Z_FINISH, Z_BLOCK,
73844       Z_OK, Z_STREAM_END, Z_STREAM_ERROR, Z_DATA_ERROR, Z_BUF_ERROR,
73845       Z_DEFAULT_COMPRESSION,
73846       Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED: Z_FIXED$1, Z_DEFAULT_STRATEGY,
73847       Z_UNKNOWN: Z_UNKNOWN$1,
73848       Z_DEFLATED
73849     } = constants;
73850
73851     /*============================================================================*/
73852
73853
73854     const MAX_MEM_LEVEL = 9;
73855     /* Maximum value for memLevel in deflateInit2 */
73856     const MAX_WBITS = 15;
73857     /* 32K LZ77 window */
73858     const DEF_MEM_LEVEL = 8;
73859
73860
73861     const LENGTH_CODES$1  = 29;
73862     /* number of length codes, not counting the special END_BLOCK code */
73863     const LITERALS$1      = 256;
73864     /* number of literal bytes 0..255 */
73865     const L_CODES$1       = LITERALS$1 + 1 + LENGTH_CODES$1;
73866     /* number of Literal or Length codes, including the END_BLOCK code */
73867     const D_CODES$1       = 30;
73868     /* number of distance codes */
73869     const BL_CODES$1      = 19;
73870     /* number of codes used to transfer the bit lengths */
73871     const HEAP_SIZE$1     = 2 * L_CODES$1 + 1;
73872     /* maximum heap size */
73873     const MAX_BITS$1  = 15;
73874     /* All codes must not exceed MAX_BITS bits */
73875
73876     const MIN_MATCH$1 = 3;
73877     const MAX_MATCH$1 = 258;
73878     const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1);
73879
73880     const PRESET_DICT = 0x20;
73881
73882     const INIT_STATE = 42;
73883     const EXTRA_STATE = 69;
73884     const NAME_STATE = 73;
73885     const COMMENT_STATE = 91;
73886     const HCRC_STATE = 103;
73887     const BUSY_STATE = 113;
73888     const FINISH_STATE = 666;
73889
73890     const BS_NEED_MORE      = 1; /* block not completed, need more input or more output */
73891     const BS_BLOCK_DONE     = 2; /* block flush performed */
73892     const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
73893     const BS_FINISH_DONE    = 4; /* finish done, accept no more input or output */
73894
73895     const OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
73896
73897     const err = (strm, errorCode) => {
73898       strm.msg = messages[errorCode];
73899       return errorCode;
73900     };
73901
73902     const rank = (f) => {
73903       return ((f) << 1) - ((f) > 4 ? 9 : 0);
73904     };
73905
73906     const zero$1 = (buf) => {
73907       let len = buf.length; while (--len >= 0) { buf[len] = 0; }
73908     };
73909
73910
73911     /* eslint-disable new-cap */
73912     let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask;
73913     // This hash causes less collisions, https://github.com/nodeca/pako/issues/135
73914     // But breaks binary compatibility
73915     //let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;
73916     let HASH = HASH_ZLIB;
73917
73918     /* =========================================================================
73919      * Flush as much pending output as possible. All deflate() output goes
73920      * through this function so some applications may wish to modify it
73921      * to avoid allocating a large strm->output buffer and copying into it.
73922      * (See also read_buf()).
73923      */
73924     const flush_pending = (strm) => {
73925       const s = strm.state;
73926
73927       //_tr_flush_bits(s);
73928       let len = s.pending;
73929       if (len > strm.avail_out) {
73930         len = strm.avail_out;
73931       }
73932       if (len === 0) { return; }
73933
73934       strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);
73935       strm.next_out += len;
73936       s.pending_out += len;
73937       strm.total_out += len;
73938       strm.avail_out -= len;
73939       s.pending -= len;
73940       if (s.pending === 0) {
73941         s.pending_out = 0;
73942       }
73943     };
73944
73945
73946     const flush_block_only = (s, last) => {
73947       _tr_flush_block$1(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
73948       s.block_start = s.strstart;
73949       flush_pending(s.strm);
73950     };
73951
73952
73953     const put_byte = (s, b) => {
73954       s.pending_buf[s.pending++] = b;
73955     };
73956
73957
73958     /* =========================================================================
73959      * Put a short in the pending buffer. The 16-bit value is put in MSB order.
73960      * IN assertion: the stream state is correct and there is enough room in
73961      * pending_buf.
73962      */
73963     const putShortMSB = (s, b) => {
73964
73965       //  put_byte(s, (Byte)(b >> 8));
73966     //  put_byte(s, (Byte)(b & 0xff));
73967       s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
73968       s.pending_buf[s.pending++] = b & 0xff;
73969     };
73970
73971
73972     /* ===========================================================================
73973      * Read a new buffer from the current input stream, update the adler32
73974      * and total number of bytes read.  All deflate() input goes through
73975      * this function so some applications may wish to modify it to avoid
73976      * allocating a large strm->input buffer and copying from it.
73977      * (See also flush_pending()).
73978      */
73979     const read_buf = (strm, buf, start, size) => {
73980
73981       let len = strm.avail_in;
73982
73983       if (len > size) { len = size; }
73984       if (len === 0) { return 0; }
73985
73986       strm.avail_in -= len;
73987
73988       // zmemcpy(buf, strm->next_in, len);
73989       buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start);
73990       if (strm.state.wrap === 1) {
73991         strm.adler = adler32_1(strm.adler, buf, len, start);
73992       }
73993
73994       else if (strm.state.wrap === 2) {
73995         strm.adler = crc32_1(strm.adler, buf, len, start);
73996       }
73997
73998       strm.next_in += len;
73999       strm.total_in += len;
74000
74001       return len;
74002     };
74003
74004
74005     /* ===========================================================================
74006      * Set match_start to the longest match starting at the given string and
74007      * return its length. Matches shorter or equal to prev_length are discarded,
74008      * in which case the result is equal to prev_length and match_start is
74009      * garbage.
74010      * IN assertions: cur_match is the head of the hash chain for the current
74011      *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
74012      * OUT assertion: the match length is not greater than s->lookahead.
74013      */
74014     const longest_match = (s, cur_match) => {
74015
74016       let chain_length = s.max_chain_length;      /* max hash chain length */
74017       let scan = s.strstart; /* current string */
74018       let match;                       /* matched string */
74019       let len;                           /* length of current match */
74020       let best_len = s.prev_length;              /* best match length so far */
74021       let nice_match = s.nice_match;             /* stop if match long enough */
74022       const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
74023           s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
74024
74025       const _win = s.window; // shortcut
74026
74027       const wmask = s.w_mask;
74028       const prev  = s.prev;
74029
74030       /* Stop when cur_match becomes <= limit. To simplify the code,
74031        * we prevent matches with the string of window index 0.
74032        */
74033
74034       const strend = s.strstart + MAX_MATCH$1;
74035       let scan_end1  = _win[scan + best_len - 1];
74036       let scan_end   = _win[scan + best_len];
74037
74038       /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
74039        * It is easy to get rid of this optimization if necessary.
74040        */
74041       // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
74042
74043       /* Do not waste too much time if we already have a good match: */
74044       if (s.prev_length >= s.good_match) {
74045         chain_length >>= 2;
74046       }
74047       /* Do not look for matches beyond the end of the input. This is necessary
74048        * to make deflate deterministic.
74049        */
74050       if (nice_match > s.lookahead) { nice_match = s.lookahead; }
74051
74052       // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
74053
74054       do {
74055         // Assert(cur_match < s->strstart, "no future");
74056         match = cur_match;
74057
74058         /* Skip to next match if the match length cannot increase
74059          * or if the match length is less than 2.  Note that the checks below
74060          * for insufficient lookahead only occur occasionally for performance
74061          * reasons.  Therefore uninitialized memory will be accessed, and
74062          * conditional jumps will be made that depend on those values.
74063          * However the length of the match is limited to the lookahead, so
74064          * the output of deflate is not affected by the uninitialized values.
74065          */
74066
74067         if (_win[match + best_len]     !== scan_end  ||
74068             _win[match + best_len - 1] !== scan_end1 ||
74069             _win[match]                !== _win[scan] ||
74070             _win[++match]              !== _win[scan + 1]) {
74071           continue;
74072         }
74073
74074         /* The check at best_len-1 can be removed because it will be made
74075          * again later. (This heuristic is not always a win.)
74076          * It is not necessary to compare scan[2] and match[2] since they
74077          * are always equal when the other bytes match, given that
74078          * the hash keys are equal and that HASH_BITS >= 8.
74079          */
74080         scan += 2;
74081         match++;
74082         // Assert(*scan == *match, "match[2]?");
74083
74084         /* We check for insufficient lookahead only every 8th comparison;
74085          * the 256th check will be made at strstart+258.
74086          */
74087         do {
74088           /*jshint noempty:false*/
74089         } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
74090                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
74091                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
74092                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
74093                  scan < strend);
74094
74095         // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
74096
74097         len = MAX_MATCH$1 - (strend - scan);
74098         scan = strend - MAX_MATCH$1;
74099
74100         if (len > best_len) {
74101           s.match_start = cur_match;
74102           best_len = len;
74103           if (len >= nice_match) {
74104             break;
74105           }
74106           scan_end1  = _win[scan + best_len - 1];
74107           scan_end   = _win[scan + best_len];
74108         }
74109       } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
74110
74111       if (best_len <= s.lookahead) {
74112         return best_len;
74113       }
74114       return s.lookahead;
74115     };
74116
74117
74118     /* ===========================================================================
74119      * Fill the window when the lookahead becomes insufficient.
74120      * Updates strstart and lookahead.
74121      *
74122      * IN assertion: lookahead < MIN_LOOKAHEAD
74123      * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
74124      *    At least one byte has been read, or avail_in == 0; reads are
74125      *    performed for at least two bytes (required for the zip translate_eol
74126      *    option -- not supported here).
74127      */
74128     const fill_window = (s) => {
74129
74130       const _w_size = s.w_size;
74131       let p, n, m, more, str;
74132
74133       //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
74134
74135       do {
74136         more = s.window_size - s.lookahead - s.strstart;
74137
74138         // JS ints have 32 bit, block below not needed
74139         /* Deal with !@#$% 64K limit: */
74140         //if (sizeof(int) <= 2) {
74141         //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
74142         //        more = wsize;
74143         //
74144         //  } else if (more == (unsigned)(-1)) {
74145         //        /* Very unlikely, but possible on 16 bit machine if
74146         //         * strstart == 0 && lookahead == 1 (input done a byte at time)
74147         //         */
74148         //        more--;
74149         //    }
74150         //}
74151
74152
74153         /* If the window is almost full and there is insufficient lookahead,
74154          * move the upper half to the lower one to make room in the upper half.
74155          */
74156         if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
74157
74158           s.window.set(s.window.subarray(_w_size, _w_size + _w_size), 0);
74159           s.match_start -= _w_size;
74160           s.strstart -= _w_size;
74161           /* we now have strstart >= MAX_DIST */
74162           s.block_start -= _w_size;
74163
74164           /* Slide the hash table (could be avoided with 32 bit values
74165            at the expense of memory usage). We slide even when level == 0
74166            to keep the hash table consistent if we switch back to level > 0
74167            later. (Using level 0 permanently is not an optimal usage of
74168            zlib, so we don't care about this pathological case.)
74169            */
74170
74171           n = s.hash_size;
74172           p = n;
74173
74174           do {
74175             m = s.head[--p];
74176             s.head[p] = (m >= _w_size ? m - _w_size : 0);
74177           } while (--n);
74178
74179           n = _w_size;
74180           p = n;
74181
74182           do {
74183             m = s.prev[--p];
74184             s.prev[p] = (m >= _w_size ? m - _w_size : 0);
74185             /* If n is not on any hash chain, prev[n] is garbage but
74186              * its value will never be used.
74187              */
74188           } while (--n);
74189
74190           more += _w_size;
74191         }
74192         if (s.strm.avail_in === 0) {
74193           break;
74194         }
74195
74196         /* If there was no sliding:
74197          *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
74198          *    more == window_size - lookahead - strstart
74199          * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
74200          * => more >= window_size - 2*WSIZE + 2
74201          * In the BIG_MEM or MMAP case (not yet supported),
74202          *   window_size == input_size + MIN_LOOKAHEAD  &&
74203          *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
74204          * Otherwise, window_size == 2*WSIZE so more >= 2.
74205          * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
74206          */
74207         //Assert(more >= 2, "more < 2");
74208         n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
74209         s.lookahead += n;
74210
74211         /* Initialize the hash value now that we have some input: */
74212         if (s.lookahead + s.insert >= MIN_MATCH$1) {
74213           str = s.strstart - s.insert;
74214           s.ins_h = s.window[str];
74215
74216           /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
74217           s.ins_h = HASH(s, s.ins_h, s.window[str + 1]);
74218     //#if MIN_MATCH != 3
74219     //        Call update_hash() MIN_MATCH-3 more times
74220     //#endif
74221           while (s.insert) {
74222             /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
74223             s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH$1 - 1]);
74224
74225             s.prev[str & s.w_mask] = s.head[s.ins_h];
74226             s.head[s.ins_h] = str;
74227             str++;
74228             s.insert--;
74229             if (s.lookahead + s.insert < MIN_MATCH$1) {
74230               break;
74231             }
74232           }
74233         }
74234         /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
74235          * but this is not important since only literal bytes will be emitted.
74236          */
74237
74238       } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
74239
74240       /* If the WIN_INIT bytes after the end of the current data have never been
74241        * written, then zero those bytes in order to avoid memory check reports of
74242        * the use of uninitialized (or uninitialised as Julian writes) bytes by
74243        * the longest match routines.  Update the high water mark for the next
74244        * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
74245        * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
74246        */
74247     //  if (s.high_water < s.window_size) {
74248     //    const curr = s.strstart + s.lookahead;
74249     //    let init = 0;
74250     //
74251     //    if (s.high_water < curr) {
74252     //      /* Previous high water mark below current data -- zero WIN_INIT
74253     //       * bytes or up to end of window, whichever is less.
74254     //       */
74255     //      init = s.window_size - curr;
74256     //      if (init > WIN_INIT)
74257     //        init = WIN_INIT;
74258     //      zmemzero(s->window + curr, (unsigned)init);
74259     //      s->high_water = curr + init;
74260     //    }
74261     //    else if (s->high_water < (ulg)curr + WIN_INIT) {
74262     //      /* High water mark at or above current data, but below current data
74263     //       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
74264     //       * to end of window, whichever is less.
74265     //       */
74266     //      init = (ulg)curr + WIN_INIT - s->high_water;
74267     //      if (init > s->window_size - s->high_water)
74268     //        init = s->window_size - s->high_water;
74269     //      zmemzero(s->window + s->high_water, (unsigned)init);
74270     //      s->high_water += init;
74271     //    }
74272     //  }
74273     //
74274     //  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
74275     //    "not enough room for search");
74276     };
74277
74278     /* ===========================================================================
74279      * Copy without compression as much as possible from the input stream, return
74280      * the current block state.
74281      * This function does not insert new strings in the dictionary since
74282      * uncompressible data is probably not useful. This function is used
74283      * only for the level=0 compression option.
74284      * NOTE: this function should be optimized to avoid extra copying from
74285      * window to pending_buf.
74286      */
74287     const deflate_stored = (s, flush) => {
74288
74289       /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
74290        * to pending_buf_size, and each stored block has a 5 byte header:
74291        */
74292       let max_block_size = 0xffff;
74293
74294       if (max_block_size > s.pending_buf_size - 5) {
74295         max_block_size = s.pending_buf_size - 5;
74296       }
74297
74298       /* Copy as much as possible from input to output: */
74299       for (;;) {
74300         /* Fill the window as much as possible: */
74301         if (s.lookahead <= 1) {
74302
74303           //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
74304           //  s->block_start >= (long)s->w_size, "slide too late");
74305     //      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
74306     //        s.block_start >= s.w_size)) {
74307     //        throw  new Error("slide too late");
74308     //      }
74309
74310           fill_window(s);
74311           if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
74312             return BS_NEED_MORE;
74313           }
74314
74315           if (s.lookahead === 0) {
74316             break;
74317           }
74318           /* flush the current block */
74319         }
74320         //Assert(s->block_start >= 0L, "block gone");
74321     //    if (s.block_start < 0) throw new Error("block gone");
74322
74323         s.strstart += s.lookahead;
74324         s.lookahead = 0;
74325
74326         /* Emit a stored block if pending_buf will be full: */
74327         const max_start = s.block_start + max_block_size;
74328
74329         if (s.strstart === 0 || s.strstart >= max_start) {
74330           /* strstart == 0 is possible when wraparound on 16-bit machine */
74331           s.lookahead = s.strstart - max_start;
74332           s.strstart = max_start;
74333           /*** FLUSH_BLOCK(s, 0); ***/
74334           flush_block_only(s, false);
74335           if (s.strm.avail_out === 0) {
74336             return BS_NEED_MORE;
74337           }
74338           /***/
74339
74340
74341         }
74342         /* Flush if we may have to slide, otherwise block_start may become
74343          * negative and the data will be gone:
74344          */
74345         if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
74346           /*** FLUSH_BLOCK(s, 0); ***/
74347           flush_block_only(s, false);
74348           if (s.strm.avail_out === 0) {
74349             return BS_NEED_MORE;
74350           }
74351           /***/
74352         }
74353       }
74354
74355       s.insert = 0;
74356
74357       if (flush === Z_FINISH) {
74358         /*** FLUSH_BLOCK(s, 1); ***/
74359         flush_block_only(s, true);
74360         if (s.strm.avail_out === 0) {
74361           return BS_FINISH_STARTED;
74362         }
74363         /***/
74364         return BS_FINISH_DONE;
74365       }
74366
74367       if (s.strstart > s.block_start) {
74368         /*** FLUSH_BLOCK(s, 0); ***/
74369         flush_block_only(s, false);
74370         if (s.strm.avail_out === 0) {
74371           return BS_NEED_MORE;
74372         }
74373         /***/
74374       }
74375
74376       return BS_NEED_MORE;
74377     };
74378
74379     /* ===========================================================================
74380      * Compress as much as possible from the input stream, return the current
74381      * block state.
74382      * This function does not perform lazy evaluation of matches and inserts
74383      * new strings in the dictionary only for unmatched strings or for short
74384      * matches. It is used only for the fast compression options.
74385      */
74386     const deflate_fast = (s, flush) => {
74387
74388       let hash_head;        /* head of the hash chain */
74389       let bflush;           /* set if current block must be flushed */
74390
74391       for (;;) {
74392         /* Make sure that we always have enough lookahead, except
74393          * at the end of the input file. We need MAX_MATCH bytes
74394          * for the next match, plus MIN_MATCH bytes to insert the
74395          * string following the next match.
74396          */
74397         if (s.lookahead < MIN_LOOKAHEAD) {
74398           fill_window(s);
74399           if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
74400             return BS_NEED_MORE;
74401           }
74402           if (s.lookahead === 0) {
74403             break; /* flush the current block */
74404           }
74405         }
74406
74407         /* Insert the string window[strstart .. strstart+2] in the
74408          * dictionary, and set hash_head to the head of the hash chain:
74409          */
74410         hash_head = 0/*NIL*/;
74411         if (s.lookahead >= MIN_MATCH$1) {
74412           /*** INSERT_STRING(s, s.strstart, hash_head); ***/
74413           s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1]);
74414           hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
74415           s.head[s.ins_h] = s.strstart;
74416           /***/
74417         }
74418
74419         /* Find the longest match, discarding those <= prev_length.
74420          * At this point we have always match_length < MIN_MATCH
74421          */
74422         if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
74423           /* To simplify the code, we prevent matches with the string
74424            * of window index 0 (in particular we have to avoid a match
74425            * of the string with itself at the start of the input file).
74426            */
74427           s.match_length = longest_match(s, hash_head);
74428           /* longest_match() sets match_start */
74429         }
74430         if (s.match_length >= MIN_MATCH$1) {
74431           // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
74432
74433           /*** _tr_tally_dist(s, s.strstart - s.match_start,
74434                          s.match_length - MIN_MATCH, bflush); ***/
74435           bflush = _tr_tally$1(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1);
74436
74437           s.lookahead -= s.match_length;
74438
74439           /* Insert new strings in the hash table only if the match length
74440            * is not too large. This saves time but degrades compression.
74441            */
74442           if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) {
74443             s.match_length--; /* string at strstart already in table */
74444             do {
74445               s.strstart++;
74446               /*** INSERT_STRING(s, s.strstart, hash_head); ***/
74447               s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1]);
74448               hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
74449               s.head[s.ins_h] = s.strstart;
74450               /***/
74451               /* strstart never exceeds WSIZE-MAX_MATCH, so there are
74452                * always MIN_MATCH bytes ahead.
74453                */
74454             } while (--s.match_length !== 0);
74455             s.strstart++;
74456           } else
74457           {
74458             s.strstart += s.match_length;
74459             s.match_length = 0;
74460             s.ins_h = s.window[s.strstart];
74461             /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
74462             s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]);
74463
74464     //#if MIN_MATCH != 3
74465     //                Call UPDATE_HASH() MIN_MATCH-3 more times
74466     //#endif
74467             /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
74468              * matter since it will be recomputed at next deflate call.
74469              */
74470           }
74471         } else {
74472           /* No match, output a literal byte */
74473           //Tracevv((stderr,"%c", s.window[s.strstart]));
74474           /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
74475           bflush = _tr_tally$1(s, 0, s.window[s.strstart]);
74476
74477           s.lookahead--;
74478           s.strstart++;
74479         }
74480         if (bflush) {
74481           /*** FLUSH_BLOCK(s, 0); ***/
74482           flush_block_only(s, false);
74483           if (s.strm.avail_out === 0) {
74484             return BS_NEED_MORE;
74485           }
74486           /***/
74487         }
74488       }
74489       s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1);
74490       if (flush === Z_FINISH) {
74491         /*** FLUSH_BLOCK(s, 1); ***/
74492         flush_block_only(s, true);
74493         if (s.strm.avail_out === 0) {
74494           return BS_FINISH_STARTED;
74495         }
74496         /***/
74497         return BS_FINISH_DONE;
74498       }
74499       if (s.last_lit) {
74500         /*** FLUSH_BLOCK(s, 0); ***/
74501         flush_block_only(s, false);
74502         if (s.strm.avail_out === 0) {
74503           return BS_NEED_MORE;
74504         }
74505         /***/
74506       }
74507       return BS_BLOCK_DONE;
74508     };
74509
74510     /* ===========================================================================
74511      * Same as above, but achieves better compression. We use a lazy
74512      * evaluation for matches: a match is finally adopted only if there is
74513      * no better match at the next window position.
74514      */
74515     const deflate_slow = (s, flush) => {
74516
74517       let hash_head;          /* head of hash chain */
74518       let bflush;              /* set if current block must be flushed */
74519
74520       let max_insert;
74521
74522       /* Process the input block. */
74523       for (;;) {
74524         /* Make sure that we always have enough lookahead, except
74525          * at the end of the input file. We need MAX_MATCH bytes
74526          * for the next match, plus MIN_MATCH bytes to insert the
74527          * string following the next match.
74528          */
74529         if (s.lookahead < MIN_LOOKAHEAD) {
74530           fill_window(s);
74531           if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
74532             return BS_NEED_MORE;
74533           }
74534           if (s.lookahead === 0) { break; } /* flush the current block */
74535         }
74536
74537         /* Insert the string window[strstart .. strstart+2] in the
74538          * dictionary, and set hash_head to the head of the hash chain:
74539          */
74540         hash_head = 0/*NIL*/;
74541         if (s.lookahead >= MIN_MATCH$1) {
74542           /*** INSERT_STRING(s, s.strstart, hash_head); ***/
74543           s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1]);
74544           hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
74545           s.head[s.ins_h] = s.strstart;
74546           /***/
74547         }
74548
74549         /* Find the longest match, discarding those <= prev_length.
74550          */
74551         s.prev_length = s.match_length;
74552         s.prev_match = s.match_start;
74553         s.match_length = MIN_MATCH$1 - 1;
74554
74555         if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
74556             s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
74557           /* To simplify the code, we prevent matches with the string
74558            * of window index 0 (in particular we have to avoid a match
74559            * of the string with itself at the start of the input file).
74560            */
74561           s.match_length = longest_match(s, hash_head);
74562           /* longest_match() sets match_start */
74563
74564           if (s.match_length <= 5 &&
74565              (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
74566
74567             /* If prev_match is also MIN_MATCH, match_start is garbage
74568              * but we will ignore the current match anyway.
74569              */
74570             s.match_length = MIN_MATCH$1 - 1;
74571           }
74572         }
74573         /* If there was a match at the previous step and the current
74574          * match is not better, output the previous match:
74575          */
74576         if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) {
74577           max_insert = s.strstart + s.lookahead - MIN_MATCH$1;
74578           /* Do not insert strings in hash table beyond this. */
74579
74580           //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
74581
74582           /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
74583                          s.prev_length - MIN_MATCH, bflush);***/
74584           bflush = _tr_tally$1(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1);
74585           /* Insert in hash table all strings up to the end of the match.
74586            * strstart-1 and strstart are already inserted. If there is not
74587            * enough lookahead, the last two strings are not inserted in
74588            * the hash table.
74589            */
74590           s.lookahead -= s.prev_length - 1;
74591           s.prev_length -= 2;
74592           do {
74593             if (++s.strstart <= max_insert) {
74594               /*** INSERT_STRING(s, s.strstart, hash_head); ***/
74595               s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1]);
74596               hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
74597               s.head[s.ins_h] = s.strstart;
74598               /***/
74599             }
74600           } while (--s.prev_length !== 0);
74601           s.match_available = 0;
74602           s.match_length = MIN_MATCH$1 - 1;
74603           s.strstart++;
74604
74605           if (bflush) {
74606             /*** FLUSH_BLOCK(s, 0); ***/
74607             flush_block_only(s, false);
74608             if (s.strm.avail_out === 0) {
74609               return BS_NEED_MORE;
74610             }
74611             /***/
74612           }
74613
74614         } else if (s.match_available) {
74615           /* If there was no match at the previous position, output a
74616            * single literal. If there was a match but the current match
74617            * is longer, truncate the previous match to a single literal.
74618            */
74619           //Tracevv((stderr,"%c", s->window[s->strstart-1]));
74620           /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
74621           bflush = _tr_tally$1(s, 0, s.window[s.strstart - 1]);
74622
74623           if (bflush) {
74624             /*** FLUSH_BLOCK_ONLY(s, 0) ***/
74625             flush_block_only(s, false);
74626             /***/
74627           }
74628           s.strstart++;
74629           s.lookahead--;
74630           if (s.strm.avail_out === 0) {
74631             return BS_NEED_MORE;
74632           }
74633         } else {
74634           /* There is no previous match to compare with, wait for
74635            * the next step to decide.
74636            */
74637           s.match_available = 1;
74638           s.strstart++;
74639           s.lookahead--;
74640         }
74641       }
74642       //Assert (flush != Z_NO_FLUSH, "no flush?");
74643       if (s.match_available) {
74644         //Tracevv((stderr,"%c", s->window[s->strstart-1]));
74645         /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
74646         bflush = _tr_tally$1(s, 0, s.window[s.strstart - 1]);
74647
74648         s.match_available = 0;
74649       }
74650       s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1;
74651       if (flush === Z_FINISH) {
74652         /*** FLUSH_BLOCK(s, 1); ***/
74653         flush_block_only(s, true);
74654         if (s.strm.avail_out === 0) {
74655           return BS_FINISH_STARTED;
74656         }
74657         /***/
74658         return BS_FINISH_DONE;
74659       }
74660       if (s.last_lit) {
74661         /*** FLUSH_BLOCK(s, 0); ***/
74662         flush_block_only(s, false);
74663         if (s.strm.avail_out === 0) {
74664           return BS_NEED_MORE;
74665         }
74666         /***/
74667       }
74668
74669       return BS_BLOCK_DONE;
74670     };
74671
74672
74673     /* ===========================================================================
74674      * For Z_RLE, simply look for runs of bytes, generate matches only of distance
74675      * one.  Do not maintain a hash table.  (It will be regenerated if this run of
74676      * deflate switches away from Z_RLE.)
74677      */
74678     const deflate_rle = (s, flush) => {
74679
74680       let bflush;            /* set if current block must be flushed */
74681       let prev;              /* byte at distance one to match */
74682       let scan, strend;      /* scan goes up to strend for length of run */
74683
74684       const _win = s.window;
74685
74686       for (;;) {
74687         /* Make sure that we always have enough lookahead, except
74688          * at the end of the input file. We need MAX_MATCH bytes
74689          * for the longest run, plus one for the unrolled loop.
74690          */
74691         if (s.lookahead <= MAX_MATCH$1) {
74692           fill_window(s);
74693           if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) {
74694             return BS_NEED_MORE;
74695           }
74696           if (s.lookahead === 0) { break; } /* flush the current block */
74697         }
74698
74699         /* See how many times the previous byte repeats */
74700         s.match_length = 0;
74701         if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) {
74702           scan = s.strstart - 1;
74703           prev = _win[scan];
74704           if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
74705             strend = s.strstart + MAX_MATCH$1;
74706             do {
74707               /*jshint noempty:false*/
74708             } while (prev === _win[++scan] && prev === _win[++scan] &&
74709                      prev === _win[++scan] && prev === _win[++scan] &&
74710                      prev === _win[++scan] && prev === _win[++scan] &&
74711                      prev === _win[++scan] && prev === _win[++scan] &&
74712                      scan < strend);
74713             s.match_length = MAX_MATCH$1 - (strend - scan);
74714             if (s.match_length > s.lookahead) {
74715               s.match_length = s.lookahead;
74716             }
74717           }
74718           //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
74719         }
74720
74721         /* Emit match if have run of MIN_MATCH or longer, else emit literal */
74722         if (s.match_length >= MIN_MATCH$1) {
74723           //check_match(s, s.strstart, s.strstart - 1, s.match_length);
74724
74725           /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
74726           bflush = _tr_tally$1(s, 1, s.match_length - MIN_MATCH$1);
74727
74728           s.lookahead -= s.match_length;
74729           s.strstart += s.match_length;
74730           s.match_length = 0;
74731         } else {
74732           /* No match, output a literal byte */
74733           //Tracevv((stderr,"%c", s->window[s->strstart]));
74734           /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
74735           bflush = _tr_tally$1(s, 0, s.window[s.strstart]);
74736
74737           s.lookahead--;
74738           s.strstart++;
74739         }
74740         if (bflush) {
74741           /*** FLUSH_BLOCK(s, 0); ***/
74742           flush_block_only(s, false);
74743           if (s.strm.avail_out === 0) {
74744             return BS_NEED_MORE;
74745           }
74746           /***/
74747         }
74748       }
74749       s.insert = 0;
74750       if (flush === Z_FINISH) {
74751         /*** FLUSH_BLOCK(s, 1); ***/
74752         flush_block_only(s, true);
74753         if (s.strm.avail_out === 0) {
74754           return BS_FINISH_STARTED;
74755         }
74756         /***/
74757         return BS_FINISH_DONE;
74758       }
74759       if (s.last_lit) {
74760         /*** FLUSH_BLOCK(s, 0); ***/
74761         flush_block_only(s, false);
74762         if (s.strm.avail_out === 0) {
74763           return BS_NEED_MORE;
74764         }
74765         /***/
74766       }
74767       return BS_BLOCK_DONE;
74768     };
74769
74770     /* ===========================================================================
74771      * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
74772      * (It will be regenerated if this run of deflate switches away from Huffman.)
74773      */
74774     const deflate_huff = (s, flush) => {
74775
74776       let bflush;             /* set if current block must be flushed */
74777
74778       for (;;) {
74779         /* Make sure that we have a literal to write. */
74780         if (s.lookahead === 0) {
74781           fill_window(s);
74782           if (s.lookahead === 0) {
74783             if (flush === Z_NO_FLUSH) {
74784               return BS_NEED_MORE;
74785             }
74786             break;      /* flush the current block */
74787           }
74788         }
74789
74790         /* Output a literal byte */
74791         s.match_length = 0;
74792         //Tracevv((stderr,"%c", s->window[s->strstart]));
74793         /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
74794         bflush = _tr_tally$1(s, 0, s.window[s.strstart]);
74795         s.lookahead--;
74796         s.strstart++;
74797         if (bflush) {
74798           /*** FLUSH_BLOCK(s, 0); ***/
74799           flush_block_only(s, false);
74800           if (s.strm.avail_out === 0) {
74801             return BS_NEED_MORE;
74802           }
74803           /***/
74804         }
74805       }
74806       s.insert = 0;
74807       if (flush === Z_FINISH) {
74808         /*** FLUSH_BLOCK(s, 1); ***/
74809         flush_block_only(s, true);
74810         if (s.strm.avail_out === 0) {
74811           return BS_FINISH_STARTED;
74812         }
74813         /***/
74814         return BS_FINISH_DONE;
74815       }
74816       if (s.last_lit) {
74817         /*** FLUSH_BLOCK(s, 0); ***/
74818         flush_block_only(s, false);
74819         if (s.strm.avail_out === 0) {
74820           return BS_NEED_MORE;
74821         }
74822         /***/
74823       }
74824       return BS_BLOCK_DONE;
74825     };
74826
74827     /* Values for max_lazy_match, good_match and max_chain_length, depending on
74828      * the desired pack level (0..9). The values given below have been tuned to
74829      * exclude worst case performance for pathological files. Better values may be
74830      * found for specific files.
74831      */
74832     function Config(good_length, max_lazy, nice_length, max_chain, func) {
74833
74834       this.good_length = good_length;
74835       this.max_lazy = max_lazy;
74836       this.nice_length = nice_length;
74837       this.max_chain = max_chain;
74838       this.func = func;
74839     }
74840
74841     const configuration_table = [
74842       /*      good lazy nice chain */
74843       new Config(0, 0, 0, 0, deflate_stored),          /* 0 store only */
74844       new Config(4, 4, 8, 4, deflate_fast),            /* 1 max speed, no lazy matches */
74845       new Config(4, 5, 16, 8, deflate_fast),           /* 2 */
74846       new Config(4, 6, 32, 32, deflate_fast),          /* 3 */
74847
74848       new Config(4, 4, 16, 16, deflate_slow),          /* 4 lazy matches */
74849       new Config(8, 16, 32, 32, deflate_slow),         /* 5 */
74850       new Config(8, 16, 128, 128, deflate_slow),       /* 6 */
74851       new Config(8, 32, 128, 256, deflate_slow),       /* 7 */
74852       new Config(32, 128, 258, 1024, deflate_slow),    /* 8 */
74853       new Config(32, 258, 258, 4096, deflate_slow)     /* 9 max compression */
74854     ];
74855
74856
74857     /* ===========================================================================
74858      * Initialize the "longest match" routines for a new zlib stream
74859      */
74860     const lm_init = (s) => {
74861
74862       s.window_size = 2 * s.w_size;
74863
74864       /*** CLEAR_HASH(s); ***/
74865       zero$1(s.head); // Fill with NIL (= 0);
74866
74867       /* Set the default configuration parameters:
74868        */
74869       s.max_lazy_match = configuration_table[s.level].max_lazy;
74870       s.good_match = configuration_table[s.level].good_length;
74871       s.nice_match = configuration_table[s.level].nice_length;
74872       s.max_chain_length = configuration_table[s.level].max_chain;
74873
74874       s.strstart = 0;
74875       s.block_start = 0;
74876       s.lookahead = 0;
74877       s.insert = 0;
74878       s.match_length = s.prev_length = MIN_MATCH$1 - 1;
74879       s.match_available = 0;
74880       s.ins_h = 0;
74881     };
74882
74883
74884     function DeflateState() {
74885       this.strm = null;            /* pointer back to this zlib stream */
74886       this.status = 0;            /* as the name implies */
74887       this.pending_buf = null;      /* output still pending */
74888       this.pending_buf_size = 0;  /* size of pending_buf */
74889       this.pending_out = 0;       /* next pending byte to output to the stream */
74890       this.pending = 0;           /* nb of bytes in the pending buffer */
74891       this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
74892       this.gzhead = null;         /* gzip header information to write */
74893       this.gzindex = 0;           /* where in extra, name, or comment */
74894       this.method = Z_DEFLATED; /* can only be DEFLATED */
74895       this.last_flush = -1;   /* value of flush param for previous deflate call */
74896
74897       this.w_size = 0;  /* LZ77 window size (32K by default) */
74898       this.w_bits = 0;  /* log2(w_size)  (8..16) */
74899       this.w_mask = 0;  /* w_size - 1 */
74900
74901       this.window = null;
74902       /* Sliding window. Input bytes are read into the second half of the window,
74903        * and move to the first half later to keep a dictionary of at least wSize
74904        * bytes. With this organization, matches are limited to a distance of
74905        * wSize-MAX_MATCH bytes, but this ensures that IO is always
74906        * performed with a length multiple of the block size.
74907        */
74908
74909       this.window_size = 0;
74910       /* Actual size of window: 2*wSize, except when the user input buffer
74911        * is directly used as sliding window.
74912        */
74913
74914       this.prev = null;
74915       /* Link to older string with same hash index. To limit the size of this
74916        * array to 64K, this link is maintained only for the last 32K strings.
74917        * An index in this array is thus a window index modulo 32K.
74918        */
74919
74920       this.head = null;   /* Heads of the hash chains or NIL. */
74921
74922       this.ins_h = 0;       /* hash index of string to be inserted */
74923       this.hash_size = 0;   /* number of elements in hash table */
74924       this.hash_bits = 0;   /* log2(hash_size) */
74925       this.hash_mask = 0;   /* hash_size-1 */
74926
74927       this.hash_shift = 0;
74928       /* Number of bits by which ins_h must be shifted at each input
74929        * step. It must be such that after MIN_MATCH steps, the oldest
74930        * byte no longer takes part in the hash key, that is:
74931        *   hash_shift * MIN_MATCH >= hash_bits
74932        */
74933
74934       this.block_start = 0;
74935       /* Window position at the beginning of the current output block. Gets
74936        * negative when the window is moved backwards.
74937        */
74938
74939       this.match_length = 0;      /* length of best match */
74940       this.prev_match = 0;        /* previous match */
74941       this.match_available = 0;   /* set if previous match exists */
74942       this.strstart = 0;          /* start of string to insert */
74943       this.match_start = 0;       /* start of matching string */
74944       this.lookahead = 0;         /* number of valid bytes ahead in window */
74945
74946       this.prev_length = 0;
74947       /* Length of the best match at previous step. Matches not greater than this
74948        * are discarded. This is used in the lazy match evaluation.
74949        */
74950
74951       this.max_chain_length = 0;
74952       /* To speed up deflation, hash chains are never searched beyond this
74953        * length.  A higher limit improves compression ratio but degrades the
74954        * speed.
74955        */
74956
74957       this.max_lazy_match = 0;
74958       /* Attempt to find a better match only when the current match is strictly
74959        * smaller than this value. This mechanism is used only for compression
74960        * levels >= 4.
74961        */
74962       // That's alias to max_lazy_match, don't use directly
74963       //this.max_insert_length = 0;
74964       /* Insert new strings in the hash table only if the match length is not
74965        * greater than this length. This saves time but degrades compression.
74966        * max_insert_length is used only for compression levels <= 3.
74967        */
74968
74969       this.level = 0;     /* compression level (1..9) */
74970       this.strategy = 0;  /* favor or force Huffman coding*/
74971
74972       this.good_match = 0;
74973       /* Use a faster search when the previous match is longer than this */
74974
74975       this.nice_match = 0; /* Stop searching when current match exceeds this */
74976
74977                   /* used by trees.c: */
74978
74979       /* Didn't use ct_data typedef below to suppress compiler warning */
74980
74981       // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
74982       // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
74983       // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
74984
74985       // Use flat array of DOUBLE size, with interleaved fata,
74986       // because JS does not support effective
74987       this.dyn_ltree  = new Uint16Array(HEAP_SIZE$1 * 2);
74988       this.dyn_dtree  = new Uint16Array((2 * D_CODES$1 + 1) * 2);
74989       this.bl_tree    = new Uint16Array((2 * BL_CODES$1 + 1) * 2);
74990       zero$1(this.dyn_ltree);
74991       zero$1(this.dyn_dtree);
74992       zero$1(this.bl_tree);
74993
74994       this.l_desc   = null;         /* desc. for literal tree */
74995       this.d_desc   = null;         /* desc. for distance tree */
74996       this.bl_desc  = null;         /* desc. for bit length tree */
74997
74998       //ush bl_count[MAX_BITS+1];
74999       this.bl_count = new Uint16Array(MAX_BITS$1 + 1);
75000       /* number of codes at each bit length for an optimal tree */
75001
75002       //int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
75003       this.heap = new Uint16Array(2 * L_CODES$1 + 1);  /* heap used to build the Huffman trees */
75004       zero$1(this.heap);
75005
75006       this.heap_len = 0;               /* number of elements in the heap */
75007       this.heap_max = 0;               /* element of largest frequency */
75008       /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
75009        * The same heap array is used to build all trees.
75010        */
75011
75012       this.depth = new Uint16Array(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1];
75013       zero$1(this.depth);
75014       /* Depth of each subtree used as tie breaker for trees of equal frequency
75015        */
75016
75017       this.l_buf = 0;          /* buffer index for literals or lengths */
75018
75019       this.lit_bufsize = 0;
75020       /* Size of match buffer for literals/lengths.  There are 4 reasons for
75021        * limiting lit_bufsize to 64K:
75022        *   - frequencies can be kept in 16 bit counters
75023        *   - if compression is not successful for the first block, all input
75024        *     data is still in the window so we can still emit a stored block even
75025        *     when input comes from standard input.  (This can also be done for
75026        *     all blocks if lit_bufsize is not greater than 32K.)
75027        *   - if compression is not successful for a file smaller than 64K, we can
75028        *     even emit a stored file instead of a stored block (saving 5 bytes).
75029        *     This is applicable only for zip (not gzip or zlib).
75030        *   - creating new Huffman trees less frequently may not provide fast
75031        *     adaptation to changes in the input data statistics. (Take for
75032        *     example a binary file with poorly compressible code followed by
75033        *     a highly compressible string table.) Smaller buffer sizes give
75034        *     fast adaptation but have of course the overhead of transmitting
75035        *     trees more frequently.
75036        *   - I can't count above 4
75037        */
75038
75039       this.last_lit = 0;      /* running index in l_buf */
75040
75041       this.d_buf = 0;
75042       /* Buffer index for distances. To simplify the code, d_buf and l_buf have
75043        * the same number of elements. To use different lengths, an extra flag
75044        * array would be necessary.
75045        */
75046
75047       this.opt_len = 0;       /* bit length of current block with optimal trees */
75048       this.static_len = 0;    /* bit length of current block with static trees */
75049       this.matches = 0;       /* number of string matches in current block */
75050       this.insert = 0;        /* bytes at end of window left to insert */
75051
75052
75053       this.bi_buf = 0;
75054       /* Output buffer. bits are inserted starting at the bottom (least
75055        * significant bits).
75056        */
75057       this.bi_valid = 0;
75058       /* Number of valid bits in bi_buf.  All bits above the last valid bit
75059        * are always zero.
75060        */
75061
75062       // Used for window memory init. We safely ignore it for JS. That makes
75063       // sense only for pointers and memory check tools.
75064       //this.high_water = 0;
75065       /* High water mark offset in window for initialized bytes -- bytes above
75066        * this are set to zero in order to avoid memory check warnings when
75067        * longest match routines access bytes past the input.  This is then
75068        * updated to the new high water mark.
75069        */
75070     }
75071
75072
75073     const deflateResetKeep = (strm) => {
75074
75075       if (!strm || !strm.state) {
75076         return err(strm, Z_STREAM_ERROR);
75077       }
75078
75079       strm.total_in = strm.total_out = 0;
75080       strm.data_type = Z_UNKNOWN$1;
75081
75082       const s = strm.state;
75083       s.pending = 0;
75084       s.pending_out = 0;
75085
75086       if (s.wrap < 0) {
75087         s.wrap = -s.wrap;
75088         /* was made negative by deflate(..., Z_FINISH); */
75089       }
75090       s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
75091       strm.adler = (s.wrap === 2) ?
75092         0  // crc32(0, Z_NULL, 0)
75093       :
75094         1; // adler32(0, Z_NULL, 0)
75095       s.last_flush = Z_NO_FLUSH;
75096       _tr_init$1(s);
75097       return Z_OK;
75098     };
75099
75100
75101     const deflateReset = (strm) => {
75102
75103       const ret = deflateResetKeep(strm);
75104       if (ret === Z_OK) {
75105         lm_init(strm.state);
75106       }
75107       return ret;
75108     };
75109
75110
75111     const deflateSetHeader = (strm, head) => {
75112
75113       if (!strm || !strm.state) { return Z_STREAM_ERROR; }
75114       if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
75115       strm.state.gzhead = head;
75116       return Z_OK;
75117     };
75118
75119
75120     const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => {
75121
75122       if (!strm) { // === Z_NULL
75123         return Z_STREAM_ERROR;
75124       }
75125       let wrap = 1;
75126
75127       if (level === Z_DEFAULT_COMPRESSION) {
75128         level = 6;
75129       }
75130
75131       if (windowBits < 0) { /* suppress zlib wrapper */
75132         wrap = 0;
75133         windowBits = -windowBits;
75134       }
75135
75136       else if (windowBits > 15) {
75137         wrap = 2;           /* write gzip wrapper instead */
75138         windowBits -= 16;
75139       }
75140
75141
75142       if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
75143         windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
75144         strategy < 0 || strategy > Z_FIXED$1) {
75145         return err(strm, Z_STREAM_ERROR);
75146       }
75147
75148
75149       if (windowBits === 8) {
75150         windowBits = 9;
75151       }
75152       /* until 256-byte window bug fixed */
75153
75154       const s = new DeflateState();
75155
75156       strm.state = s;
75157       s.strm = strm;
75158
75159       s.wrap = wrap;
75160       s.gzhead = null;
75161       s.w_bits = windowBits;
75162       s.w_size = 1 << s.w_bits;
75163       s.w_mask = s.w_size - 1;
75164
75165       s.hash_bits = memLevel + 7;
75166       s.hash_size = 1 << s.hash_bits;
75167       s.hash_mask = s.hash_size - 1;
75168       s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1);
75169
75170       s.window = new Uint8Array(s.w_size * 2);
75171       s.head = new Uint16Array(s.hash_size);
75172       s.prev = new Uint16Array(s.w_size);
75173
75174       // Don't need mem init magic for JS.
75175       //s.high_water = 0;  /* nothing written to s->window yet */
75176
75177       s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
75178
75179       s.pending_buf_size = s.lit_bufsize * 4;
75180
75181       //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
75182       //s->pending_buf = (uchf *) overlay;
75183       s.pending_buf = new Uint8Array(s.pending_buf_size);
75184
75185       // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
75186       //s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
75187       s.d_buf = 1 * s.lit_bufsize;
75188
75189       //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
75190       s.l_buf = (1 + 2) * s.lit_bufsize;
75191
75192       s.level = level;
75193       s.strategy = strategy;
75194       s.method = method;
75195
75196       return deflateReset(strm);
75197     };
75198
75199     const deflateInit = (strm, level) => {
75200
75201       return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
75202     };
75203
75204
75205     const deflate = (strm, flush) => {
75206
75207       let beg, val; // for gzip header write only
75208
75209       if (!strm || !strm.state ||
75210         flush > Z_BLOCK || flush < 0) {
75211         return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
75212       }
75213
75214       const s = strm.state;
75215
75216       if (!strm.output ||
75217           (!strm.input && strm.avail_in !== 0) ||
75218           (s.status === FINISH_STATE && flush !== Z_FINISH)) {
75219         return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
75220       }
75221
75222       s.strm = strm; /* just in case */
75223       const old_flush = s.last_flush;
75224       s.last_flush = flush;
75225
75226       /* Write the header */
75227       if (s.status === INIT_STATE) {
75228
75229         if (s.wrap === 2) { // GZIP header
75230           strm.adler = 0;  //crc32(0L, Z_NULL, 0);
75231           put_byte(s, 31);
75232           put_byte(s, 139);
75233           put_byte(s, 8);
75234           if (!s.gzhead) { // s->gzhead == Z_NULL
75235             put_byte(s, 0);
75236             put_byte(s, 0);
75237             put_byte(s, 0);
75238             put_byte(s, 0);
75239             put_byte(s, 0);
75240             put_byte(s, s.level === 9 ? 2 :
75241                         (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
75242                          4 : 0));
75243             put_byte(s, OS_CODE);
75244             s.status = BUSY_STATE;
75245           }
75246           else {
75247             put_byte(s, (s.gzhead.text ? 1 : 0) +
75248                         (s.gzhead.hcrc ? 2 : 0) +
75249                         (!s.gzhead.extra ? 0 : 4) +
75250                         (!s.gzhead.name ? 0 : 8) +
75251                         (!s.gzhead.comment ? 0 : 16)
75252             );
75253             put_byte(s, s.gzhead.time & 0xff);
75254             put_byte(s, (s.gzhead.time >> 8) & 0xff);
75255             put_byte(s, (s.gzhead.time >> 16) & 0xff);
75256             put_byte(s, (s.gzhead.time >> 24) & 0xff);
75257             put_byte(s, s.level === 9 ? 2 :
75258                         (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
75259                          4 : 0));
75260             put_byte(s, s.gzhead.os & 0xff);
75261             if (s.gzhead.extra && s.gzhead.extra.length) {
75262               put_byte(s, s.gzhead.extra.length & 0xff);
75263               put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
75264             }
75265             if (s.gzhead.hcrc) {
75266               strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);
75267             }
75268             s.gzindex = 0;
75269             s.status = EXTRA_STATE;
75270           }
75271         }
75272         else // DEFLATE header
75273         {
75274           let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
75275           let level_flags = -1;
75276
75277           if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
75278             level_flags = 0;
75279           } else if (s.level < 6) {
75280             level_flags = 1;
75281           } else if (s.level === 6) {
75282             level_flags = 2;
75283           } else {
75284             level_flags = 3;
75285           }
75286           header |= (level_flags << 6);
75287           if (s.strstart !== 0) { header |= PRESET_DICT; }
75288           header += 31 - (header % 31);
75289
75290           s.status = BUSY_STATE;
75291           putShortMSB(s, header);
75292
75293           /* Save the adler32 of the preset dictionary: */
75294           if (s.strstart !== 0) {
75295             putShortMSB(s, strm.adler >>> 16);
75296             putShortMSB(s, strm.adler & 0xffff);
75297           }
75298           strm.adler = 1; // adler32(0L, Z_NULL, 0);
75299         }
75300       }
75301
75302     //#ifdef GZIP
75303       if (s.status === EXTRA_STATE) {
75304         if (s.gzhead.extra/* != Z_NULL*/) {
75305           beg = s.pending;  /* start of bytes to update crc */
75306
75307           while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
75308             if (s.pending === s.pending_buf_size) {
75309               if (s.gzhead.hcrc && s.pending > beg) {
75310                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75311               }
75312               flush_pending(strm);
75313               beg = s.pending;
75314               if (s.pending === s.pending_buf_size) {
75315                 break;
75316               }
75317             }
75318             put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
75319             s.gzindex++;
75320           }
75321           if (s.gzhead.hcrc && s.pending > beg) {
75322             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75323           }
75324           if (s.gzindex === s.gzhead.extra.length) {
75325             s.gzindex = 0;
75326             s.status = NAME_STATE;
75327           }
75328         }
75329         else {
75330           s.status = NAME_STATE;
75331         }
75332       }
75333       if (s.status === NAME_STATE) {
75334         if (s.gzhead.name/* != Z_NULL*/) {
75335           beg = s.pending;  /* start of bytes to update crc */
75336           //int val;
75337
75338           do {
75339             if (s.pending === s.pending_buf_size) {
75340               if (s.gzhead.hcrc && s.pending > beg) {
75341                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75342               }
75343               flush_pending(strm);
75344               beg = s.pending;
75345               if (s.pending === s.pending_buf_size) {
75346                 val = 1;
75347                 break;
75348               }
75349             }
75350             // JS specific: little magic to add zero terminator to end of string
75351             if (s.gzindex < s.gzhead.name.length) {
75352               val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
75353             } else {
75354               val = 0;
75355             }
75356             put_byte(s, val);
75357           } while (val !== 0);
75358
75359           if (s.gzhead.hcrc && s.pending > beg) {
75360             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75361           }
75362           if (val === 0) {
75363             s.gzindex = 0;
75364             s.status = COMMENT_STATE;
75365           }
75366         }
75367         else {
75368           s.status = COMMENT_STATE;
75369         }
75370       }
75371       if (s.status === COMMENT_STATE) {
75372         if (s.gzhead.comment/* != Z_NULL*/) {
75373           beg = s.pending;  /* start of bytes to update crc */
75374           //int val;
75375
75376           do {
75377             if (s.pending === s.pending_buf_size) {
75378               if (s.gzhead.hcrc && s.pending > beg) {
75379                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75380               }
75381               flush_pending(strm);
75382               beg = s.pending;
75383               if (s.pending === s.pending_buf_size) {
75384                 val = 1;
75385                 break;
75386               }
75387             }
75388             // JS specific: little magic to add zero terminator to end of string
75389             if (s.gzindex < s.gzhead.comment.length) {
75390               val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
75391             } else {
75392               val = 0;
75393             }
75394             put_byte(s, val);
75395           } while (val !== 0);
75396
75397           if (s.gzhead.hcrc && s.pending > beg) {
75398             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
75399           }
75400           if (val === 0) {
75401             s.status = HCRC_STATE;
75402           }
75403         }
75404         else {
75405           s.status = HCRC_STATE;
75406         }
75407       }
75408       if (s.status === HCRC_STATE) {
75409         if (s.gzhead.hcrc) {
75410           if (s.pending + 2 > s.pending_buf_size) {
75411             flush_pending(strm);
75412           }
75413           if (s.pending + 2 <= s.pending_buf_size) {
75414             put_byte(s, strm.adler & 0xff);
75415             put_byte(s, (strm.adler >> 8) & 0xff);
75416             strm.adler = 0; //crc32(0L, Z_NULL, 0);
75417             s.status = BUSY_STATE;
75418           }
75419         }
75420         else {
75421           s.status = BUSY_STATE;
75422         }
75423       }
75424     //#endif
75425
75426       /* Flush as much pending output as possible */
75427       if (s.pending !== 0) {
75428         flush_pending(strm);
75429         if (strm.avail_out === 0) {
75430           /* Since avail_out is 0, deflate will be called again with
75431            * more output space, but possibly with both pending and
75432            * avail_in equal to zero. There won't be anything to do,
75433            * but this is not an error situation so make sure we
75434            * return OK instead of BUF_ERROR at next call of deflate:
75435            */
75436           s.last_flush = -1;
75437           return Z_OK;
75438         }
75439
75440         /* Make sure there is something to do and avoid duplicate consecutive
75441          * flushes. For repeated and useless calls with Z_FINISH, we keep
75442          * returning Z_STREAM_END instead of Z_BUF_ERROR.
75443          */
75444       } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
75445         flush !== Z_FINISH) {
75446         return err(strm, Z_BUF_ERROR);
75447       }
75448
75449       /* User must not provide more input after the first FINISH: */
75450       if (s.status === FINISH_STATE && strm.avail_in !== 0) {
75451         return err(strm, Z_BUF_ERROR);
75452       }
75453
75454       /* Start a new block or continue the current one.
75455        */
75456       if (strm.avail_in !== 0 || s.lookahead !== 0 ||
75457         (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
75458         let bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
75459           (s.strategy === Z_RLE ? deflate_rle(s, flush) :
75460             configuration_table[s.level].func(s, flush));
75461
75462         if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
75463           s.status = FINISH_STATE;
75464         }
75465         if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
75466           if (strm.avail_out === 0) {
75467             s.last_flush = -1;
75468             /* avoid BUF_ERROR next call, see above */
75469           }
75470           return Z_OK;
75471           /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
75472            * of deflate should use the same flush parameter to make sure
75473            * that the flush is complete. So we don't have to output an
75474            * empty block here, this will be done at next call. This also
75475            * ensures that for a very small output buffer, we emit at most
75476            * one empty block.
75477            */
75478         }
75479         if (bstate === BS_BLOCK_DONE) {
75480           if (flush === Z_PARTIAL_FLUSH) {
75481             _tr_align$1(s);
75482           }
75483           else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
75484
75485             _tr_stored_block$1(s, 0, 0, false);
75486             /* For a full flush, this empty block will be recognized
75487              * as a special marker by inflate_sync().
75488              */
75489             if (flush === Z_FULL_FLUSH) {
75490               /*** CLEAR_HASH(s); ***/             /* forget history */
75491               zero$1(s.head); // Fill with NIL (= 0);
75492
75493               if (s.lookahead === 0) {
75494                 s.strstart = 0;
75495                 s.block_start = 0;
75496                 s.insert = 0;
75497               }
75498             }
75499           }
75500           flush_pending(strm);
75501           if (strm.avail_out === 0) {
75502             s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
75503             return Z_OK;
75504           }
75505         }
75506       }
75507       //Assert(strm->avail_out > 0, "bug2");
75508       //if (strm.avail_out <= 0) { throw new Error("bug2");}
75509
75510       if (flush !== Z_FINISH) { return Z_OK; }
75511       if (s.wrap <= 0) { return Z_STREAM_END; }
75512
75513       /* Write the trailer */
75514       if (s.wrap === 2) {
75515         put_byte(s, strm.adler & 0xff);
75516         put_byte(s, (strm.adler >> 8) & 0xff);
75517         put_byte(s, (strm.adler >> 16) & 0xff);
75518         put_byte(s, (strm.adler >> 24) & 0xff);
75519         put_byte(s, strm.total_in & 0xff);
75520         put_byte(s, (strm.total_in >> 8) & 0xff);
75521         put_byte(s, (strm.total_in >> 16) & 0xff);
75522         put_byte(s, (strm.total_in >> 24) & 0xff);
75523       }
75524       else
75525       {
75526         putShortMSB(s, strm.adler >>> 16);
75527         putShortMSB(s, strm.adler & 0xffff);
75528       }
75529
75530       flush_pending(strm);
75531       /* If avail_out is zero, the application will call deflate again
75532        * to flush the rest.
75533        */
75534       if (s.wrap > 0) { s.wrap = -s.wrap; }
75535       /* write the trailer only once! */
75536       return s.pending !== 0 ? Z_OK : Z_STREAM_END;
75537     };
75538
75539
75540     const deflateEnd = (strm) => {
75541
75542       if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
75543         return Z_STREAM_ERROR;
75544       }
75545
75546       const status = strm.state.status;
75547       if (status !== INIT_STATE &&
75548         status !== EXTRA_STATE &&
75549         status !== NAME_STATE &&
75550         status !== COMMENT_STATE &&
75551         status !== HCRC_STATE &&
75552         status !== BUSY_STATE &&
75553         status !== FINISH_STATE
75554       ) {
75555         return err(strm, Z_STREAM_ERROR);
75556       }
75557
75558       strm.state = null;
75559
75560       return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
75561     };
75562
75563
75564     /* =========================================================================
75565      * Initializes the compression dictionary from the given byte
75566      * sequence without producing any compressed output.
75567      */
75568     const deflateSetDictionary = (strm, dictionary) => {
75569
75570       let dictLength = dictionary.length;
75571
75572       if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
75573         return Z_STREAM_ERROR;
75574       }
75575
75576       const s = strm.state;
75577       const wrap = s.wrap;
75578
75579       if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
75580         return Z_STREAM_ERROR;
75581       }
75582
75583       /* when using zlib wrappers, compute Adler-32 for provided dictionary */
75584       if (wrap === 1) {
75585         /* adler32(strm->adler, dictionary, dictLength); */
75586         strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);
75587       }
75588
75589       s.wrap = 0;   /* avoid computing Adler-32 in read_buf */
75590
75591       /* if dictionary would fill window, just replace the history */
75592       if (dictLength >= s.w_size) {
75593         if (wrap === 0) {            /* already empty otherwise */
75594           /*** CLEAR_HASH(s); ***/
75595           zero$1(s.head); // Fill with NIL (= 0);
75596           s.strstart = 0;
75597           s.block_start = 0;
75598           s.insert = 0;
75599         }
75600         /* use the tail */
75601         // dictionary = dictionary.slice(dictLength - s.w_size);
75602         let tmpDict = new Uint8Array(s.w_size);
75603         tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0);
75604         dictionary = tmpDict;
75605         dictLength = s.w_size;
75606       }
75607       /* insert dictionary into window and hash */
75608       const avail = strm.avail_in;
75609       const next = strm.next_in;
75610       const input = strm.input;
75611       strm.avail_in = dictLength;
75612       strm.next_in = 0;
75613       strm.input = dictionary;
75614       fill_window(s);
75615       while (s.lookahead >= MIN_MATCH$1) {
75616         let str = s.strstart;
75617         let n = s.lookahead - (MIN_MATCH$1 - 1);
75618         do {
75619           /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
75620           s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH$1 - 1]);
75621
75622           s.prev[str & s.w_mask] = s.head[s.ins_h];
75623
75624           s.head[s.ins_h] = str;
75625           str++;
75626         } while (--n);
75627         s.strstart = str;
75628         s.lookahead = MIN_MATCH$1 - 1;
75629         fill_window(s);
75630       }
75631       s.strstart += s.lookahead;
75632       s.block_start = s.strstart;
75633       s.insert = s.lookahead;
75634       s.lookahead = 0;
75635       s.match_length = s.prev_length = MIN_MATCH$1 - 1;
75636       s.match_available = 0;
75637       strm.next_in = next;
75638       strm.input = input;
75639       strm.avail_in = avail;
75640       s.wrap = wrap;
75641       return Z_OK;
75642     };
75643
75644
75645     var deflateInit_1 = deflateInit;
75646     var deflateInit2_1 = deflateInit2;
75647     var deflateReset_1 = deflateReset;
75648     var deflateResetKeep_1 = deflateResetKeep;
75649     var deflateSetHeader_1 = deflateSetHeader;
75650     var deflate_2 = deflate;
75651     var deflateEnd_1 = deflateEnd;
75652     var deflateSetDictionary_1 = deflateSetDictionary;
75653     var deflateInfo = 'pako deflate (from Nodeca project)';
75654
75655     /* Not implemented
75656     module.exports.deflateBound = deflateBound;
75657     module.exports.deflateCopy = deflateCopy;
75658     module.exports.deflateParams = deflateParams;
75659     module.exports.deflatePending = deflatePending;
75660     module.exports.deflatePrime = deflatePrime;
75661     module.exports.deflateTune = deflateTune;
75662     */
75663
75664     var deflate_1 = {
75665         deflateInit: deflateInit_1,
75666         deflateInit2: deflateInit2_1,
75667         deflateReset: deflateReset_1,
75668         deflateResetKeep: deflateResetKeep_1,
75669         deflateSetHeader: deflateSetHeader_1,
75670         deflate: deflate_2,
75671         deflateEnd: deflateEnd_1,
75672         deflateSetDictionary: deflateSetDictionary_1,
75673         deflateInfo: deflateInfo
75674     };
75675
75676     const _has = (obj, key) => {
75677       return Object.prototype.hasOwnProperty.call(obj, key);
75678     };
75679
75680     var assign = function (obj /*from1, from2, from3, ...*/) {
75681       const sources = Array.prototype.slice.call(arguments, 1);
75682       while (sources.length) {
75683         const source = sources.shift();
75684         if (!source) { continue; }
75685
75686         if (typeof source !== 'object') {
75687           throw new TypeError(source + 'must be non-object');
75688         }
75689
75690         for (const p in source) {
75691           if (_has(source, p)) {
75692             obj[p] = source[p];
75693           }
75694         }
75695       }
75696
75697       return obj;
75698     };
75699
75700
75701     // Join array of chunks to single array.
75702     var flattenChunks = (chunks) => {
75703       // calculate data length
75704       let len = 0;
75705
75706       for (let i = 0, l = chunks.length; i < l; i++) {
75707         len += chunks[i].length;
75708       }
75709
75710       // join chunks
75711       const result = new Uint8Array(len);
75712
75713       for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {
75714         let chunk = chunks[i];
75715         result.set(chunk, pos);
75716         pos += chunk.length;
75717       }
75718
75719       return result;
75720     };
75721
75722     var common = {
75723         assign: assign,
75724         flattenChunks: flattenChunks
75725     };
75726
75727     // String encode/decode helpers
75728
75729
75730     // Quick check if we can use fast array to bin string conversion
75731     //
75732     // - apply(Array) can fail on Android 2.2
75733     // - apply(Uint8Array) can fail on iOS 5.1 Safari
75734     //
75735     let STR_APPLY_UIA_OK = true;
75736
75737     try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
75738
75739
75740     // Table with utf8 lengths (calculated by first byte of sequence)
75741     // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
75742     // because max possible codepoint is 0x10ffff
75743     const _utf8len = new Uint8Array(256);
75744     for (let q = 0; q < 256; q++) {
75745       _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
75746     }
75747     _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
75748
75749
75750     // convert string to array (typed, when possible)
75751     var string2buf = (str) => {
75752       let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
75753
75754       // count binary size
75755       for (m_pos = 0; m_pos < str_len; m_pos++) {
75756         c = str.charCodeAt(m_pos);
75757         if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
75758           c2 = str.charCodeAt(m_pos + 1);
75759           if ((c2 & 0xfc00) === 0xdc00) {
75760             c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
75761             m_pos++;
75762           }
75763         }
75764         buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
75765       }
75766
75767       // allocate buffer
75768       buf = new Uint8Array(buf_len);
75769
75770       // convert
75771       for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
75772         c = str.charCodeAt(m_pos);
75773         if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
75774           c2 = str.charCodeAt(m_pos + 1);
75775           if ((c2 & 0xfc00) === 0xdc00) {
75776             c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
75777             m_pos++;
75778           }
75779         }
75780         if (c < 0x80) {
75781           /* one byte */
75782           buf[i++] = c;
75783         } else if (c < 0x800) {
75784           /* two bytes */
75785           buf[i++] = 0xC0 | (c >>> 6);
75786           buf[i++] = 0x80 | (c & 0x3f);
75787         } else if (c < 0x10000) {
75788           /* three bytes */
75789           buf[i++] = 0xE0 | (c >>> 12);
75790           buf[i++] = 0x80 | (c >>> 6 & 0x3f);
75791           buf[i++] = 0x80 | (c & 0x3f);
75792         } else {
75793           /* four bytes */
75794           buf[i++] = 0xf0 | (c >>> 18);
75795           buf[i++] = 0x80 | (c >>> 12 & 0x3f);
75796           buf[i++] = 0x80 | (c >>> 6 & 0x3f);
75797           buf[i++] = 0x80 | (c & 0x3f);
75798         }
75799       }
75800
75801       return buf;
75802     };
75803
75804     // Helper
75805     const buf2binstring = (buf, len) => {
75806       // On Chrome, the arguments in a function call that are allowed is `65534`.
75807       // If the length of the buffer is smaller than that, we can use this optimization,
75808       // otherwise we will take a slower path.
75809       if (len < 65534) {
75810         if (buf.subarray && STR_APPLY_UIA_OK) {
75811           return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));
75812         }
75813       }
75814
75815       let result = '';
75816       for (let i = 0; i < len; i++) {
75817         result += String.fromCharCode(buf[i]);
75818       }
75819       return result;
75820     };
75821
75822
75823     // convert array to string
75824     var buf2string = (buf, max) => {
75825       let i, out;
75826       const len = max || buf.length;
75827
75828       // Reserve max possible length (2 words per char)
75829       // NB: by unknown reasons, Array is significantly faster for
75830       //     String.fromCharCode.apply than Uint16Array.
75831       const utf16buf = new Array(len * 2);
75832
75833       for (out = 0, i = 0; i < len;) {
75834         let c = buf[i++];
75835         // quick process ascii
75836         if (c < 0x80) { utf16buf[out++] = c; continue; }
75837
75838         let c_len = _utf8len[c];
75839         // skip 5 & 6 byte codes
75840         if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
75841
75842         // apply mask on first byte
75843         c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
75844         // join the rest
75845         while (c_len > 1 && i < len) {
75846           c = (c << 6) | (buf[i++] & 0x3f);
75847           c_len--;
75848         }
75849
75850         // terminated by end of string?
75851         if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
75852
75853         if (c < 0x10000) {
75854           utf16buf[out++] = c;
75855         } else {
75856           c -= 0x10000;
75857           utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
75858           utf16buf[out++] = 0xdc00 | (c & 0x3ff);
75859         }
75860       }
75861
75862       return buf2binstring(utf16buf, out);
75863     };
75864
75865
75866     // Calculate max possible position in utf8 buffer,
75867     // that will not break sequence. If that's not possible
75868     // - (very small limits) return max size as is.
75869     //
75870     // buf[] - utf8 bytes array
75871     // max   - length limit (mandatory);
75872     var utf8border = (buf, max) => {
75873
75874       max = max || buf.length;
75875       if (max > buf.length) { max = buf.length; }
75876
75877       // go back from last position, until start of sequence found
75878       let pos = max - 1;
75879       while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
75880
75881       // Very small and broken sequence,
75882       // return max, because we should return something anyway.
75883       if (pos < 0) { return max; }
75884
75885       // If we came to start of buffer - that means buffer is too small,
75886       // return max too.
75887       if (pos === 0) { return max; }
75888
75889       return (pos + _utf8len[buf[pos]] > max) ? pos : max;
75890     };
75891
75892     var strings = {
75893         string2buf: string2buf,
75894         buf2string: buf2string,
75895         utf8border: utf8border
75896     };
75897
75898     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
75899     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
75900     //
75901     // This software is provided 'as-is', without any express or implied
75902     // warranty. In no event will the authors be held liable for any damages
75903     // arising from the use of this software.
75904     //
75905     // Permission is granted to anyone to use this software for any purpose,
75906     // including commercial applications, and to alter it and redistribute it
75907     // freely, subject to the following restrictions:
75908     //
75909     // 1. The origin of this software must not be misrepresented; you must not
75910     //   claim that you wrote the original software. If you use this software
75911     //   in a product, an acknowledgment in the product documentation would be
75912     //   appreciated but is not required.
75913     // 2. Altered source versions must be plainly marked as such, and must not be
75914     //   misrepresented as being the original software.
75915     // 3. This notice may not be removed or altered from any source distribution.
75916
75917     function ZStream() {
75918       /* next input byte */
75919       this.input = null; // JS specific, because we have no pointers
75920       this.next_in = 0;
75921       /* number of bytes available at input */
75922       this.avail_in = 0;
75923       /* total number of input bytes read so far */
75924       this.total_in = 0;
75925       /* next output byte should be put there */
75926       this.output = null; // JS specific, because we have no pointers
75927       this.next_out = 0;
75928       /* remaining free space at output */
75929       this.avail_out = 0;
75930       /* total number of bytes output so far */
75931       this.total_out = 0;
75932       /* last error message, NULL if no error */
75933       this.msg = ''/*Z_NULL*/;
75934       /* not visible by applications */
75935       this.state = null;
75936       /* best guess about the data type: binary or text */
75937       this.data_type = 2/*Z_UNKNOWN*/;
75938       /* adler32 value of the uncompressed data */
75939       this.adler = 0;
75940     }
75941
75942     var zstream = ZStream;
75943
75944     const toString = Object.prototype.toString;
75945
75946     /* Public constants ==========================================================*/
75947     /* ===========================================================================*/
75948
75949     const {
75950       Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$1,
75951       Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1,
75952       Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1,
75953       Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1,
75954       Z_DEFLATED: Z_DEFLATED$1
75955     } = constants;
75956
75957     /* ===========================================================================*/
75958
75959
75960     /**
75961      * class Deflate
75962      *
75963      * Generic JS-style wrapper for zlib calls. If you don't need
75964      * streaming behaviour - use more simple functions: [[deflate]],
75965      * [[deflateRaw]] and [[gzip]].
75966      **/
75967
75968     /* internal
75969      * Deflate.chunks -> Array
75970      *
75971      * Chunks of output data, if [[Deflate#onData]] not overridden.
75972      **/
75973
75974     /**
75975      * Deflate.result -> Uint8Array
75976      *
75977      * Compressed result, generated by default [[Deflate#onData]]
75978      * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
75979      * (call [[Deflate#push]] with `Z_FINISH` / `true` param).
75980      **/
75981
75982     /**
75983      * Deflate.err -> Number
75984      *
75985      * Error code after deflate finished. 0 (Z_OK) on success.
75986      * You will not need it in real life, because deflate errors
75987      * are possible only on wrong options or bad `onData` / `onEnd`
75988      * custom handlers.
75989      **/
75990
75991     /**
75992      * Deflate.msg -> String
75993      *
75994      * Error message, if [[Deflate.err]] != 0
75995      **/
75996
75997
75998     /**
75999      * new Deflate(options)
76000      * - options (Object): zlib deflate options.
76001      *
76002      * Creates new deflator instance with specified params. Throws exception
76003      * on bad params. Supported options:
76004      *
76005      * - `level`
76006      * - `windowBits`
76007      * - `memLevel`
76008      * - `strategy`
76009      * - `dictionary`
76010      *
76011      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
76012      * for more information on these.
76013      *
76014      * Additional options, for internal needs:
76015      *
76016      * - `chunkSize` - size of generated data chunks (16K by default)
76017      * - `raw` (Boolean) - do raw deflate
76018      * - `gzip` (Boolean) - create gzip wrapper
76019      * - `header` (Object) - custom header for gzip
76020      *   - `text` (Boolean) - true if compressed data believed to be text
76021      *   - `time` (Number) - modification time, unix timestamp
76022      *   - `os` (Number) - operation system code
76023      *   - `extra` (Array) - array of bytes with extra data (max 65536)
76024      *   - `name` (String) - file name (binary string)
76025      *   - `comment` (String) - comment (binary string)
76026      *   - `hcrc` (Boolean) - true if header crc should be added
76027      *
76028      * ##### Example:
76029      *
76030      * ```javascript
76031      * const pako = require('pako')
76032      *   , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
76033      *   , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
76034      *
76035      * const deflate = new pako.Deflate({ level: 3});
76036      *
76037      * deflate.push(chunk1, false);
76038      * deflate.push(chunk2, true);  // true -> last chunk
76039      *
76040      * if (deflate.err) { throw new Error(deflate.err); }
76041      *
76042      * console.log(deflate.result);
76043      * ```
76044      **/
76045     function Deflate(options) {
76046       this.options = common.assign({
76047         level: Z_DEFAULT_COMPRESSION$1,
76048         method: Z_DEFLATED$1,
76049         chunkSize: 16384,
76050         windowBits: 15,
76051         memLevel: 8,
76052         strategy: Z_DEFAULT_STRATEGY$1
76053       }, options || {});
76054
76055       let opt = this.options;
76056
76057       if (opt.raw && (opt.windowBits > 0)) {
76058         opt.windowBits = -opt.windowBits;
76059       }
76060
76061       else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
76062         opt.windowBits += 16;
76063       }
76064
76065       this.err    = 0;      // error code, if happens (0 = Z_OK)
76066       this.msg    = '';     // error message
76067       this.ended  = false;  // used to avoid multiple onEnd() calls
76068       this.chunks = [];     // chunks of compressed data
76069
76070       this.strm = new zstream();
76071       this.strm.avail_out = 0;
76072
76073       let status = deflate_1.deflateInit2(
76074         this.strm,
76075         opt.level,
76076         opt.method,
76077         opt.windowBits,
76078         opt.memLevel,
76079         opt.strategy
76080       );
76081
76082       if (status !== Z_OK$1) {
76083         throw new Error(messages[status]);
76084       }
76085
76086       if (opt.header) {
76087         deflate_1.deflateSetHeader(this.strm, opt.header);
76088       }
76089
76090       if (opt.dictionary) {
76091         let dict;
76092         // Convert data if needed
76093         if (typeof opt.dictionary === 'string') {
76094           // If we need to compress text, change encoding to utf8.
76095           dict = strings.string2buf(opt.dictionary);
76096         } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
76097           dict = new Uint8Array(opt.dictionary);
76098         } else {
76099           dict = opt.dictionary;
76100         }
76101
76102         status = deflate_1.deflateSetDictionary(this.strm, dict);
76103
76104         if (status !== Z_OK$1) {
76105           throw new Error(messages[status]);
76106         }
76107
76108         this._dict_set = true;
76109       }
76110     }
76111
76112     /**
76113      * Deflate#push(data[, flush_mode]) -> Boolean
76114      * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be
76115      *   converted to utf8 byte sequence.
76116      * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
76117      *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
76118      *
76119      * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
76120      * new compressed chunks. Returns `true` on success. The last data block must
76121      * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending
76122      * buffers and call [[Deflate#onEnd]].
76123      *
76124      * On fail call [[Deflate#onEnd]] with error code and return false.
76125      *
76126      * ##### Example
76127      *
76128      * ```javascript
76129      * push(chunk, false); // push one of data chunks
76130      * ...
76131      * push(chunk, true);  // push last chunk
76132      * ```
76133      **/
76134     Deflate.prototype.push = function (data, flush_mode) {
76135       const strm = this.strm;
76136       const chunkSize = this.options.chunkSize;
76137       let status, _flush_mode;
76138
76139       if (this.ended) { return false; }
76140
76141       if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
76142       else _flush_mode = flush_mode === true ? Z_FINISH$1 : Z_NO_FLUSH$1;
76143
76144       // Convert data if needed
76145       if (typeof data === 'string') {
76146         // If we need to compress text, change encoding to utf8.
76147         strm.input = strings.string2buf(data);
76148       } else if (toString.call(data) === '[object ArrayBuffer]') {
76149         strm.input = new Uint8Array(data);
76150       } else {
76151         strm.input = data;
76152       }
76153
76154       strm.next_in = 0;
76155       strm.avail_in = strm.input.length;
76156
76157       for (;;) {
76158         if (strm.avail_out === 0) {
76159           strm.output = new Uint8Array(chunkSize);
76160           strm.next_out = 0;
76161           strm.avail_out = chunkSize;
76162         }
76163
76164         // Make sure avail_out > 6 to avoid repeating markers
76165         if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH$1) && strm.avail_out <= 6) {
76166           this.onData(strm.output.subarray(0, strm.next_out));
76167           strm.avail_out = 0;
76168           continue;
76169         }
76170
76171         status = deflate_1.deflate(strm, _flush_mode);
76172
76173         // Ended => flush and finish
76174         if (status === Z_STREAM_END$1) {
76175           if (strm.next_out > 0) {
76176             this.onData(strm.output.subarray(0, strm.next_out));
76177           }
76178           status = deflate_1.deflateEnd(this.strm);
76179           this.onEnd(status);
76180           this.ended = true;
76181           return status === Z_OK$1;
76182         }
76183
76184         // Flush if out buffer full
76185         if (strm.avail_out === 0) {
76186           this.onData(strm.output);
76187           continue;
76188         }
76189
76190         // Flush if requested and has data
76191         if (_flush_mode > 0 && strm.next_out > 0) {
76192           this.onData(strm.output.subarray(0, strm.next_out));
76193           strm.avail_out = 0;
76194           continue;
76195         }
76196
76197         if (strm.avail_in === 0) break;
76198       }
76199
76200       return true;
76201     };
76202
76203
76204     /**
76205      * Deflate#onData(chunk) -> Void
76206      * - chunk (Uint8Array): output data.
76207      *
76208      * By default, stores data blocks in `chunks[]` property and glue
76209      * those in `onEnd`. Override this handler, if you need another behaviour.
76210      **/
76211     Deflate.prototype.onData = function (chunk) {
76212       this.chunks.push(chunk);
76213     };
76214
76215
76216     /**
76217      * Deflate#onEnd(status) -> Void
76218      * - status (Number): deflate status. 0 (Z_OK) on success,
76219      *   other if not.
76220      *
76221      * Called once after you tell deflate that the input stream is
76222      * complete (Z_FINISH). By default - join collected chunks,
76223      * free memory and fill `results` / `err` properties.
76224      **/
76225     Deflate.prototype.onEnd = function (status) {
76226       // On success - join
76227       if (status === Z_OK$1) {
76228         this.result = common.flattenChunks(this.chunks);
76229       }
76230       this.chunks = [];
76231       this.err = status;
76232       this.msg = this.strm.msg;
76233     };
76234
76235     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
76236     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
76237     //
76238     // This software is provided 'as-is', without any express or implied
76239     // warranty. In no event will the authors be held liable for any damages
76240     // arising from the use of this software.
76241     //
76242     // Permission is granted to anyone to use this software for any purpose,
76243     // including commercial applications, and to alter it and redistribute it
76244     // freely, subject to the following restrictions:
76245     //
76246     // 1. The origin of this software must not be misrepresented; you must not
76247     //   claim that you wrote the original software. If you use this software
76248     //   in a product, an acknowledgment in the product documentation would be
76249     //   appreciated but is not required.
76250     // 2. Altered source versions must be plainly marked as such, and must not be
76251     //   misrepresented as being the original software.
76252     // 3. This notice may not be removed or altered from any source distribution.
76253
76254     // See state defs from inflate.js
76255     const BAD = 30;       /* got a data error -- remain here until reset */
76256     const TYPE = 12;      /* i: waiting for type bits, including last-flag bit */
76257
76258     /*
76259        Decode literal, length, and distance codes and write out the resulting
76260        literal and match bytes until either not enough input or output is
76261        available, an end-of-block is encountered, or a data error is encountered.
76262        When large enough input and output buffers are supplied to inflate(), for
76263        example, a 16K input buffer and a 64K output buffer, more than 95% of the
76264        inflate execution time is spent in this routine.
76265
76266        Entry assumptions:
76267
76268             state.mode === LEN
76269             strm.avail_in >= 6
76270             strm.avail_out >= 258
76271             start >= strm.avail_out
76272             state.bits < 8
76273
76274        On return, state.mode is one of:
76275
76276             LEN -- ran out of enough output space or enough available input
76277             TYPE -- reached end of block code, inflate() to interpret next block
76278             BAD -- error in block data
76279
76280        Notes:
76281
76282         - The maximum input bits used by a length/distance pair is 15 bits for the
76283           length code, 5 bits for the length extra, 15 bits for the distance code,
76284           and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
76285           Therefore if strm.avail_in >= 6, then there is enough input to avoid
76286           checking for available input while decoding.
76287
76288         - The maximum bytes that a single length/distance pair can output is 258
76289           bytes, which is the maximum length that can be coded.  inflate_fast()
76290           requires strm.avail_out >= 258 for each loop to avoid checking for
76291           output space.
76292      */
76293     var inffast = function inflate_fast(strm, start) {
76294       let _in;                    /* local strm.input */
76295       let last;                   /* have enough input while in < last */
76296       let _out;                   /* local strm.output */
76297       let beg;                    /* inflate()'s initial strm.output */
76298       let end;                    /* while out < end, enough space available */
76299     //#ifdef INFLATE_STRICT
76300       let dmax;                   /* maximum distance from zlib header */
76301     //#endif
76302       let wsize;                  /* window size or zero if not using window */
76303       let whave;                  /* valid bytes in the window */
76304       let wnext;                  /* window write index */
76305       // Use `s_window` instead `window`, avoid conflict with instrumentation tools
76306       let s_window;               /* allocated sliding window, if wsize != 0 */
76307       let hold;                   /* local strm.hold */
76308       let bits;                   /* local strm.bits */
76309       let lcode;                  /* local strm.lencode */
76310       let dcode;                  /* local strm.distcode */
76311       let lmask;                  /* mask for first level of length codes */
76312       let dmask;                  /* mask for first level of distance codes */
76313       let here;                   /* retrieved table entry */
76314       let op;                     /* code bits, operation, extra bits, or */
76315                                   /*  window position, window bytes to copy */
76316       let len;                    /* match length, unused bytes */
76317       let dist;                   /* match distance */
76318       let from;                   /* where to copy match from */
76319       let from_source;
76320
76321
76322       let input, output; // JS specific, because we have no pointers
76323
76324       /* copy state to local variables */
76325       const state = strm.state;
76326       //here = state.here;
76327       _in = strm.next_in;
76328       input = strm.input;
76329       last = _in + (strm.avail_in - 5);
76330       _out = strm.next_out;
76331       output = strm.output;
76332       beg = _out - (start - strm.avail_out);
76333       end = _out + (strm.avail_out - 257);
76334     //#ifdef INFLATE_STRICT
76335       dmax = state.dmax;
76336     //#endif
76337       wsize = state.wsize;
76338       whave = state.whave;
76339       wnext = state.wnext;
76340       s_window = state.window;
76341       hold = state.hold;
76342       bits = state.bits;
76343       lcode = state.lencode;
76344       dcode = state.distcode;
76345       lmask = (1 << state.lenbits) - 1;
76346       dmask = (1 << state.distbits) - 1;
76347
76348
76349       /* decode literals and length/distances until end-of-block or not enough
76350          input data or output space */
76351
76352       top:
76353       do {
76354         if (bits < 15) {
76355           hold += input[_in++] << bits;
76356           bits += 8;
76357           hold += input[_in++] << bits;
76358           bits += 8;
76359         }
76360
76361         here = lcode[hold & lmask];
76362
76363         dolen:
76364         for (;;) { // Goto emulation
76365           op = here >>> 24/*here.bits*/;
76366           hold >>>= op;
76367           bits -= op;
76368           op = (here >>> 16) & 0xff/*here.op*/;
76369           if (op === 0) {                          /* literal */
76370             //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
76371             //        "inflate:         literal '%c'\n" :
76372             //        "inflate:         literal 0x%02x\n", here.val));
76373             output[_out++] = here & 0xffff/*here.val*/;
76374           }
76375           else if (op & 16) {                     /* length base */
76376             len = here & 0xffff/*here.val*/;
76377             op &= 15;                           /* number of extra bits */
76378             if (op) {
76379               if (bits < op) {
76380                 hold += input[_in++] << bits;
76381                 bits += 8;
76382               }
76383               len += hold & ((1 << op) - 1);
76384               hold >>>= op;
76385               bits -= op;
76386             }
76387             //Tracevv((stderr, "inflate:         length %u\n", len));
76388             if (bits < 15) {
76389               hold += input[_in++] << bits;
76390               bits += 8;
76391               hold += input[_in++] << bits;
76392               bits += 8;
76393             }
76394             here = dcode[hold & dmask];
76395
76396             dodist:
76397             for (;;) { // goto emulation
76398               op = here >>> 24/*here.bits*/;
76399               hold >>>= op;
76400               bits -= op;
76401               op = (here >>> 16) & 0xff/*here.op*/;
76402
76403               if (op & 16) {                      /* distance base */
76404                 dist = here & 0xffff/*here.val*/;
76405                 op &= 15;                       /* number of extra bits */
76406                 if (bits < op) {
76407                   hold += input[_in++] << bits;
76408                   bits += 8;
76409                   if (bits < op) {
76410                     hold += input[_in++] << bits;
76411                     bits += 8;
76412                   }
76413                 }
76414                 dist += hold & ((1 << op) - 1);
76415     //#ifdef INFLATE_STRICT
76416                 if (dist > dmax) {
76417                   strm.msg = 'invalid distance too far back';
76418                   state.mode = BAD;
76419                   break top;
76420                 }
76421     //#endif
76422                 hold >>>= op;
76423                 bits -= op;
76424                 //Tracevv((stderr, "inflate:         distance %u\n", dist));
76425                 op = _out - beg;                /* max distance in output */
76426                 if (dist > op) {                /* see if copy from window */
76427                   op = dist - op;               /* distance back in window */
76428                   if (op > whave) {
76429                     if (state.sane) {
76430                       strm.msg = 'invalid distance too far back';
76431                       state.mode = BAD;
76432                       break top;
76433                     }
76434
76435     // (!) This block is disabled in zlib defaults,
76436     // don't enable it for binary compatibility
76437     //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
76438     //                if (len <= op - whave) {
76439     //                  do {
76440     //                    output[_out++] = 0;
76441     //                  } while (--len);
76442     //                  continue top;
76443     //                }
76444     //                len -= op - whave;
76445     //                do {
76446     //                  output[_out++] = 0;
76447     //                } while (--op > whave);
76448     //                if (op === 0) {
76449     //                  from = _out - dist;
76450     //                  do {
76451     //                    output[_out++] = output[from++];
76452     //                  } while (--len);
76453     //                  continue top;
76454     //                }
76455     //#endif
76456                   }
76457                   from = 0; // window index
76458                   from_source = s_window;
76459                   if (wnext === 0) {           /* very common case */
76460                     from += wsize - op;
76461                     if (op < len) {         /* some from window */
76462                       len -= op;
76463                       do {
76464                         output[_out++] = s_window[from++];
76465                       } while (--op);
76466                       from = _out - dist;  /* rest from output */
76467                       from_source = output;
76468                     }
76469                   }
76470                   else if (wnext < op) {      /* wrap around window */
76471                     from += wsize + wnext - op;
76472                     op -= wnext;
76473                     if (op < len) {         /* some from end of window */
76474                       len -= op;
76475                       do {
76476                         output[_out++] = s_window[from++];
76477                       } while (--op);
76478                       from = 0;
76479                       if (wnext < len) {  /* some from start of window */
76480                         op = wnext;
76481                         len -= op;
76482                         do {
76483                           output[_out++] = s_window[from++];
76484                         } while (--op);
76485                         from = _out - dist;      /* rest from output */
76486                         from_source = output;
76487                       }
76488                     }
76489                   }
76490                   else {                      /* contiguous in window */
76491                     from += wnext - op;
76492                     if (op < len) {         /* some from window */
76493                       len -= op;
76494                       do {
76495                         output[_out++] = s_window[from++];
76496                       } while (--op);
76497                       from = _out - dist;  /* rest from output */
76498                       from_source = output;
76499                     }
76500                   }
76501                   while (len > 2) {
76502                     output[_out++] = from_source[from++];
76503                     output[_out++] = from_source[from++];
76504                     output[_out++] = from_source[from++];
76505                     len -= 3;
76506                   }
76507                   if (len) {
76508                     output[_out++] = from_source[from++];
76509                     if (len > 1) {
76510                       output[_out++] = from_source[from++];
76511                     }
76512                   }
76513                 }
76514                 else {
76515                   from = _out - dist;          /* copy direct from output */
76516                   do {                        /* minimum length is three */
76517                     output[_out++] = output[from++];
76518                     output[_out++] = output[from++];
76519                     output[_out++] = output[from++];
76520                     len -= 3;
76521                   } while (len > 2);
76522                   if (len) {
76523                     output[_out++] = output[from++];
76524                     if (len > 1) {
76525                       output[_out++] = output[from++];
76526                     }
76527                   }
76528                 }
76529               }
76530               else if ((op & 64) === 0) {          /* 2nd level distance code */
76531                 here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
76532                 continue dodist;
76533               }
76534               else {
76535                 strm.msg = 'invalid distance code';
76536                 state.mode = BAD;
76537                 break top;
76538               }
76539
76540               break; // need to emulate goto via "continue"
76541             }
76542           }
76543           else if ((op & 64) === 0) {              /* 2nd level length code */
76544             here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
76545             continue dolen;
76546           }
76547           else if (op & 32) {                     /* end-of-block */
76548             //Tracevv((stderr, "inflate:         end of block\n"));
76549             state.mode = TYPE;
76550             break top;
76551           }
76552           else {
76553             strm.msg = 'invalid literal/length code';
76554             state.mode = BAD;
76555             break top;
76556           }
76557
76558           break; // need to emulate goto via "continue"
76559         }
76560       } while (_in < last && _out < end);
76561
76562       /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
76563       len = bits >> 3;
76564       _in -= len;
76565       bits -= len << 3;
76566       hold &= (1 << bits) - 1;
76567
76568       /* update state and return */
76569       strm.next_in = _in;
76570       strm.next_out = _out;
76571       strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
76572       strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
76573       state.hold = hold;
76574       state.bits = bits;
76575       return;
76576     };
76577
76578     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
76579     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
76580     //
76581     // This software is provided 'as-is', without any express or implied
76582     // warranty. In no event will the authors be held liable for any damages
76583     // arising from the use of this software.
76584     //
76585     // Permission is granted to anyone to use this software for any purpose,
76586     // including commercial applications, and to alter it and redistribute it
76587     // freely, subject to the following restrictions:
76588     //
76589     // 1. The origin of this software must not be misrepresented; you must not
76590     //   claim that you wrote the original software. If you use this software
76591     //   in a product, an acknowledgment in the product documentation would be
76592     //   appreciated but is not required.
76593     // 2. Altered source versions must be plainly marked as such, and must not be
76594     //   misrepresented as being the original software.
76595     // 3. This notice may not be removed or altered from any source distribution.
76596
76597     const MAXBITS = 15;
76598     const ENOUGH_LENS = 852;
76599     const ENOUGH_DISTS = 592;
76600     //const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
76601
76602     const CODES = 0;
76603     const LENS = 1;
76604     const DISTS = 2;
76605
76606     const lbase = new Uint16Array([ /* Length codes 257..285 base */
76607       3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
76608       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
76609     ]);
76610
76611     const lext = new Uint8Array([ /* Length codes 257..285 extra */
76612       16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
76613       19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
76614     ]);
76615
76616     const dbase = new Uint16Array([ /* Distance codes 0..29 base */
76617       1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
76618       257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
76619       8193, 12289, 16385, 24577, 0, 0
76620     ]);
76621
76622     const dext = new Uint8Array([ /* Distance codes 0..29 extra */
76623       16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
76624       23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
76625       28, 28, 29, 29, 64, 64
76626     ]);
76627
76628     const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>
76629     {
76630       const bits = opts.bits;
76631           //here = opts.here; /* table entry for duplication */
76632
76633       let len = 0;               /* a code's length in bits */
76634       let sym = 0;               /* index of code symbols */
76635       let min = 0, max = 0;          /* minimum and maximum code lengths */
76636       let root = 0;              /* number of index bits for root table */
76637       let curr = 0;              /* number of index bits for current table */
76638       let drop = 0;              /* code bits to drop for sub-table */
76639       let left = 0;                   /* number of prefix codes available */
76640       let used = 0;              /* code entries in table used */
76641       let huff = 0;              /* Huffman code */
76642       let incr;              /* for incrementing code, index */
76643       let fill;              /* index for replicating entries */
76644       let low;               /* low bits for current root entry */
76645       let mask;              /* mask for low root bits */
76646       let next;             /* next available space in table */
76647       let base = null;     /* base value table to use */
76648       let base_index = 0;
76649     //  let shoextra;    /* extra bits table to use */
76650       let end;                    /* use base and extra for symbol > end */
76651       const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */
76652       const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */
76653       let extra = null;
76654       let extra_index = 0;
76655
76656       let here_bits, here_op, here_val;
76657
76658       /*
76659        Process a set of code lengths to create a canonical Huffman code.  The
76660        code lengths are lens[0..codes-1].  Each length corresponds to the
76661        symbols 0..codes-1.  The Huffman code is generated by first sorting the
76662        symbols by length from short to long, and retaining the symbol order
76663        for codes with equal lengths.  Then the code starts with all zero bits
76664        for the first code of the shortest length, and the codes are integer
76665        increments for the same length, and zeros are appended as the length
76666        increases.  For the deflate format, these bits are stored backwards
76667        from their more natural integer increment ordering, and so when the
76668        decoding tables are built in the large loop below, the integer codes
76669        are incremented backwards.
76670
76671        This routine assumes, but does not check, that all of the entries in
76672        lens[] are in the range 0..MAXBITS.  The caller must assure this.
76673        1..MAXBITS is interpreted as that code length.  zero means that that
76674        symbol does not occur in this code.
76675
76676        The codes are sorted by computing a count of codes for each length,
76677        creating from that a table of starting indices for each length in the
76678        sorted table, and then entering the symbols in order in the sorted
76679        table.  The sorted table is work[], with that space being provided by
76680        the caller.
76681
76682        The length counts are used for other purposes as well, i.e. finding
76683        the minimum and maximum length codes, determining if there are any
76684        codes at all, checking for a valid set of lengths, and looking ahead
76685        at length counts to determine sub-table sizes when building the
76686        decoding tables.
76687        */
76688
76689       /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
76690       for (len = 0; len <= MAXBITS; len++) {
76691         count[len] = 0;
76692       }
76693       for (sym = 0; sym < codes; sym++) {
76694         count[lens[lens_index + sym]]++;
76695       }
76696
76697       /* bound code lengths, force root to be within code lengths */
76698       root = bits;
76699       for (max = MAXBITS; max >= 1; max--) {
76700         if (count[max] !== 0) { break; }
76701       }
76702       if (root > max) {
76703         root = max;
76704       }
76705       if (max === 0) {                     /* no symbols to code at all */
76706         //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */
76707         //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;
76708         //table.val[opts.table_index++] = 0;   //here.val = (var short)0;
76709         table[table_index++] = (1 << 24) | (64 << 16) | 0;
76710
76711
76712         //table.op[opts.table_index] = 64;
76713         //table.bits[opts.table_index] = 1;
76714         //table.val[opts.table_index++] = 0;
76715         table[table_index++] = (1 << 24) | (64 << 16) | 0;
76716
76717         opts.bits = 1;
76718         return 0;     /* no symbols, but wait for decoding to report error */
76719       }
76720       for (min = 1; min < max; min++) {
76721         if (count[min] !== 0) { break; }
76722       }
76723       if (root < min) {
76724         root = min;
76725       }
76726
76727       /* check for an over-subscribed or incomplete set of lengths */
76728       left = 1;
76729       for (len = 1; len <= MAXBITS; len++) {
76730         left <<= 1;
76731         left -= count[len];
76732         if (left < 0) {
76733           return -1;
76734         }        /* over-subscribed */
76735       }
76736       if (left > 0 && (type === CODES || max !== 1)) {
76737         return -1;                      /* incomplete set */
76738       }
76739
76740       /* generate offsets into symbol table for each length for sorting */
76741       offs[1] = 0;
76742       for (len = 1; len < MAXBITS; len++) {
76743         offs[len + 1] = offs[len] + count[len];
76744       }
76745
76746       /* sort symbols by length, by symbol order within each length */
76747       for (sym = 0; sym < codes; sym++) {
76748         if (lens[lens_index + sym] !== 0) {
76749           work[offs[lens[lens_index + sym]]++] = sym;
76750         }
76751       }
76752
76753       /*
76754        Create and fill in decoding tables.  In this loop, the table being
76755        filled is at next and has curr index bits.  The code being used is huff
76756        with length len.  That code is converted to an index by dropping drop
76757        bits off of the bottom.  For codes where len is less than drop + curr,
76758        those top drop + curr - len bits are incremented through all values to
76759        fill the table with replicated entries.
76760
76761        root is the number of index bits for the root table.  When len exceeds
76762        root, sub-tables are created pointed to by the root entry with an index
76763        of the low root bits of huff.  This is saved in low to check for when a
76764        new sub-table should be started.  drop is zero when the root table is
76765        being filled, and drop is root when sub-tables are being filled.
76766
76767        When a new sub-table is needed, it is necessary to look ahead in the
76768        code lengths to determine what size sub-table is needed.  The length
76769        counts are used for this, and so count[] is decremented as codes are
76770        entered in the tables.
76771
76772        used keeps track of how many table entries have been allocated from the
76773        provided *table space.  It is checked for LENS and DIST tables against
76774        the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
76775        the initial root table size constants.  See the comments in inftrees.h
76776        for more information.
76777
76778        sym increments through all symbols, and the loop terminates when
76779        all codes of length max, i.e. all codes, have been processed.  This
76780        routine permits incomplete codes, so another loop after this one fills
76781        in the rest of the decoding tables with invalid code markers.
76782        */
76783
76784       /* set up for code type */
76785       // poor man optimization - use if-else instead of switch,
76786       // to avoid deopts in old v8
76787       if (type === CODES) {
76788         base = extra = work;    /* dummy value--not used */
76789         end = 19;
76790
76791       } else if (type === LENS) {
76792         base = lbase;
76793         base_index -= 257;
76794         extra = lext;
76795         extra_index -= 257;
76796         end = 256;
76797
76798       } else {                    /* DISTS */
76799         base = dbase;
76800         extra = dext;
76801         end = -1;
76802       }
76803
76804       /* initialize opts for loop */
76805       huff = 0;                   /* starting code */
76806       sym = 0;                    /* starting code symbol */
76807       len = min;                  /* starting code length */
76808       next = table_index;              /* current table to fill in */
76809       curr = root;                /* current table index bits */
76810       drop = 0;                   /* current bits to drop from code for index */
76811       low = -1;                   /* trigger new sub-table when len > root */
76812       used = 1 << root;          /* use root table entries */
76813       mask = used - 1;            /* mask for comparing low */
76814
76815       /* check available table space */
76816       if ((type === LENS && used > ENOUGH_LENS) ||
76817         (type === DISTS && used > ENOUGH_DISTS)) {
76818         return 1;
76819       }
76820
76821       /* process all codes and make table entries */
76822       for (;;) {
76823         /* create table entry */
76824         here_bits = len - drop;
76825         if (work[sym] < end) {
76826           here_op = 0;
76827           here_val = work[sym];
76828         }
76829         else if (work[sym] > end) {
76830           here_op = extra[extra_index + work[sym]];
76831           here_val = base[base_index + work[sym]];
76832         }
76833         else {
76834           here_op = 32 + 64;         /* end of block */
76835           here_val = 0;
76836         }
76837
76838         /* replicate for those indices with low len bits equal to huff */
76839         incr = 1 << (len - drop);
76840         fill = 1 << curr;
76841         min = fill;                 /* save offset to next table */
76842         do {
76843           fill -= incr;
76844           table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
76845         } while (fill !== 0);
76846
76847         /* backwards increment the len-bit code huff */
76848         incr = 1 << (len - 1);
76849         while (huff & incr) {
76850           incr >>= 1;
76851         }
76852         if (incr !== 0) {
76853           huff &= incr - 1;
76854           huff += incr;
76855         } else {
76856           huff = 0;
76857         }
76858
76859         /* go to next symbol, update count, len */
76860         sym++;
76861         if (--count[len] === 0) {
76862           if (len === max) { break; }
76863           len = lens[lens_index + work[sym]];
76864         }
76865
76866         /* create new sub-table if needed */
76867         if (len > root && (huff & mask) !== low) {
76868           /* if first time, transition to sub-tables */
76869           if (drop === 0) {
76870             drop = root;
76871           }
76872
76873           /* increment past last table */
76874           next += min;            /* here min is 1 << curr */
76875
76876           /* determine length of next table */
76877           curr = len - drop;
76878           left = 1 << curr;
76879           while (curr + drop < max) {
76880             left -= count[curr + drop];
76881             if (left <= 0) { break; }
76882             curr++;
76883             left <<= 1;
76884           }
76885
76886           /* check for enough space */
76887           used += 1 << curr;
76888           if ((type === LENS && used > ENOUGH_LENS) ||
76889             (type === DISTS && used > ENOUGH_DISTS)) {
76890             return 1;
76891           }
76892
76893           /* point entry in root table to sub-table */
76894           low = huff & mask;
76895           /*table.op[low] = curr;
76896           table.bits[low] = root;
76897           table.val[low] = next - opts.table_index;*/
76898           table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
76899         }
76900       }
76901
76902       /* fill in remaining table entry if code is incomplete (guaranteed to have
76903        at most one remaining entry, since if the code is incomplete, the
76904        maximum code length that was allowed to get this far is one bit) */
76905       if (huff !== 0) {
76906         //table.op[next + huff] = 64;            /* invalid code marker */
76907         //table.bits[next + huff] = len - drop;
76908         //table.val[next + huff] = 0;
76909         table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
76910       }
76911
76912       /* set return parameters */
76913       //opts.table_index += used;
76914       opts.bits = root;
76915       return 0;
76916     };
76917
76918
76919     var inftrees = inflate_table;
76920
76921     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
76922     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
76923     //
76924     // This software is provided 'as-is', without any express or implied
76925     // warranty. In no event will the authors be held liable for any damages
76926     // arising from the use of this software.
76927     //
76928     // Permission is granted to anyone to use this software for any purpose,
76929     // including commercial applications, and to alter it and redistribute it
76930     // freely, subject to the following restrictions:
76931     //
76932     // 1. The origin of this software must not be misrepresented; you must not
76933     //   claim that you wrote the original software. If you use this software
76934     //   in a product, an acknowledgment in the product documentation would be
76935     //   appreciated but is not required.
76936     // 2. Altered source versions must be plainly marked as such, and must not be
76937     //   misrepresented as being the original software.
76938     // 3. This notice may not be removed or altered from any source distribution.
76939
76940
76941
76942
76943
76944
76945     const CODES$1 = 0;
76946     const LENS$1 = 1;
76947     const DISTS$1 = 2;
76948
76949     /* Public constants ==========================================================*/
76950     /* ===========================================================================*/
76951
76952     const {
76953       Z_FINISH: Z_FINISH$2, Z_BLOCK: Z_BLOCK$1, Z_TREES,
76954       Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2, Z_NEED_DICT, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR, Z_BUF_ERROR: Z_BUF_ERROR$1,
76955       Z_DEFLATED: Z_DEFLATED$2
76956     } = constants;
76957
76958
76959     /* STATES ====================================================================*/
76960     /* ===========================================================================*/
76961
76962
76963     const    HEAD = 1;       /* i: waiting for magic header */
76964     const    FLAGS = 2;      /* i: waiting for method and flags (gzip) */
76965     const    TIME = 3;       /* i: waiting for modification time (gzip) */
76966     const    OS = 4;         /* i: waiting for extra flags and operating system (gzip) */
76967     const    EXLEN = 5;      /* i: waiting for extra length (gzip) */
76968     const    EXTRA = 6;      /* i: waiting for extra bytes (gzip) */
76969     const    NAME = 7;       /* i: waiting for end of file name (gzip) */
76970     const    COMMENT = 8;    /* i: waiting for end of comment (gzip) */
76971     const    HCRC = 9;       /* i: waiting for header crc (gzip) */
76972     const    DICTID = 10;    /* i: waiting for dictionary check value */
76973     const    DICT = 11;      /* waiting for inflateSetDictionary() call */
76974     const        TYPE$1 = 12;      /* i: waiting for type bits, including last-flag bit */
76975     const        TYPEDO = 13;    /* i: same, but skip check to exit inflate on new block */
76976     const        STORED = 14;    /* i: waiting for stored size (length and complement) */
76977     const        COPY_ = 15;     /* i/o: same as COPY below, but only first time in */
76978     const        COPY = 16;      /* i/o: waiting for input or output to copy stored block */
76979     const        TABLE = 17;     /* i: waiting for dynamic block table lengths */
76980     const        LENLENS = 18;   /* i: waiting for code length code lengths */
76981     const        CODELENS = 19;  /* i: waiting for length/lit and distance code lengths */
76982     const            LEN_ = 20;      /* i: same as LEN below, but only first time in */
76983     const            LEN = 21;       /* i: waiting for length/lit/eob code */
76984     const            LENEXT = 22;    /* i: waiting for length extra bits */
76985     const            DIST = 23;      /* i: waiting for distance code */
76986     const            DISTEXT = 24;   /* i: waiting for distance extra bits */
76987     const            MATCH = 25;     /* o: waiting for output space to copy string */
76988     const            LIT = 26;       /* o: waiting for output space to write literal */
76989     const    CHECK = 27;     /* i: waiting for 32-bit check value */
76990     const    LENGTH = 28;    /* i: waiting for 32-bit length (gzip) */
76991     const    DONE = 29;      /* finished check, done -- remain here until reset */
76992     const    BAD$1 = 30;       /* got a data error -- remain here until reset */
76993     const    MEM = 31;       /* got an inflate() memory error -- remain here until reset */
76994     const    SYNC = 32;      /* looking for synchronization bytes to restart inflate() */
76995
76996     /* ===========================================================================*/
76997
76998
76999
77000     const ENOUGH_LENS$1 = 852;
77001     const ENOUGH_DISTS$1 = 592;
77002     //const ENOUGH =  (ENOUGH_LENS+ENOUGH_DISTS);
77003
77004     const MAX_WBITS$1 = 15;
77005     /* 32K LZ77 window */
77006     const DEF_WBITS = MAX_WBITS$1;
77007
77008
77009     const zswap32 = (q) => {
77010
77011       return  (((q >>> 24) & 0xff) +
77012               ((q >>> 8) & 0xff00) +
77013               ((q & 0xff00) << 8) +
77014               ((q & 0xff) << 24));
77015     };
77016
77017
77018     function InflateState() {
77019       this.mode = 0;             /* current inflate mode */
77020       this.last = false;          /* true if processing last block */
77021       this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
77022       this.havedict = false;      /* true if dictionary provided */
77023       this.flags = 0;             /* gzip header method and flags (0 if zlib) */
77024       this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */
77025       this.check = 0;             /* protected copy of check value */
77026       this.total = 0;             /* protected copy of output count */
77027       // TODO: may be {}
77028       this.head = null;           /* where to save gzip header information */
77029
77030       /* sliding window */
77031       this.wbits = 0;             /* log base 2 of requested window size */
77032       this.wsize = 0;             /* window size or zero if not using window */
77033       this.whave = 0;             /* valid bytes in the window */
77034       this.wnext = 0;             /* window write index */
77035       this.window = null;         /* allocated sliding window, if needed */
77036
77037       /* bit accumulator */
77038       this.hold = 0;              /* input bit accumulator */
77039       this.bits = 0;              /* number of bits in "in" */
77040
77041       /* for string and stored block copying */
77042       this.length = 0;            /* literal or length of data to copy */
77043       this.offset = 0;            /* distance back to copy string from */
77044
77045       /* for table and code decoding */
77046       this.extra = 0;             /* extra bits needed */
77047
77048       /* fixed and dynamic code tables */
77049       this.lencode = null;          /* starting table for length/literal codes */
77050       this.distcode = null;         /* starting table for distance codes */
77051       this.lenbits = 0;           /* index bits for lencode */
77052       this.distbits = 0;          /* index bits for distcode */
77053
77054       /* dynamic table building */
77055       this.ncode = 0;             /* number of code length code lengths */
77056       this.nlen = 0;              /* number of length code lengths */
77057       this.ndist = 0;             /* number of distance code lengths */
77058       this.have = 0;              /* number of code lengths in lens[] */
77059       this.next = null;              /* next available space in codes[] */
77060
77061       this.lens = new Uint16Array(320); /* temporary storage for code lengths */
77062       this.work = new Uint16Array(288); /* work area for code table building */
77063
77064       /*
77065        because we don't have pointers in js, we use lencode and distcode directly
77066        as buffers so we don't need codes
77067       */
77068       //this.codes = new Int32Array(ENOUGH);       /* space for code tables */
77069       this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */
77070       this.distdyn = null;             /* dynamic table for distance codes (JS specific) */
77071       this.sane = 0;                   /* if false, allow invalid distance too far */
77072       this.back = 0;                   /* bits back of last unprocessed length/lit */
77073       this.was = 0;                    /* initial length of match */
77074     }
77075
77076
77077     const inflateResetKeep = (strm) => {
77078
77079       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
77080       const state = strm.state;
77081       strm.total_in = strm.total_out = state.total = 0;
77082       strm.msg = ''; /*Z_NULL*/
77083       if (state.wrap) {       /* to support ill-conceived Java test suite */
77084         strm.adler = state.wrap & 1;
77085       }
77086       state.mode = HEAD;
77087       state.last = 0;
77088       state.havedict = 0;
77089       state.dmax = 32768;
77090       state.head = null/*Z_NULL*/;
77091       state.hold = 0;
77092       state.bits = 0;
77093       //state.lencode = state.distcode = state.next = state.codes;
77094       state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS$1);
77095       state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS$1);
77096
77097       state.sane = 1;
77098       state.back = -1;
77099       //Tracev((stderr, "inflate: reset\n"));
77100       return Z_OK$2;
77101     };
77102
77103
77104     const inflateReset = (strm) => {
77105
77106       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
77107       const state = strm.state;
77108       state.wsize = 0;
77109       state.whave = 0;
77110       state.wnext = 0;
77111       return inflateResetKeep(strm);
77112
77113     };
77114
77115
77116     const inflateReset2 = (strm, windowBits) => {
77117       let wrap;
77118
77119       /* get the state */
77120       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
77121       const state = strm.state;
77122
77123       /* extract wrap request from windowBits parameter */
77124       if (windowBits < 0) {
77125         wrap = 0;
77126         windowBits = -windowBits;
77127       }
77128       else {
77129         wrap = (windowBits >> 4) + 1;
77130         if (windowBits < 48) {
77131           windowBits &= 15;
77132         }
77133       }
77134
77135       /* set number of window bits, free window if different */
77136       if (windowBits && (windowBits < 8 || windowBits > 15)) {
77137         return Z_STREAM_ERROR$1;
77138       }
77139       if (state.window !== null && state.wbits !== windowBits) {
77140         state.window = null;
77141       }
77142
77143       /* update state and reset the rest of it */
77144       state.wrap = wrap;
77145       state.wbits = windowBits;
77146       return inflateReset(strm);
77147     };
77148
77149
77150     const inflateInit2 = (strm, windowBits) => {
77151
77152       if (!strm) { return Z_STREAM_ERROR$1; }
77153       //strm.msg = Z_NULL;                 /* in case we return an error */
77154
77155       const state = new InflateState();
77156
77157       //if (state === Z_NULL) return Z_MEM_ERROR;
77158       //Tracev((stderr, "inflate: allocated\n"));
77159       strm.state = state;
77160       state.window = null/*Z_NULL*/;
77161       const ret = inflateReset2(strm, windowBits);
77162       if (ret !== Z_OK$2) {
77163         strm.state = null/*Z_NULL*/;
77164       }
77165       return ret;
77166     };
77167
77168
77169     const inflateInit = (strm) => {
77170
77171       return inflateInit2(strm, DEF_WBITS);
77172     };
77173
77174
77175     /*
77176      Return state with length and distance decoding tables and index sizes set to
77177      fixed code decoding.  Normally this returns fixed tables from inffixed.h.
77178      If BUILDFIXED is defined, then instead this routine builds the tables the
77179      first time it's called, and returns those tables the first time and
77180      thereafter.  This reduces the size of the code by about 2K bytes, in
77181      exchange for a little execution time.  However, BUILDFIXED should not be
77182      used for threaded applications, since the rewriting of the tables and virgin
77183      may not be thread-safe.
77184      */
77185     let virgin = true;
77186
77187     let lenfix, distfix; // We have no pointers in JS, so keep tables separate
77188
77189
77190     const fixedtables = (state) => {
77191
77192       /* build fixed huffman tables if first call (may not be thread safe) */
77193       if (virgin) {
77194         lenfix = new Int32Array(512);
77195         distfix = new Int32Array(32);
77196
77197         /* literal/length table */
77198         let sym = 0;
77199         while (sym < 144) { state.lens[sym++] = 8; }
77200         while (sym < 256) { state.lens[sym++] = 9; }
77201         while (sym < 280) { state.lens[sym++] = 7; }
77202         while (sym < 288) { state.lens[sym++] = 8; }
77203
77204         inftrees(LENS$1,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });
77205
77206         /* distance table */
77207         sym = 0;
77208         while (sym < 32) { state.lens[sym++] = 5; }
77209
77210         inftrees(DISTS$1, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });
77211
77212         /* do this just once */
77213         virgin = false;
77214       }
77215
77216       state.lencode = lenfix;
77217       state.lenbits = 9;
77218       state.distcode = distfix;
77219       state.distbits = 5;
77220     };
77221
77222
77223     /*
77224      Update the window with the last wsize (normally 32K) bytes written before
77225      returning.  If window does not exist yet, create it.  This is only called
77226      when a window is already in use, or when output has been written during this
77227      inflate call, but the end of the deflate stream has not been reached yet.
77228      It is also called to create a window for dictionary data when a dictionary
77229      is loaded.
77230
77231      Providing output buffers larger than 32K to inflate() should provide a speed
77232      advantage, since only the last 32K of output is copied to the sliding window
77233      upon return from inflate(), and since all distances after the first 32K of
77234      output will fall in the output data, making match copies simpler and faster.
77235      The advantage may be dependent on the size of the processor's data caches.
77236      */
77237     const updatewindow = (strm, src, end, copy) => {
77238
77239       let dist;
77240       const state = strm.state;
77241
77242       /* if it hasn't been done already, allocate space for the window */
77243       if (state.window === null) {
77244         state.wsize = 1 << state.wbits;
77245         state.wnext = 0;
77246         state.whave = 0;
77247
77248         state.window = new Uint8Array(state.wsize);
77249       }
77250
77251       /* copy state->wsize or less output bytes into the circular window */
77252       if (copy >= state.wsize) {
77253         state.window.set(src.subarray(end - state.wsize, end), 0);
77254         state.wnext = 0;
77255         state.whave = state.wsize;
77256       }
77257       else {
77258         dist = state.wsize - state.wnext;
77259         if (dist > copy) {
77260           dist = copy;
77261         }
77262         //zmemcpy(state->window + state->wnext, end - copy, dist);
77263         state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);
77264         copy -= dist;
77265         if (copy) {
77266           //zmemcpy(state->window, end - copy, copy);
77267           state.window.set(src.subarray(end - copy, end), 0);
77268           state.wnext = copy;
77269           state.whave = state.wsize;
77270         }
77271         else {
77272           state.wnext += dist;
77273           if (state.wnext === state.wsize) { state.wnext = 0; }
77274           if (state.whave < state.wsize) { state.whave += dist; }
77275         }
77276       }
77277       return 0;
77278     };
77279
77280
77281     const inflate = (strm, flush) => {
77282
77283       let state;
77284       let input, output;          // input/output buffers
77285       let next;                   /* next input INDEX */
77286       let put;                    /* next output INDEX */
77287       let have, left;             /* available input and output */
77288       let hold;                   /* bit buffer */
77289       let bits;                   /* bits in bit buffer */
77290       let _in, _out;              /* save starting available input and output */
77291       let copy;                   /* number of stored or match bytes to copy */
77292       let from;                   /* where to copy match bytes from */
77293       let from_source;
77294       let here = 0;               /* current decoding table entry */
77295       let here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
77296       //let last;                   /* parent table entry */
77297       let last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
77298       let len;                    /* length to copy for repeats, bits to drop */
77299       let ret;                    /* return code */
77300       const hbuf = new Uint8Array(4);    /* buffer for gzip header crc calculation */
77301       let opts;
77302
77303       let n; // temporary variable for NEED_BITS
77304
77305       const order = /* permutation of code lengths */
77306         new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);
77307
77308
77309       if (!strm || !strm.state || !strm.output ||
77310           (!strm.input && strm.avail_in !== 0)) {
77311         return Z_STREAM_ERROR$1;
77312       }
77313
77314       state = strm.state;
77315       if (state.mode === TYPE$1) { state.mode = TYPEDO; }    /* skip check */
77316
77317
77318       //--- LOAD() ---
77319       put = strm.next_out;
77320       output = strm.output;
77321       left = strm.avail_out;
77322       next = strm.next_in;
77323       input = strm.input;
77324       have = strm.avail_in;
77325       hold = state.hold;
77326       bits = state.bits;
77327       //---
77328
77329       _in = have;
77330       _out = left;
77331       ret = Z_OK$2;
77332
77333       inf_leave: // goto emulation
77334       for (;;) {
77335         switch (state.mode) {
77336           case HEAD:
77337             if (state.wrap === 0) {
77338               state.mode = TYPEDO;
77339               break;
77340             }
77341             //=== NEEDBITS(16);
77342             while (bits < 16) {
77343               if (have === 0) { break inf_leave; }
77344               have--;
77345               hold += input[next++] << bits;
77346               bits += 8;
77347             }
77348             //===//
77349             if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */
77350               state.check = 0/*crc32(0L, Z_NULL, 0)*/;
77351               //=== CRC2(state.check, hold);
77352               hbuf[0] = hold & 0xff;
77353               hbuf[1] = (hold >>> 8) & 0xff;
77354               state.check = crc32_1(state.check, hbuf, 2, 0);
77355               //===//
77356
77357               //=== INITBITS();
77358               hold = 0;
77359               bits = 0;
77360               //===//
77361               state.mode = FLAGS;
77362               break;
77363             }
77364             state.flags = 0;           /* expect zlib header */
77365             if (state.head) {
77366               state.head.done = false;
77367             }
77368             if (!(state.wrap & 1) ||   /* check if zlib header allowed */
77369               (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
77370               strm.msg = 'incorrect header check';
77371               state.mode = BAD$1;
77372               break;
77373             }
77374             if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED$2) {
77375               strm.msg = 'unknown compression method';
77376               state.mode = BAD$1;
77377               break;
77378             }
77379             //--- DROPBITS(4) ---//
77380             hold >>>= 4;
77381             bits -= 4;
77382             //---//
77383             len = (hold & 0x0f)/*BITS(4)*/ + 8;
77384             if (state.wbits === 0) {
77385               state.wbits = len;
77386             }
77387             else if (len > state.wbits) {
77388               strm.msg = 'invalid window size';
77389               state.mode = BAD$1;
77390               break;
77391             }
77392
77393             // !!! pako patch. Force use `options.windowBits` if passed.
77394             // Required to always use max window size by default.
77395             state.dmax = 1 << state.wbits;
77396             //state.dmax = 1 << len;
77397
77398             //Tracev((stderr, "inflate:   zlib header ok\n"));
77399             strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
77400             state.mode = hold & 0x200 ? DICTID : TYPE$1;
77401             //=== INITBITS();
77402             hold = 0;
77403             bits = 0;
77404             //===//
77405             break;
77406           case FLAGS:
77407             //=== NEEDBITS(16); */
77408             while (bits < 16) {
77409               if (have === 0) { break inf_leave; }
77410               have--;
77411               hold += input[next++] << bits;
77412               bits += 8;
77413             }
77414             //===//
77415             state.flags = hold;
77416             if ((state.flags & 0xff) !== Z_DEFLATED$2) {
77417               strm.msg = 'unknown compression method';
77418               state.mode = BAD$1;
77419               break;
77420             }
77421             if (state.flags & 0xe000) {
77422               strm.msg = 'unknown header flags set';
77423               state.mode = BAD$1;
77424               break;
77425             }
77426             if (state.head) {
77427               state.head.text = ((hold >> 8) & 1);
77428             }
77429             if (state.flags & 0x0200) {
77430               //=== CRC2(state.check, hold);
77431               hbuf[0] = hold & 0xff;
77432               hbuf[1] = (hold >>> 8) & 0xff;
77433               state.check = crc32_1(state.check, hbuf, 2, 0);
77434               //===//
77435             }
77436             //=== INITBITS();
77437             hold = 0;
77438             bits = 0;
77439             //===//
77440             state.mode = TIME;
77441             /* falls through */
77442           case TIME:
77443             //=== NEEDBITS(32); */
77444             while (bits < 32) {
77445               if (have === 0) { break inf_leave; }
77446               have--;
77447               hold += input[next++] << bits;
77448               bits += 8;
77449             }
77450             //===//
77451             if (state.head) {
77452               state.head.time = hold;
77453             }
77454             if (state.flags & 0x0200) {
77455               //=== CRC4(state.check, hold)
77456               hbuf[0] = hold & 0xff;
77457               hbuf[1] = (hold >>> 8) & 0xff;
77458               hbuf[2] = (hold >>> 16) & 0xff;
77459               hbuf[3] = (hold >>> 24) & 0xff;
77460               state.check = crc32_1(state.check, hbuf, 4, 0);
77461               //===
77462             }
77463             //=== INITBITS();
77464             hold = 0;
77465             bits = 0;
77466             //===//
77467             state.mode = OS;
77468             /* falls through */
77469           case OS:
77470             //=== NEEDBITS(16); */
77471             while (bits < 16) {
77472               if (have === 0) { break inf_leave; }
77473               have--;
77474               hold += input[next++] << bits;
77475               bits += 8;
77476             }
77477             //===//
77478             if (state.head) {
77479               state.head.xflags = (hold & 0xff);
77480               state.head.os = (hold >> 8);
77481             }
77482             if (state.flags & 0x0200) {
77483               //=== CRC2(state.check, hold);
77484               hbuf[0] = hold & 0xff;
77485               hbuf[1] = (hold >>> 8) & 0xff;
77486               state.check = crc32_1(state.check, hbuf, 2, 0);
77487               //===//
77488             }
77489             //=== INITBITS();
77490             hold = 0;
77491             bits = 0;
77492             //===//
77493             state.mode = EXLEN;
77494             /* falls through */
77495           case EXLEN:
77496             if (state.flags & 0x0400) {
77497               //=== NEEDBITS(16); */
77498               while (bits < 16) {
77499                 if (have === 0) { break inf_leave; }
77500                 have--;
77501                 hold += input[next++] << bits;
77502                 bits += 8;
77503               }
77504               //===//
77505               state.length = hold;
77506               if (state.head) {
77507                 state.head.extra_len = hold;
77508               }
77509               if (state.flags & 0x0200) {
77510                 //=== CRC2(state.check, hold);
77511                 hbuf[0] = hold & 0xff;
77512                 hbuf[1] = (hold >>> 8) & 0xff;
77513                 state.check = crc32_1(state.check, hbuf, 2, 0);
77514                 //===//
77515               }
77516               //=== INITBITS();
77517               hold = 0;
77518               bits = 0;
77519               //===//
77520             }
77521             else if (state.head) {
77522               state.head.extra = null/*Z_NULL*/;
77523             }
77524             state.mode = EXTRA;
77525             /* falls through */
77526           case EXTRA:
77527             if (state.flags & 0x0400) {
77528               copy = state.length;
77529               if (copy > have) { copy = have; }
77530               if (copy) {
77531                 if (state.head) {
77532                   len = state.head.extra_len - state.length;
77533                   if (!state.head.extra) {
77534                     // Use untyped array for more convenient processing later
77535                     state.head.extra = new Uint8Array(state.head.extra_len);
77536                   }
77537                   state.head.extra.set(
77538                     input.subarray(
77539                       next,
77540                       // extra field is limited to 65536 bytes
77541                       // - no need for additional size check
77542                       next + copy
77543                     ),
77544                     /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
77545                     len
77546                   );
77547                   //zmemcpy(state.head.extra + len, next,
77548                   //        len + copy > state.head.extra_max ?
77549                   //        state.head.extra_max - len : copy);
77550                 }
77551                 if (state.flags & 0x0200) {
77552                   state.check = crc32_1(state.check, input, copy, next);
77553                 }
77554                 have -= copy;
77555                 next += copy;
77556                 state.length -= copy;
77557               }
77558               if (state.length) { break inf_leave; }
77559             }
77560             state.length = 0;
77561             state.mode = NAME;
77562             /* falls through */
77563           case NAME:
77564             if (state.flags & 0x0800) {
77565               if (have === 0) { break inf_leave; }
77566               copy = 0;
77567               do {
77568                 // TODO: 2 or 1 bytes?
77569                 len = input[next + copy++];
77570                 /* use constant limit because in js we should not preallocate memory */
77571                 if (state.head && len &&
77572                     (state.length < 65536 /*state.head.name_max*/)) {
77573                   state.head.name += String.fromCharCode(len);
77574                 }
77575               } while (len && copy < have);
77576
77577               if (state.flags & 0x0200) {
77578                 state.check = crc32_1(state.check, input, copy, next);
77579               }
77580               have -= copy;
77581               next += copy;
77582               if (len) { break inf_leave; }
77583             }
77584             else if (state.head) {
77585               state.head.name = null;
77586             }
77587             state.length = 0;
77588             state.mode = COMMENT;
77589             /* falls through */
77590           case COMMENT:
77591             if (state.flags & 0x1000) {
77592               if (have === 0) { break inf_leave; }
77593               copy = 0;
77594               do {
77595                 len = input[next + copy++];
77596                 /* use constant limit because in js we should not preallocate memory */
77597                 if (state.head && len &&
77598                     (state.length < 65536 /*state.head.comm_max*/)) {
77599                   state.head.comment += String.fromCharCode(len);
77600                 }
77601               } while (len && copy < have);
77602               if (state.flags & 0x0200) {
77603                 state.check = crc32_1(state.check, input, copy, next);
77604               }
77605               have -= copy;
77606               next += copy;
77607               if (len) { break inf_leave; }
77608             }
77609             else if (state.head) {
77610               state.head.comment = null;
77611             }
77612             state.mode = HCRC;
77613             /* falls through */
77614           case HCRC:
77615             if (state.flags & 0x0200) {
77616               //=== NEEDBITS(16); */
77617               while (bits < 16) {
77618                 if (have === 0) { break inf_leave; }
77619                 have--;
77620                 hold += input[next++] << bits;
77621                 bits += 8;
77622               }
77623               //===//
77624               if (hold !== (state.check & 0xffff)) {
77625                 strm.msg = 'header crc mismatch';
77626                 state.mode = BAD$1;
77627                 break;
77628               }
77629               //=== INITBITS();
77630               hold = 0;
77631               bits = 0;
77632               //===//
77633             }
77634             if (state.head) {
77635               state.head.hcrc = ((state.flags >> 9) & 1);
77636               state.head.done = true;
77637             }
77638             strm.adler = state.check = 0;
77639             state.mode = TYPE$1;
77640             break;
77641           case DICTID:
77642             //=== NEEDBITS(32); */
77643             while (bits < 32) {
77644               if (have === 0) { break inf_leave; }
77645               have--;
77646               hold += input[next++] << bits;
77647               bits += 8;
77648             }
77649             //===//
77650             strm.adler = state.check = zswap32(hold);
77651             //=== INITBITS();
77652             hold = 0;
77653             bits = 0;
77654             //===//
77655             state.mode = DICT;
77656             /* falls through */
77657           case DICT:
77658             if (state.havedict === 0) {
77659               //--- RESTORE() ---
77660               strm.next_out = put;
77661               strm.avail_out = left;
77662               strm.next_in = next;
77663               strm.avail_in = have;
77664               state.hold = hold;
77665               state.bits = bits;
77666               //---
77667               return Z_NEED_DICT;
77668             }
77669             strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
77670             state.mode = TYPE$1;
77671             /* falls through */
77672           case TYPE$1:
77673             if (flush === Z_BLOCK$1 || flush === Z_TREES) { break inf_leave; }
77674             /* falls through */
77675           case TYPEDO:
77676             if (state.last) {
77677               //--- BYTEBITS() ---//
77678               hold >>>= bits & 7;
77679               bits -= bits & 7;
77680               //---//
77681               state.mode = CHECK;
77682               break;
77683             }
77684             //=== NEEDBITS(3); */
77685             while (bits < 3) {
77686               if (have === 0) { break inf_leave; }
77687               have--;
77688               hold += input[next++] << bits;
77689               bits += 8;
77690             }
77691             //===//
77692             state.last = (hold & 0x01)/*BITS(1)*/;
77693             //--- DROPBITS(1) ---//
77694             hold >>>= 1;
77695             bits -= 1;
77696             //---//
77697
77698             switch ((hold & 0x03)/*BITS(2)*/) {
77699               case 0:                             /* stored block */
77700                 //Tracev((stderr, "inflate:     stored block%s\n",
77701                 //        state.last ? " (last)" : ""));
77702                 state.mode = STORED;
77703                 break;
77704               case 1:                             /* fixed block */
77705                 fixedtables(state);
77706                 //Tracev((stderr, "inflate:     fixed codes block%s\n",
77707                 //        state.last ? " (last)" : ""));
77708                 state.mode = LEN_;             /* decode codes */
77709                 if (flush === Z_TREES) {
77710                   //--- DROPBITS(2) ---//
77711                   hold >>>= 2;
77712                   bits -= 2;
77713                   //---//
77714                   break inf_leave;
77715                 }
77716                 break;
77717               case 2:                             /* dynamic block */
77718                 //Tracev((stderr, "inflate:     dynamic codes block%s\n",
77719                 //        state.last ? " (last)" : ""));
77720                 state.mode = TABLE;
77721                 break;
77722               case 3:
77723                 strm.msg = 'invalid block type';
77724                 state.mode = BAD$1;
77725             }
77726             //--- DROPBITS(2) ---//
77727             hold >>>= 2;
77728             bits -= 2;
77729             //---//
77730             break;
77731           case STORED:
77732             //--- BYTEBITS() ---// /* go to byte boundary */
77733             hold >>>= bits & 7;
77734             bits -= bits & 7;
77735             //---//
77736             //=== NEEDBITS(32); */
77737             while (bits < 32) {
77738               if (have === 0) { break inf_leave; }
77739               have--;
77740               hold += input[next++] << bits;
77741               bits += 8;
77742             }
77743             //===//
77744             if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
77745               strm.msg = 'invalid stored block lengths';
77746               state.mode = BAD$1;
77747               break;
77748             }
77749             state.length = hold & 0xffff;
77750             //Tracev((stderr, "inflate:       stored length %u\n",
77751             //        state.length));
77752             //=== INITBITS();
77753             hold = 0;
77754             bits = 0;
77755             //===//
77756             state.mode = COPY_;
77757             if (flush === Z_TREES) { break inf_leave; }
77758             /* falls through */
77759           case COPY_:
77760             state.mode = COPY;
77761             /* falls through */
77762           case COPY:
77763             copy = state.length;
77764             if (copy) {
77765               if (copy > have) { copy = have; }
77766               if (copy > left) { copy = left; }
77767               if (copy === 0) { break inf_leave; }
77768               //--- zmemcpy(put, next, copy); ---
77769               output.set(input.subarray(next, next + copy), put);
77770               //---//
77771               have -= copy;
77772               next += copy;
77773               left -= copy;
77774               put += copy;
77775               state.length -= copy;
77776               break;
77777             }
77778             //Tracev((stderr, "inflate:       stored end\n"));
77779             state.mode = TYPE$1;
77780             break;
77781           case TABLE:
77782             //=== NEEDBITS(14); */
77783             while (bits < 14) {
77784               if (have === 0) { break inf_leave; }
77785               have--;
77786               hold += input[next++] << bits;
77787               bits += 8;
77788             }
77789             //===//
77790             state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
77791             //--- DROPBITS(5) ---//
77792             hold >>>= 5;
77793             bits -= 5;
77794             //---//
77795             state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
77796             //--- DROPBITS(5) ---//
77797             hold >>>= 5;
77798             bits -= 5;
77799             //---//
77800             state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
77801             //--- DROPBITS(4) ---//
77802             hold >>>= 4;
77803             bits -= 4;
77804             //---//
77805     //#ifndef PKZIP_BUG_WORKAROUND
77806             if (state.nlen > 286 || state.ndist > 30) {
77807               strm.msg = 'too many length or distance symbols';
77808               state.mode = BAD$1;
77809               break;
77810             }
77811     //#endif
77812             //Tracev((stderr, "inflate:       table sizes ok\n"));
77813             state.have = 0;
77814             state.mode = LENLENS;
77815             /* falls through */
77816           case LENLENS:
77817             while (state.have < state.ncode) {
77818               //=== NEEDBITS(3);
77819               while (bits < 3) {
77820                 if (have === 0) { break inf_leave; }
77821                 have--;
77822                 hold += input[next++] << bits;
77823                 bits += 8;
77824               }
77825               //===//
77826               state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
77827               //--- DROPBITS(3) ---//
77828               hold >>>= 3;
77829               bits -= 3;
77830               //---//
77831             }
77832             while (state.have < 19) {
77833               state.lens[order[state.have++]] = 0;
77834             }
77835             // We have separate tables & no pointers. 2 commented lines below not needed.
77836             //state.next = state.codes;
77837             //state.lencode = state.next;
77838             // Switch to use dynamic table
77839             state.lencode = state.lendyn;
77840             state.lenbits = 7;
77841
77842             opts = { bits: state.lenbits };
77843             ret = inftrees(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts);
77844             state.lenbits = opts.bits;
77845
77846             if (ret) {
77847               strm.msg = 'invalid code lengths set';
77848               state.mode = BAD$1;
77849               break;
77850             }
77851             //Tracev((stderr, "inflate:       code lengths ok\n"));
77852             state.have = 0;
77853             state.mode = CODELENS;
77854             /* falls through */
77855           case CODELENS:
77856             while (state.have < state.nlen + state.ndist) {
77857               for (;;) {
77858                 here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
77859                 here_bits = here >>> 24;
77860                 here_op = (here >>> 16) & 0xff;
77861                 here_val = here & 0xffff;
77862
77863                 if ((here_bits) <= bits) { break; }
77864                 //--- PULLBYTE() ---//
77865                 if (have === 0) { break inf_leave; }
77866                 have--;
77867                 hold += input[next++] << bits;
77868                 bits += 8;
77869                 //---//
77870               }
77871               if (here_val < 16) {
77872                 //--- DROPBITS(here.bits) ---//
77873                 hold >>>= here_bits;
77874                 bits -= here_bits;
77875                 //---//
77876                 state.lens[state.have++] = here_val;
77877               }
77878               else {
77879                 if (here_val === 16) {
77880                   //=== NEEDBITS(here.bits + 2);
77881                   n = here_bits + 2;
77882                   while (bits < n) {
77883                     if (have === 0) { break inf_leave; }
77884                     have--;
77885                     hold += input[next++] << bits;
77886                     bits += 8;
77887                   }
77888                   //===//
77889                   //--- DROPBITS(here.bits) ---//
77890                   hold >>>= here_bits;
77891                   bits -= here_bits;
77892                   //---//
77893                   if (state.have === 0) {
77894                     strm.msg = 'invalid bit length repeat';
77895                     state.mode = BAD$1;
77896                     break;
77897                   }
77898                   len = state.lens[state.have - 1];
77899                   copy = 3 + (hold & 0x03);//BITS(2);
77900                   //--- DROPBITS(2) ---//
77901                   hold >>>= 2;
77902                   bits -= 2;
77903                   //---//
77904                 }
77905                 else if (here_val === 17) {
77906                   //=== NEEDBITS(here.bits + 3);
77907                   n = here_bits + 3;
77908                   while (bits < n) {
77909                     if (have === 0) { break inf_leave; }
77910                     have--;
77911                     hold += input[next++] << bits;
77912                     bits += 8;
77913                   }
77914                   //===//
77915                   //--- DROPBITS(here.bits) ---//
77916                   hold >>>= here_bits;
77917                   bits -= here_bits;
77918                   //---//
77919                   len = 0;
77920                   copy = 3 + (hold & 0x07);//BITS(3);
77921                   //--- DROPBITS(3) ---//
77922                   hold >>>= 3;
77923                   bits -= 3;
77924                   //---//
77925                 }
77926                 else {
77927                   //=== NEEDBITS(here.bits + 7);
77928                   n = here_bits + 7;
77929                   while (bits < n) {
77930                     if (have === 0) { break inf_leave; }
77931                     have--;
77932                     hold += input[next++] << bits;
77933                     bits += 8;
77934                   }
77935                   //===//
77936                   //--- DROPBITS(here.bits) ---//
77937                   hold >>>= here_bits;
77938                   bits -= here_bits;
77939                   //---//
77940                   len = 0;
77941                   copy = 11 + (hold & 0x7f);//BITS(7);
77942                   //--- DROPBITS(7) ---//
77943                   hold >>>= 7;
77944                   bits -= 7;
77945                   //---//
77946                 }
77947                 if (state.have + copy > state.nlen + state.ndist) {
77948                   strm.msg = 'invalid bit length repeat';
77949                   state.mode = BAD$1;
77950                   break;
77951                 }
77952                 while (copy--) {
77953                   state.lens[state.have++] = len;
77954                 }
77955               }
77956             }
77957
77958             /* handle error breaks in while */
77959             if (state.mode === BAD$1) { break; }
77960
77961             /* check for end-of-block code (better have one) */
77962             if (state.lens[256] === 0) {
77963               strm.msg = 'invalid code -- missing end-of-block';
77964               state.mode = BAD$1;
77965               break;
77966             }
77967
77968             /* build code tables -- note: do not change the lenbits or distbits
77969                values here (9 and 6) without reading the comments in inftrees.h
77970                concerning the ENOUGH constants, which depend on those values */
77971             state.lenbits = 9;
77972
77973             opts = { bits: state.lenbits };
77974             ret = inftrees(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
77975             // We have separate tables & no pointers. 2 commented lines below not needed.
77976             // state.next_index = opts.table_index;
77977             state.lenbits = opts.bits;
77978             // state.lencode = state.next;
77979
77980             if (ret) {
77981               strm.msg = 'invalid literal/lengths set';
77982               state.mode = BAD$1;
77983               break;
77984             }
77985
77986             state.distbits = 6;
77987             //state.distcode.copy(state.codes);
77988             // Switch to use dynamic table
77989             state.distcode = state.distdyn;
77990             opts = { bits: state.distbits };
77991             ret = inftrees(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
77992             // We have separate tables & no pointers. 2 commented lines below not needed.
77993             // state.next_index = opts.table_index;
77994             state.distbits = opts.bits;
77995             // state.distcode = state.next;
77996
77997             if (ret) {
77998               strm.msg = 'invalid distances set';
77999               state.mode = BAD$1;
78000               break;
78001             }
78002             //Tracev((stderr, 'inflate:       codes ok\n'));
78003             state.mode = LEN_;
78004             if (flush === Z_TREES) { break inf_leave; }
78005             /* falls through */
78006           case LEN_:
78007             state.mode = LEN;
78008             /* falls through */
78009           case LEN:
78010             if (have >= 6 && left >= 258) {
78011               //--- RESTORE() ---
78012               strm.next_out = put;
78013               strm.avail_out = left;
78014               strm.next_in = next;
78015               strm.avail_in = have;
78016               state.hold = hold;
78017               state.bits = bits;
78018               //---
78019               inffast(strm, _out);
78020               //--- LOAD() ---
78021               put = strm.next_out;
78022               output = strm.output;
78023               left = strm.avail_out;
78024               next = strm.next_in;
78025               input = strm.input;
78026               have = strm.avail_in;
78027               hold = state.hold;
78028               bits = state.bits;
78029               //---
78030
78031               if (state.mode === TYPE$1) {
78032                 state.back = -1;
78033               }
78034               break;
78035             }
78036             state.back = 0;
78037             for (;;) {
78038               here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/
78039               here_bits = here >>> 24;
78040               here_op = (here >>> 16) & 0xff;
78041               here_val = here & 0xffff;
78042
78043               if (here_bits <= bits) { break; }
78044               //--- PULLBYTE() ---//
78045               if (have === 0) { break inf_leave; }
78046               have--;
78047               hold += input[next++] << bits;
78048               bits += 8;
78049               //---//
78050             }
78051             if (here_op && (here_op & 0xf0) === 0) {
78052               last_bits = here_bits;
78053               last_op = here_op;
78054               last_val = here_val;
78055               for (;;) {
78056                 here = state.lencode[last_val +
78057                         ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
78058                 here_bits = here >>> 24;
78059                 here_op = (here >>> 16) & 0xff;
78060                 here_val = here & 0xffff;
78061
78062                 if ((last_bits + here_bits) <= bits) { break; }
78063                 //--- PULLBYTE() ---//
78064                 if (have === 0) { break inf_leave; }
78065                 have--;
78066                 hold += input[next++] << bits;
78067                 bits += 8;
78068                 //---//
78069               }
78070               //--- DROPBITS(last.bits) ---//
78071               hold >>>= last_bits;
78072               bits -= last_bits;
78073               //---//
78074               state.back += last_bits;
78075             }
78076             //--- DROPBITS(here.bits) ---//
78077             hold >>>= here_bits;
78078             bits -= here_bits;
78079             //---//
78080             state.back += here_bits;
78081             state.length = here_val;
78082             if (here_op === 0) {
78083               //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
78084               //        "inflate:         literal '%c'\n" :
78085               //        "inflate:         literal 0x%02x\n", here.val));
78086               state.mode = LIT;
78087               break;
78088             }
78089             if (here_op & 32) {
78090               //Tracevv((stderr, "inflate:         end of block\n"));
78091               state.back = -1;
78092               state.mode = TYPE$1;
78093               break;
78094             }
78095             if (here_op & 64) {
78096               strm.msg = 'invalid literal/length code';
78097               state.mode = BAD$1;
78098               break;
78099             }
78100             state.extra = here_op & 15;
78101             state.mode = LENEXT;
78102             /* falls through */
78103           case LENEXT:
78104             if (state.extra) {
78105               //=== NEEDBITS(state.extra);
78106               n = state.extra;
78107               while (bits < n) {
78108                 if (have === 0) { break inf_leave; }
78109                 have--;
78110                 hold += input[next++] << bits;
78111                 bits += 8;
78112               }
78113               //===//
78114               state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
78115               //--- DROPBITS(state.extra) ---//
78116               hold >>>= state.extra;
78117               bits -= state.extra;
78118               //---//
78119               state.back += state.extra;
78120             }
78121             //Tracevv((stderr, "inflate:         length %u\n", state.length));
78122             state.was = state.length;
78123             state.mode = DIST;
78124             /* falls through */
78125           case DIST:
78126             for (;;) {
78127               here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
78128               here_bits = here >>> 24;
78129               here_op = (here >>> 16) & 0xff;
78130               here_val = here & 0xffff;
78131
78132               if ((here_bits) <= bits) { break; }
78133               //--- PULLBYTE() ---//
78134               if (have === 0) { break inf_leave; }
78135               have--;
78136               hold += input[next++] << bits;
78137               bits += 8;
78138               //---//
78139             }
78140             if ((here_op & 0xf0) === 0) {
78141               last_bits = here_bits;
78142               last_op = here_op;
78143               last_val = here_val;
78144               for (;;) {
78145                 here = state.distcode[last_val +
78146                         ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
78147                 here_bits = here >>> 24;
78148                 here_op = (here >>> 16) & 0xff;
78149                 here_val = here & 0xffff;
78150
78151                 if ((last_bits + here_bits) <= bits) { break; }
78152                 //--- PULLBYTE() ---//
78153                 if (have === 0) { break inf_leave; }
78154                 have--;
78155                 hold += input[next++] << bits;
78156                 bits += 8;
78157                 //---//
78158               }
78159               //--- DROPBITS(last.bits) ---//
78160               hold >>>= last_bits;
78161               bits -= last_bits;
78162               //---//
78163               state.back += last_bits;
78164             }
78165             //--- DROPBITS(here.bits) ---//
78166             hold >>>= here_bits;
78167             bits -= here_bits;
78168             //---//
78169             state.back += here_bits;
78170             if (here_op & 64) {
78171               strm.msg = 'invalid distance code';
78172               state.mode = BAD$1;
78173               break;
78174             }
78175             state.offset = here_val;
78176             state.extra = (here_op) & 15;
78177             state.mode = DISTEXT;
78178             /* falls through */
78179           case DISTEXT:
78180             if (state.extra) {
78181               //=== NEEDBITS(state.extra);
78182               n = state.extra;
78183               while (bits < n) {
78184                 if (have === 0) { break inf_leave; }
78185                 have--;
78186                 hold += input[next++] << bits;
78187                 bits += 8;
78188               }
78189               //===//
78190               state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
78191               //--- DROPBITS(state.extra) ---//
78192               hold >>>= state.extra;
78193               bits -= state.extra;
78194               //---//
78195               state.back += state.extra;
78196             }
78197     //#ifdef INFLATE_STRICT
78198             if (state.offset > state.dmax) {
78199               strm.msg = 'invalid distance too far back';
78200               state.mode = BAD$1;
78201               break;
78202             }
78203     //#endif
78204             //Tracevv((stderr, "inflate:         distance %u\n", state.offset));
78205             state.mode = MATCH;
78206             /* falls through */
78207           case MATCH:
78208             if (left === 0) { break inf_leave; }
78209             copy = _out - left;
78210             if (state.offset > copy) {         /* copy from window */
78211               copy = state.offset - copy;
78212               if (copy > state.whave) {
78213                 if (state.sane) {
78214                   strm.msg = 'invalid distance too far back';
78215                   state.mode = BAD$1;
78216                   break;
78217                 }
78218     // (!) This block is disabled in zlib defaults,
78219     // don't enable it for binary compatibility
78220     //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
78221     //          Trace((stderr, "inflate.c too far\n"));
78222     //          copy -= state.whave;
78223     //          if (copy > state.length) { copy = state.length; }
78224     //          if (copy > left) { copy = left; }
78225     //          left -= copy;
78226     //          state.length -= copy;
78227     //          do {
78228     //            output[put++] = 0;
78229     //          } while (--copy);
78230     //          if (state.length === 0) { state.mode = LEN; }
78231     //          break;
78232     //#endif
78233               }
78234               if (copy > state.wnext) {
78235                 copy -= state.wnext;
78236                 from = state.wsize - copy;
78237               }
78238               else {
78239                 from = state.wnext - copy;
78240               }
78241               if (copy > state.length) { copy = state.length; }
78242               from_source = state.window;
78243             }
78244             else {                              /* copy from output */
78245               from_source = output;
78246               from = put - state.offset;
78247               copy = state.length;
78248             }
78249             if (copy > left) { copy = left; }
78250             left -= copy;
78251             state.length -= copy;
78252             do {
78253               output[put++] = from_source[from++];
78254             } while (--copy);
78255             if (state.length === 0) { state.mode = LEN; }
78256             break;
78257           case LIT:
78258             if (left === 0) { break inf_leave; }
78259             output[put++] = state.length;
78260             left--;
78261             state.mode = LEN;
78262             break;
78263           case CHECK:
78264             if (state.wrap) {
78265               //=== NEEDBITS(32);
78266               while (bits < 32) {
78267                 if (have === 0) { break inf_leave; }
78268                 have--;
78269                 // Use '|' instead of '+' to make sure that result is signed
78270                 hold |= input[next++] << bits;
78271                 bits += 8;
78272               }
78273               //===//
78274               _out -= left;
78275               strm.total_out += _out;
78276               state.total += _out;
78277               if (_out) {
78278                 strm.adler = state.check =
78279                     /*UPDATE(state.check, put - _out, _out);*/
78280                     (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));
78281
78282               }
78283               _out = left;
78284               // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
78285               if ((state.flags ? hold : zswap32(hold)) !== state.check) {
78286                 strm.msg = 'incorrect data check';
78287                 state.mode = BAD$1;
78288                 break;
78289               }
78290               //=== INITBITS();
78291               hold = 0;
78292               bits = 0;
78293               //===//
78294               //Tracev((stderr, "inflate:   check matches trailer\n"));
78295             }
78296             state.mode = LENGTH;
78297             /* falls through */
78298           case LENGTH:
78299             if (state.wrap && state.flags) {
78300               //=== NEEDBITS(32);
78301               while (bits < 32) {
78302                 if (have === 0) { break inf_leave; }
78303                 have--;
78304                 hold += input[next++] << bits;
78305                 bits += 8;
78306               }
78307               //===//
78308               if (hold !== (state.total & 0xffffffff)) {
78309                 strm.msg = 'incorrect length check';
78310                 state.mode = BAD$1;
78311                 break;
78312               }
78313               //=== INITBITS();
78314               hold = 0;
78315               bits = 0;
78316               //===//
78317               //Tracev((stderr, "inflate:   length matches trailer\n"));
78318             }
78319             state.mode = DONE;
78320             /* falls through */
78321           case DONE:
78322             ret = Z_STREAM_END$2;
78323             break inf_leave;
78324           case BAD$1:
78325             ret = Z_DATA_ERROR$1;
78326             break inf_leave;
78327           case MEM:
78328             return Z_MEM_ERROR;
78329           case SYNC:
78330             /* falls through */
78331           default:
78332             return Z_STREAM_ERROR$1;
78333         }
78334       }
78335
78336       // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
78337
78338       /*
78339          Return from inflate(), updating the total counts and the check value.
78340          If there was no progress during the inflate() call, return a buffer
78341          error.  Call updatewindow() to create and/or update the window state.
78342          Note: a memory error from inflate() is non-recoverable.
78343        */
78344
78345       //--- RESTORE() ---
78346       strm.next_out = put;
78347       strm.avail_out = left;
78348       strm.next_in = next;
78349       strm.avail_in = have;
78350       state.hold = hold;
78351       state.bits = bits;
78352       //---
78353
78354       if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 &&
78355                           (state.mode < CHECK || flush !== Z_FINISH$2))) {
78356         if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;
78357       }
78358       _in -= strm.avail_in;
78359       _out -= strm.avail_out;
78360       strm.total_in += _in;
78361       strm.total_out += _out;
78362       state.total += _out;
78363       if (state.wrap && _out) {
78364         strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
78365           (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));
78366       }
78367       strm.data_type = state.bits + (state.last ? 64 : 0) +
78368                         (state.mode === TYPE$1 ? 128 : 0) +
78369                         (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
78370       if (((_in === 0 && _out === 0) || flush === Z_FINISH$2) && ret === Z_OK$2) {
78371         ret = Z_BUF_ERROR$1;
78372       }
78373       return ret;
78374     };
78375
78376
78377     const inflateEnd = (strm) => {
78378
78379       if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
78380         return Z_STREAM_ERROR$1;
78381       }
78382
78383       let state = strm.state;
78384       if (state.window) {
78385         state.window = null;
78386       }
78387       strm.state = null;
78388       return Z_OK$2;
78389     };
78390
78391
78392     const inflateGetHeader = (strm, head) => {
78393
78394       /* check state */
78395       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
78396       const state = strm.state;
78397       if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }
78398
78399       /* save header structure */
78400       state.head = head;
78401       head.done = false;
78402       return Z_OK$2;
78403     };
78404
78405
78406     const inflateSetDictionary = (strm, dictionary) => {
78407       const dictLength = dictionary.length;
78408
78409       let state;
78410       let dictid;
78411       let ret;
78412
78413       /* check state */
78414       if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR$1; }
78415       state = strm.state;
78416
78417       if (state.wrap !== 0 && state.mode !== DICT) {
78418         return Z_STREAM_ERROR$1;
78419       }
78420
78421       /* check for correct dictionary identifier */
78422       if (state.mode === DICT) {
78423         dictid = 1; /* adler32(0, null, 0)*/
78424         /* dictid = adler32(dictid, dictionary, dictLength); */
78425         dictid = adler32_1(dictid, dictionary, dictLength, 0);
78426         if (dictid !== state.check) {
78427           return Z_DATA_ERROR$1;
78428         }
78429       }
78430       /* copy dictionary to window using updatewindow(), which will amend the
78431        existing dictionary if appropriate */
78432       ret = updatewindow(strm, dictionary, dictLength, dictLength);
78433       if (ret) {
78434         state.mode = MEM;
78435         return Z_MEM_ERROR;
78436       }
78437       state.havedict = 1;
78438       // Tracev((stderr, "inflate:   dictionary set\n"));
78439       return Z_OK$2;
78440     };
78441
78442
78443     var inflateReset_1 = inflateReset;
78444     var inflateReset2_1 = inflateReset2;
78445     var inflateResetKeep_1 = inflateResetKeep;
78446     var inflateInit_1 = inflateInit;
78447     var inflateInit2_1 = inflateInit2;
78448     var inflate_2 = inflate;
78449     var inflateEnd_1 = inflateEnd;
78450     var inflateGetHeader_1 = inflateGetHeader;
78451     var inflateSetDictionary_1 = inflateSetDictionary;
78452     var inflateInfo = 'pako inflate (from Nodeca project)';
78453
78454     /* Not implemented
78455     module.exports.inflateCopy = inflateCopy;
78456     module.exports.inflateGetDictionary = inflateGetDictionary;
78457     module.exports.inflateMark = inflateMark;
78458     module.exports.inflatePrime = inflatePrime;
78459     module.exports.inflateSync = inflateSync;
78460     module.exports.inflateSyncPoint = inflateSyncPoint;
78461     module.exports.inflateUndermine = inflateUndermine;
78462     */
78463
78464     var inflate_1 = {
78465         inflateReset: inflateReset_1,
78466         inflateReset2: inflateReset2_1,
78467         inflateResetKeep: inflateResetKeep_1,
78468         inflateInit: inflateInit_1,
78469         inflateInit2: inflateInit2_1,
78470         inflate: inflate_2,
78471         inflateEnd: inflateEnd_1,
78472         inflateGetHeader: inflateGetHeader_1,
78473         inflateSetDictionary: inflateSetDictionary_1,
78474         inflateInfo: inflateInfo
78475     };
78476
78477     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
78478     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
78479     //
78480     // This software is provided 'as-is', without any express or implied
78481     // warranty. In no event will the authors be held liable for any damages
78482     // arising from the use of this software.
78483     //
78484     // Permission is granted to anyone to use this software for any purpose,
78485     // including commercial applications, and to alter it and redistribute it
78486     // freely, subject to the following restrictions:
78487     //
78488     // 1. The origin of this software must not be misrepresented; you must not
78489     //   claim that you wrote the original software. If you use this software
78490     //   in a product, an acknowledgment in the product documentation would be
78491     //   appreciated but is not required.
78492     // 2. Altered source versions must be plainly marked as such, and must not be
78493     //   misrepresented as being the original software.
78494     // 3. This notice may not be removed or altered from any source distribution.
78495
78496     function GZheader() {
78497       /* true if compressed data believed to be text */
78498       this.text       = 0;
78499       /* modification time */
78500       this.time       = 0;
78501       /* extra flags (not used when writing a gzip file) */
78502       this.xflags     = 0;
78503       /* operating system */
78504       this.os         = 0;
78505       /* pointer to extra field or Z_NULL if none */
78506       this.extra      = null;
78507       /* extra field length (valid if extra != Z_NULL) */
78508       this.extra_len  = 0; // Actually, we don't need it in JS,
78509                            // but leave for few code modifications
78510
78511       //
78512       // Setup limits is not necessary because in js we should not preallocate memory
78513       // for inflate use constant limit in 65536 bytes
78514       //
78515
78516       /* space at extra (only when reading header) */
78517       // this.extra_max  = 0;
78518       /* pointer to zero-terminated file name or Z_NULL */
78519       this.name       = '';
78520       /* space at name (only when reading header) */
78521       // this.name_max   = 0;
78522       /* pointer to zero-terminated comment or Z_NULL */
78523       this.comment    = '';
78524       /* space at comment (only when reading header) */
78525       // this.comm_max   = 0;
78526       /* true if there was or will be a header crc */
78527       this.hcrc       = 0;
78528       /* true when done reading gzip header (not used when writing a gzip file) */
78529       this.done       = false;
78530     }
78531
78532     var gzheader = GZheader;
78533
78534     const toString$1 = Object.prototype.toString;
78535
78536     /* Public constants ==========================================================*/
78537     /* ===========================================================================*/
78538
78539     const {
78540       Z_NO_FLUSH: Z_NO_FLUSH$2, Z_FINISH: Z_FINISH$3,
78541       Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_MEM_ERROR: Z_MEM_ERROR$1
78542     } = constants;
78543
78544     /* ===========================================================================*/
78545
78546
78547     /**
78548      * class Inflate
78549      *
78550      * Generic JS-style wrapper for zlib calls. If you don't need
78551      * streaming behaviour - use more simple functions: [[inflate]]
78552      * and [[inflateRaw]].
78553      **/
78554
78555     /* internal
78556      * inflate.chunks -> Array
78557      *
78558      * Chunks of output data, if [[Inflate#onData]] not overridden.
78559      **/
78560
78561     /**
78562      * Inflate.result -> Uint8Array|String
78563      *
78564      * Uncompressed result, generated by default [[Inflate#onData]]
78565      * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
78566      * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
78567      **/
78568
78569     /**
78570      * Inflate.err -> Number
78571      *
78572      * Error code after inflate finished. 0 (Z_OK) on success.
78573      * Should be checked if broken data possible.
78574      **/
78575
78576     /**
78577      * Inflate.msg -> String
78578      *
78579      * Error message, if [[Inflate.err]] != 0
78580      **/
78581
78582
78583     /**
78584      * new Inflate(options)
78585      * - options (Object): zlib inflate options.
78586      *
78587      * Creates new inflator instance with specified params. Throws exception
78588      * on bad params. Supported options:
78589      *
78590      * - `windowBits`
78591      * - `dictionary`
78592      *
78593      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
78594      * for more information on these.
78595      *
78596      * Additional options, for internal needs:
78597      *
78598      * - `chunkSize` - size of generated data chunks (16K by default)
78599      * - `raw` (Boolean) - do raw inflate
78600      * - `to` (String) - if equal to 'string', then result will be converted
78601      *   from utf8 to utf16 (javascript) string. When string output requested,
78602      *   chunk length can differ from `chunkSize`, depending on content.
78603      *
78604      * By default, when no options set, autodetect deflate/gzip data format via
78605      * wrapper header.
78606      *
78607      * ##### Example:
78608      *
78609      * ```javascript
78610      * const pako = require('pako')
78611      * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
78612      * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
78613      *
78614      * const inflate = new pako.Inflate({ level: 3});
78615      *
78616      * inflate.push(chunk1, false);
78617      * inflate.push(chunk2, true);  // true -> last chunk
78618      *
78619      * if (inflate.err) { throw new Error(inflate.err); }
78620      *
78621      * console.log(inflate.result);
78622      * ```
78623      **/
78624     function Inflate(options) {
78625       this.options = common.assign({
78626         chunkSize: 1024 * 64,
78627         windowBits: 15,
78628         to: ''
78629       }, options || {});
78630
78631       const opt = this.options;
78632
78633       // Force window size for `raw` data, if not set directly,
78634       // because we have no header for autodetect.
78635       if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
78636         opt.windowBits = -opt.windowBits;
78637         if (opt.windowBits === 0) { opt.windowBits = -15; }
78638       }
78639
78640       // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
78641       if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
78642           !(options && options.windowBits)) {
78643         opt.windowBits += 32;
78644       }
78645
78646       // Gzip header has no info about windows size, we can do autodetect only
78647       // for deflate. So, if window size not set, force it to max when gzip possible
78648       if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
78649         // bit 3 (16) -> gzipped data
78650         // bit 4 (32) -> autodetect gzip/deflate
78651         if ((opt.windowBits & 15) === 0) {
78652           opt.windowBits |= 15;
78653         }
78654       }
78655
78656       this.err    = 0;      // error code, if happens (0 = Z_OK)
78657       this.msg    = '';     // error message
78658       this.ended  = false;  // used to avoid multiple onEnd() calls
78659       this.chunks = [];     // chunks of compressed data
78660
78661       this.strm   = new zstream();
78662       this.strm.avail_out = 0;
78663
78664       let status  = inflate_1.inflateInit2(
78665         this.strm,
78666         opt.windowBits
78667       );
78668
78669       if (status !== Z_OK$3) {
78670         throw new Error(messages[status]);
78671       }
78672
78673       this.header = new gzheader();
78674
78675       inflate_1.inflateGetHeader(this.strm, this.header);
78676
78677       // Setup dictionary
78678       if (opt.dictionary) {
78679         // Convert data if needed
78680         if (typeof opt.dictionary === 'string') {
78681           opt.dictionary = strings.string2buf(opt.dictionary);
78682         } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {
78683           opt.dictionary = new Uint8Array(opt.dictionary);
78684         }
78685         if (opt.raw) { //In raw mode we need to set the dictionary early
78686           status = inflate_1.inflateSetDictionary(this.strm, opt.dictionary);
78687           if (status !== Z_OK$3) {
78688             throw new Error(messages[status]);
78689           }
78690         }
78691       }
78692     }
78693
78694     /**
78695      * Inflate#push(data[, flush_mode]) -> Boolean
78696      * - data (Uint8Array|ArrayBuffer): input data
78697      * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
78698      *   flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
78699      *   `true` means Z_FINISH.
78700      *
78701      * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
78702      * new output chunks. Returns `true` on success. If end of stream detected,
78703      * [[Inflate#onEnd]] will be called.
78704      *
78705      * `flush_mode` is not needed for normal operation, because end of stream
78706      * detected automatically. You may try to use it for advanced things, but
78707      * this functionality was not tested.
78708      *
78709      * On fail call [[Inflate#onEnd]] with error code and return false.
78710      *
78711      * ##### Example
78712      *
78713      * ```javascript
78714      * push(chunk, false); // push one of data chunks
78715      * ...
78716      * push(chunk, true);  // push last chunk
78717      * ```
78718      **/
78719     Inflate.prototype.push = function (data, flush_mode) {
78720       const strm = this.strm;
78721       const chunkSize = this.options.chunkSize;
78722       const dictionary = this.options.dictionary;
78723       let status, _flush_mode, last_avail_out;
78724
78725       if (this.ended) return false;
78726
78727       if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
78728       else _flush_mode = flush_mode === true ? Z_FINISH$3 : Z_NO_FLUSH$2;
78729
78730       // Convert data if needed
78731       if (toString$1.call(data) === '[object ArrayBuffer]') {
78732         strm.input = new Uint8Array(data);
78733       } else {
78734         strm.input = data;
78735       }
78736
78737       strm.next_in = 0;
78738       strm.avail_in = strm.input.length;
78739
78740       for (;;) {
78741         if (strm.avail_out === 0) {
78742           strm.output = new Uint8Array(chunkSize);
78743           strm.next_out = 0;
78744           strm.avail_out = chunkSize;
78745         }
78746
78747         status = inflate_1.inflate(strm, _flush_mode);
78748
78749         if (status === Z_NEED_DICT$1 && dictionary) {
78750           status = inflate_1.inflateSetDictionary(strm, dictionary);
78751
78752           if (status === Z_OK$3) {
78753             status = inflate_1.inflate(strm, _flush_mode);
78754           } else if (status === Z_DATA_ERROR$2) {
78755             // Replace code with more verbose
78756             status = Z_NEED_DICT$1;
78757           }
78758         }
78759
78760         // Skip snyc markers if more data follows and not raw mode
78761         while (strm.avail_in > 0 &&
78762                status === Z_STREAM_END$3 &&
78763                strm.state.wrap > 0 &&
78764                data[strm.next_in] !== 0)
78765         {
78766           inflate_1.inflateReset(strm);
78767           status = inflate_1.inflate(strm, _flush_mode);
78768         }
78769
78770         switch (status) {
78771           case Z_STREAM_ERROR$2:
78772           case Z_DATA_ERROR$2:
78773           case Z_NEED_DICT$1:
78774           case Z_MEM_ERROR$1:
78775             this.onEnd(status);
78776             this.ended = true;
78777             return false;
78778         }
78779
78780         // Remember real `avail_out` value, because we may patch out buffer content
78781         // to align utf8 strings boundaries.
78782         last_avail_out = strm.avail_out;
78783
78784         if (strm.next_out) {
78785           if (strm.avail_out === 0 || status === Z_STREAM_END$3) {
78786
78787             if (this.options.to === 'string') {
78788
78789               let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
78790
78791               let tail = strm.next_out - next_out_utf8;
78792               let utf8str = strings.buf2string(strm.output, next_out_utf8);
78793
78794               // move tail & realign counters
78795               strm.next_out = tail;
78796               strm.avail_out = chunkSize - tail;
78797               if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);
78798
78799               this.onData(utf8str);
78800
78801             } else {
78802               this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));
78803             }
78804           }
78805         }
78806
78807         // Must repeat iteration if out buffer is full
78808         if (status === Z_OK$3 && last_avail_out === 0) continue;
78809
78810         // Finalize if end of stream reached.
78811         if (status === Z_STREAM_END$3) {
78812           status = inflate_1.inflateEnd(this.strm);
78813           this.onEnd(status);
78814           this.ended = true;
78815           return true;
78816         }
78817
78818         if (strm.avail_in === 0) break;
78819       }
78820
78821       return true;
78822     };
78823
78824
78825     /**
78826      * Inflate#onData(chunk) -> Void
78827      * - chunk (Uint8Array|String): output data. When string output requested,
78828      *   each chunk will be string.
78829      *
78830      * By default, stores data blocks in `chunks[]` property and glue
78831      * those in `onEnd`. Override this handler, if you need another behaviour.
78832      **/
78833     Inflate.prototype.onData = function (chunk) {
78834       this.chunks.push(chunk);
78835     };
78836
78837
78838     /**
78839      * Inflate#onEnd(status) -> Void
78840      * - status (Number): inflate status. 0 (Z_OK) on success,
78841      *   other if not.
78842      *
78843      * Called either after you tell inflate that the input stream is
78844      * complete (Z_FINISH). By default - join collected chunks,
78845      * free memory and fill `results` / `err` properties.
78846      **/
78847     Inflate.prototype.onEnd = function (status) {
78848       // On success - join
78849       if (status === Z_OK$3) {
78850         if (this.options.to === 'string') {
78851           this.result = this.chunks.join('');
78852         } else {
78853           this.result = common.flattenChunks(this.chunks);
78854         }
78855       }
78856       this.chunks = [];
78857       this.err = status;
78858       this.msg = this.strm.msg;
78859     };
78860
78861
78862     /**
78863      * inflate(data[, options]) -> Uint8Array|String
78864      * - data (Uint8Array): input data to decompress.
78865      * - options (Object): zlib inflate options.
78866      *
78867      * Decompress `data` with inflate/ungzip and `options`. Autodetect
78868      * format via wrapper header by default. That's why we don't provide
78869      * separate `ungzip` method.
78870      *
78871      * Supported options are:
78872      *
78873      * - windowBits
78874      *
78875      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
78876      * for more information.
78877      *
78878      * Sugar (options):
78879      *
78880      * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
78881      *   negative windowBits implicitly.
78882      * - `to` (String) - if equal to 'string', then result will be converted
78883      *   from utf8 to utf16 (javascript) string. When string output requested,
78884      *   chunk length can differ from `chunkSize`, depending on content.
78885      *
78886      *
78887      * ##### Example:
78888      *
78889      * ```javascript
78890      * const pako = require('pako');
78891      * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));
78892      * let output;
78893      *
78894      * try {
78895      *   output = pako.inflate(input);
78896      * } catch (err)
78897      *   console.log(err);
78898      * }
78899      * ```
78900      **/
78901     function inflate$1(input, options) {
78902       const inflator = new Inflate(options);
78903
78904       inflator.push(input);
78905
78906       // That will never happens, if you don't cheat with options :)
78907       if (inflator.err) throw inflator.msg || messages[inflator.err];
78908
78909       return inflator.result;
78910     }
78911
78912
78913     /**
78914      * inflateRaw(data[, options]) -> Uint8Array|String
78915      * - data (Uint8Array): input data to decompress.
78916      * - options (Object): zlib inflate options.
78917      *
78918      * The same as [[inflate]], but creates raw data, without wrapper
78919      * (header and adler32 crc).
78920      **/
78921     function inflateRaw(input, options) {
78922       options = options || {};
78923       options.raw = true;
78924       return inflate$1(input, options);
78925     }
78926
78927
78928     /**
78929      * ungzip(data[, options]) -> Uint8Array|String
78930      * - data (Uint8Array): input data to decompress.
78931      * - options (Object): zlib inflate options.
78932      *
78933      * Just shortcut to [[inflate]], because it autodetects format
78934      * by header.content. Done for convenience.
78935      **/
78936
78937
78938     var Inflate_1 = Inflate;
78939     var inflate_2$1 = inflate$1;
78940     var inflateRaw_1 = inflateRaw;
78941     var ungzip = inflate$1;
78942     var constants$2 = constants;
78943
78944     var inflate_1$1 = {
78945         Inflate: Inflate_1,
78946         inflate: inflate_2$1,
78947         inflateRaw: inflateRaw_1,
78948         ungzip: ungzip,
78949         constants: constants$2
78950     };
78951
78952     const { Inflate: Inflate$1, inflate: inflate$2, inflateRaw: inflateRaw$1, ungzip: ungzip$1 } = inflate_1$1;
78953     var inflate_1$2 = inflate$2;
78954
78955     /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
78956     var read = function (buffer, offset, isLE, mLen, nBytes) {
78957       var e, m;
78958       var eLen = (nBytes * 8) - mLen - 1;
78959       var eMax = (1 << eLen) - 1;
78960       var eBias = eMax >> 1;
78961       var nBits = -7;
78962       var i = isLE ? (nBytes - 1) : 0;
78963       var d = isLE ? -1 : 1;
78964       var s = buffer[offset + i];
78965
78966       i += d;
78967
78968       e = s & ((1 << (-nBits)) - 1);
78969       s >>= (-nBits);
78970       nBits += eLen;
78971       for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
78972
78973       m = e & ((1 << (-nBits)) - 1);
78974       e >>= (-nBits);
78975       nBits += mLen;
78976       for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
78977
78978       if (e === 0) {
78979         e = 1 - eBias;
78980       } else if (e === eMax) {
78981         return m ? NaN : ((s ? -1 : 1) * Infinity)
78982       } else {
78983         m = m + Math.pow(2, mLen);
78984         e = e - eBias;
78985       }
78986       return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
78987     };
78988
78989     var write = function (buffer, value, offset, isLE, mLen, nBytes) {
78990       var e, m, c;
78991       var eLen = (nBytes * 8) - mLen - 1;
78992       var eMax = (1 << eLen) - 1;
78993       var eBias = eMax >> 1;
78994       var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
78995       var i = isLE ? 0 : (nBytes - 1);
78996       var d = isLE ? 1 : -1;
78997       var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
78998
78999       value = Math.abs(value);
79000
79001       if (isNaN(value) || value === Infinity) {
79002         m = isNaN(value) ? 1 : 0;
79003         e = eMax;
79004       } else {
79005         e = Math.floor(Math.log(value) / Math.LN2);
79006         if (value * (c = Math.pow(2, -e)) < 1) {
79007           e--;
79008           c *= 2;
79009         }
79010         if (e + eBias >= 1) {
79011           value += rt / c;
79012         } else {
79013           value += rt * Math.pow(2, 1 - eBias);
79014         }
79015         if (value * c >= 2) {
79016           e++;
79017           c /= 2;
79018         }
79019
79020         if (e + eBias >= eMax) {
79021           m = 0;
79022           e = eMax;
79023         } else if (e + eBias >= 1) {
79024           m = ((value * c) - 1) * Math.pow(2, mLen);
79025           e = e + eBias;
79026         } else {
79027           m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
79028           e = 0;
79029         }
79030       }
79031
79032       for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
79033
79034       e = (e << mLen) | m;
79035       eLen += mLen;
79036       for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
79037
79038       buffer[offset + i - d] |= s * 128;
79039     };
79040
79041     var ieee754 = {
79042         read: read,
79043         write: write
79044     };
79045
79046     var pbf = Pbf;
79047
79048
79049
79050     function Pbf(buf) {
79051         this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
79052         this.pos = 0;
79053         this.type = 0;
79054         this.length = this.buf.length;
79055     }
79056
79057     Pbf.Varint  = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
79058     Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
79059     Pbf.Bytes   = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
79060     Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
79061
79062     var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
79063         SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
79064
79065     // Threshold chosen based on both benchmarking and knowledge about browser string
79066     // data structures (which currently switch structure types at 12 bytes or more)
79067     var TEXT_DECODER_MIN_LENGTH = 12;
79068     var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
79069
79070     Pbf.prototype = {
79071
79072         destroy: function() {
79073             this.buf = null;
79074         },
79075
79076         // === READING =================================================================
79077
79078         readFields: function(readField, result, end) {
79079             end = end || this.length;
79080
79081             while (this.pos < end) {
79082                 var val = this.readVarint(),
79083                     tag = val >> 3,
79084                     startPos = this.pos;
79085
79086                 this.type = val & 0x7;
79087                 readField(tag, result, this);
79088
79089                 if (this.pos === startPos) this.skip(val);
79090             }
79091             return result;
79092         },
79093
79094         readMessage: function(readField, result) {
79095             return this.readFields(readField, result, this.readVarint() + this.pos);
79096         },
79097
79098         readFixed32: function() {
79099             var val = readUInt32(this.buf, this.pos);
79100             this.pos += 4;
79101             return val;
79102         },
79103
79104         readSFixed32: function() {
79105             var val = readInt32(this.buf, this.pos);
79106             this.pos += 4;
79107             return val;
79108         },
79109
79110         // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
79111
79112         readFixed64: function() {
79113             var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
79114             this.pos += 8;
79115             return val;
79116         },
79117
79118         readSFixed64: function() {
79119             var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
79120             this.pos += 8;
79121             return val;
79122         },
79123
79124         readFloat: function() {
79125             var val = ieee754.read(this.buf, this.pos, true, 23, 4);
79126             this.pos += 4;
79127             return val;
79128         },
79129
79130         readDouble: function() {
79131             var val = ieee754.read(this.buf, this.pos, true, 52, 8);
79132             this.pos += 8;
79133             return val;
79134         },
79135
79136         readVarint: function(isSigned) {
79137             var buf = this.buf,
79138                 val, b;
79139
79140             b = buf[this.pos++]; val  =  b & 0x7f;        if (b < 0x80) return val;
79141             b = buf[this.pos++]; val |= (b & 0x7f) << 7;  if (b < 0x80) return val;
79142             b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;
79143             b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;
79144             b = buf[this.pos];   val |= (b & 0x0f) << 28;
79145
79146             return readVarintRemainder(val, isSigned, this);
79147         },
79148
79149         readVarint64: function() { // for compatibility with v2.0.1
79150             return this.readVarint(true);
79151         },
79152
79153         readSVarint: function() {
79154             var num = this.readVarint();
79155             return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
79156         },
79157
79158         readBoolean: function() {
79159             return Boolean(this.readVarint());
79160         },
79161
79162         readString: function() {
79163             var end = this.readVarint() + this.pos;
79164             var pos = this.pos;
79165             this.pos = end;
79166
79167             if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
79168                 // longer strings are fast with the built-in browser TextDecoder API
79169                 return readUtf8TextDecoder(this.buf, pos, end);
79170             }
79171             // short strings are fast with our custom implementation
79172             return readUtf8(this.buf, pos, end);
79173         },
79174
79175         readBytes: function() {
79176             var end = this.readVarint() + this.pos,
79177                 buffer = this.buf.subarray(this.pos, end);
79178             this.pos = end;
79179             return buffer;
79180         },
79181
79182         // verbose for performance reasons; doesn't affect gzipped size
79183
79184         readPackedVarint: function(arr, isSigned) {
79185             if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));
79186             var end = readPackedEnd(this);
79187             arr = arr || [];
79188             while (this.pos < end) arr.push(this.readVarint(isSigned));
79189             return arr;
79190         },
79191         readPackedSVarint: function(arr) {
79192             if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());
79193             var end = readPackedEnd(this);
79194             arr = arr || [];
79195             while (this.pos < end) arr.push(this.readSVarint());
79196             return arr;
79197         },
79198         readPackedBoolean: function(arr) {
79199             if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());
79200             var end = readPackedEnd(this);
79201             arr = arr || [];
79202             while (this.pos < end) arr.push(this.readBoolean());
79203             return arr;
79204         },
79205         readPackedFloat: function(arr) {
79206             if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());
79207             var end = readPackedEnd(this);
79208             arr = arr || [];
79209             while (this.pos < end) arr.push(this.readFloat());
79210             return arr;
79211         },
79212         readPackedDouble: function(arr) {
79213             if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());
79214             var end = readPackedEnd(this);
79215             arr = arr || [];
79216             while (this.pos < end) arr.push(this.readDouble());
79217             return arr;
79218         },
79219         readPackedFixed32: function(arr) {
79220             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());
79221             var end = readPackedEnd(this);
79222             arr = arr || [];
79223             while (this.pos < end) arr.push(this.readFixed32());
79224             return arr;
79225         },
79226         readPackedSFixed32: function(arr) {
79227             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());
79228             var end = readPackedEnd(this);
79229             arr = arr || [];
79230             while (this.pos < end) arr.push(this.readSFixed32());
79231             return arr;
79232         },
79233         readPackedFixed64: function(arr) {
79234             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());
79235             var end = readPackedEnd(this);
79236             arr = arr || [];
79237             while (this.pos < end) arr.push(this.readFixed64());
79238             return arr;
79239         },
79240         readPackedSFixed64: function(arr) {
79241             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());
79242             var end = readPackedEnd(this);
79243             arr = arr || [];
79244             while (this.pos < end) arr.push(this.readSFixed64());
79245             return arr;
79246         },
79247
79248         skip: function(val) {
79249             var type = val & 0x7;
79250             if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {}
79251             else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;
79252             else if (type === Pbf.Fixed32) this.pos += 4;
79253             else if (type === Pbf.Fixed64) this.pos += 8;
79254             else throw new Error('Unimplemented type: ' + type);
79255         },
79256
79257         // === WRITING =================================================================
79258
79259         writeTag: function(tag, type) {
79260             this.writeVarint((tag << 3) | type);
79261         },
79262
79263         realloc: function(min) {
79264             var length = this.length || 16;
79265
79266             while (length < this.pos + min) length *= 2;
79267
79268             if (length !== this.length) {
79269                 var buf = new Uint8Array(length);
79270                 buf.set(this.buf);
79271                 this.buf = buf;
79272                 this.length = length;
79273             }
79274         },
79275
79276         finish: function() {
79277             this.length = this.pos;
79278             this.pos = 0;
79279             return this.buf.subarray(0, this.length);
79280         },
79281
79282         writeFixed32: function(val) {
79283             this.realloc(4);
79284             writeInt32(this.buf, val, this.pos);
79285             this.pos += 4;
79286         },
79287
79288         writeSFixed32: function(val) {
79289             this.realloc(4);
79290             writeInt32(this.buf, val, this.pos);
79291             this.pos += 4;
79292         },
79293
79294         writeFixed64: function(val) {
79295             this.realloc(8);
79296             writeInt32(this.buf, val & -1, this.pos);
79297             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
79298             this.pos += 8;
79299         },
79300
79301         writeSFixed64: function(val) {
79302             this.realloc(8);
79303             writeInt32(this.buf, val & -1, this.pos);
79304             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
79305             this.pos += 8;
79306         },
79307
79308         writeVarint: function(val) {
79309             val = +val || 0;
79310
79311             if (val > 0xfffffff || val < 0) {
79312                 writeBigVarint(val, this);
79313                 return;
79314             }
79315
79316             this.realloc(4);
79317
79318             this.buf[this.pos++] =           val & 0x7f  | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
79319             this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
79320             this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
79321             this.buf[this.pos++] =   (val >>> 7) & 0x7f;
79322         },
79323
79324         writeSVarint: function(val) {
79325             this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
79326         },
79327
79328         writeBoolean: function(val) {
79329             this.writeVarint(Boolean(val));
79330         },
79331
79332         writeString: function(str) {
79333             str = String(str);
79334             this.realloc(str.length * 4);
79335
79336             this.pos++; // reserve 1 byte for short string length
79337
79338             var startPos = this.pos;
79339             // write the string directly to the buffer and see how much was written
79340             this.pos = writeUtf8(this.buf, str, this.pos);
79341             var len = this.pos - startPos;
79342
79343             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
79344
79345             // finally, write the message length in the reserved place and restore the position
79346             this.pos = startPos - 1;
79347             this.writeVarint(len);
79348             this.pos += len;
79349         },
79350
79351         writeFloat: function(val) {
79352             this.realloc(4);
79353             ieee754.write(this.buf, val, this.pos, true, 23, 4);
79354             this.pos += 4;
79355         },
79356
79357         writeDouble: function(val) {
79358             this.realloc(8);
79359             ieee754.write(this.buf, val, this.pos, true, 52, 8);
79360             this.pos += 8;
79361         },
79362
79363         writeBytes: function(buffer) {
79364             var len = buffer.length;
79365             this.writeVarint(len);
79366             this.realloc(len);
79367             for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
79368         },
79369
79370         writeRawMessage: function(fn, obj) {
79371             this.pos++; // reserve 1 byte for short message length
79372
79373             // write the message directly to the buffer and see how much was written
79374             var startPos = this.pos;
79375             fn(obj, this);
79376             var len = this.pos - startPos;
79377
79378             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
79379
79380             // finally, write the message length in the reserved place and restore the position
79381             this.pos = startPos - 1;
79382             this.writeVarint(len);
79383             this.pos += len;
79384         },
79385
79386         writeMessage: function(tag, fn, obj) {
79387             this.writeTag(tag, Pbf.Bytes);
79388             this.writeRawMessage(fn, obj);
79389         },
79390
79391         writePackedVarint:   function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedVarint, arr);   },
79392         writePackedSVarint:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);  },
79393         writePackedBoolean:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);  },
79394         writePackedFloat:    function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFloat, arr);    },
79395         writePackedDouble:   function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedDouble, arr);   },
79396         writePackedFixed32:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);  },
79397         writePackedSFixed32: function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr); },
79398         writePackedFixed64:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);  },
79399         writePackedSFixed64: function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr); },
79400
79401         writeBytesField: function(tag, buffer) {
79402             this.writeTag(tag, Pbf.Bytes);
79403             this.writeBytes(buffer);
79404         },
79405         writeFixed32Field: function(tag, val) {
79406             this.writeTag(tag, Pbf.Fixed32);
79407             this.writeFixed32(val);
79408         },
79409         writeSFixed32Field: function(tag, val) {
79410             this.writeTag(tag, Pbf.Fixed32);
79411             this.writeSFixed32(val);
79412         },
79413         writeFixed64Field: function(tag, val) {
79414             this.writeTag(tag, Pbf.Fixed64);
79415             this.writeFixed64(val);
79416         },
79417         writeSFixed64Field: function(tag, val) {
79418             this.writeTag(tag, Pbf.Fixed64);
79419             this.writeSFixed64(val);
79420         },
79421         writeVarintField: function(tag, val) {
79422             this.writeTag(tag, Pbf.Varint);
79423             this.writeVarint(val);
79424         },
79425         writeSVarintField: function(tag, val) {
79426             this.writeTag(tag, Pbf.Varint);
79427             this.writeSVarint(val);
79428         },
79429         writeStringField: function(tag, str) {
79430             this.writeTag(tag, Pbf.Bytes);
79431             this.writeString(str);
79432         },
79433         writeFloatField: function(tag, val) {
79434             this.writeTag(tag, Pbf.Fixed32);
79435             this.writeFloat(val);
79436         },
79437         writeDoubleField: function(tag, val) {
79438             this.writeTag(tag, Pbf.Fixed64);
79439             this.writeDouble(val);
79440         },
79441         writeBooleanField: function(tag, val) {
79442             this.writeVarintField(tag, Boolean(val));
79443         }
79444     };
79445
79446     function readVarintRemainder(l, s, p) {
79447         var buf = p.buf,
79448             h, b;
79449
79450         b = buf[p.pos++]; h  = (b & 0x70) >> 4;  if (b < 0x80) return toNum(l, h, s);
79451         b = buf[p.pos++]; h |= (b & 0x7f) << 3;  if (b < 0x80) return toNum(l, h, s);
79452         b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);
79453         b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);
79454         b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);
79455         b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);
79456
79457         throw new Error('Expected varint not more than 10 bytes');
79458     }
79459
79460     function readPackedEnd(pbf) {
79461         return pbf.type === Pbf.Bytes ?
79462             pbf.readVarint() + pbf.pos : pbf.pos + 1;
79463     }
79464
79465     function toNum(low, high, isSigned) {
79466         if (isSigned) {
79467             return high * 0x100000000 + (low >>> 0);
79468         }
79469
79470         return ((high >>> 0) * 0x100000000) + (low >>> 0);
79471     }
79472
79473     function writeBigVarint(val, pbf) {
79474         var low, high;
79475
79476         if (val >= 0) {
79477             low  = (val % 0x100000000) | 0;
79478             high = (val / 0x100000000) | 0;
79479         } else {
79480             low  = ~(-val % 0x100000000);
79481             high = ~(-val / 0x100000000);
79482
79483             if (low ^ 0xffffffff) {
79484                 low = (low + 1) | 0;
79485             } else {
79486                 low = 0;
79487                 high = (high + 1) | 0;
79488             }
79489         }
79490
79491         if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
79492             throw new Error('Given varint doesn\'t fit into 10 bytes');
79493         }
79494
79495         pbf.realloc(10);
79496
79497         writeBigVarintLow(low, high, pbf);
79498         writeBigVarintHigh(high, pbf);
79499     }
79500
79501     function writeBigVarintLow(low, high, pbf) {
79502         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
79503         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
79504         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
79505         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
79506         pbf.buf[pbf.pos]   = low & 0x7f;
79507     }
79508
79509     function writeBigVarintHigh(high, pbf) {
79510         var lsb = (high & 0x07) << 4;
79511
79512         pbf.buf[pbf.pos++] |= lsb         | ((high >>>= 3) ? 0x80 : 0); if (!high) return;
79513         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
79514         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
79515         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
79516         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
79517         pbf.buf[pbf.pos++]  = high & 0x7f;
79518     }
79519
79520     function makeRoomForExtraLength(startPos, len, pbf) {
79521         var extraLen =
79522             len <= 0x3fff ? 1 :
79523             len <= 0x1fffff ? 2 :
79524             len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));
79525
79526         // if 1 byte isn't enough for encoding message length, shift the data to the right
79527         pbf.realloc(extraLen);
79528         for (var i = pbf.pos - 1; i >= startPos; i--) pbf.buf[i + extraLen] = pbf.buf[i];
79529     }
79530
79531     function writePackedVarint(arr, pbf)   { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]);   }
79532     function writePackedSVarint(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]);  }
79533     function writePackedFloat(arr, pbf)    { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]);    }
79534     function writePackedDouble(arr, pbf)   { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]);   }
79535     function writePackedBoolean(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]);  }
79536     function writePackedFixed32(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]);  }
79537     function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); }
79538     function writePackedFixed64(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]);  }
79539     function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
79540
79541     // Buffer code below from https://github.com/feross/buffer, MIT-licensed
79542
79543     function readUInt32(buf, pos) {
79544         return ((buf[pos]) |
79545             (buf[pos + 1] << 8) |
79546             (buf[pos + 2] << 16)) +
79547             (buf[pos + 3] * 0x1000000);
79548     }
79549
79550     function writeInt32(buf, val, pos) {
79551         buf[pos] = val;
79552         buf[pos + 1] = (val >>> 8);
79553         buf[pos + 2] = (val >>> 16);
79554         buf[pos + 3] = (val >>> 24);
79555     }
79556
79557     function readInt32(buf, pos) {
79558         return ((buf[pos]) |
79559             (buf[pos + 1] << 8) |
79560             (buf[pos + 2] << 16)) +
79561             (buf[pos + 3] << 24);
79562     }
79563
79564     function readUtf8(buf, pos, end) {
79565         var str = '';
79566         var i = pos;
79567
79568         while (i < end) {
79569             var b0 = buf[i];
79570             var c = null; // codepoint
79571             var bytesPerSequence =
79572                 b0 > 0xEF ? 4 :
79573                 b0 > 0xDF ? 3 :
79574                 b0 > 0xBF ? 2 : 1;
79575
79576             if (i + bytesPerSequence > end) break;
79577
79578             var b1, b2, b3;
79579
79580             if (bytesPerSequence === 1) {
79581                 if (b0 < 0x80) {
79582                     c = b0;
79583                 }
79584             } else if (bytesPerSequence === 2) {
79585                 b1 = buf[i + 1];
79586                 if ((b1 & 0xC0) === 0x80) {
79587                     c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);
79588                     if (c <= 0x7F) {
79589                         c = null;
79590                     }
79591                 }
79592             } else if (bytesPerSequence === 3) {
79593                 b1 = buf[i + 1];
79594                 b2 = buf[i + 2];
79595                 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
79596                     c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);
79597                     if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {
79598                         c = null;
79599                     }
79600                 }
79601             } else if (bytesPerSequence === 4) {
79602                 b1 = buf[i + 1];
79603                 b2 = buf[i + 2];
79604                 b3 = buf[i + 3];
79605                 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
79606                     c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);
79607                     if (c <= 0xFFFF || c >= 0x110000) {
79608                         c = null;
79609                     }
79610                 }
79611             }
79612
79613             if (c === null) {
79614                 c = 0xFFFD;
79615                 bytesPerSequence = 1;
79616
79617             } else if (c > 0xFFFF) {
79618                 c -= 0x10000;
79619                 str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
79620                 c = 0xDC00 | c & 0x3FF;
79621             }
79622
79623             str += String.fromCharCode(c);
79624             i += bytesPerSequence;
79625         }
79626
79627         return str;
79628     }
79629
79630     function readUtf8TextDecoder(buf, pos, end) {
79631         return utf8TextDecoder.decode(buf.subarray(pos, end));
79632     }
79633
79634     function writeUtf8(buf, str, pos) {
79635         for (var i = 0, c, lead; i < str.length; i++) {
79636             c = str.charCodeAt(i); // code point
79637
79638             if (c > 0xD7FF && c < 0xE000) {
79639                 if (lead) {
79640                     if (c < 0xDC00) {
79641                         buf[pos++] = 0xEF;
79642                         buf[pos++] = 0xBF;
79643                         buf[pos++] = 0xBD;
79644                         lead = c;
79645                         continue;
79646                     } else {
79647                         c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
79648                         lead = null;
79649                     }
79650                 } else {
79651                     if (c > 0xDBFF || (i + 1 === str.length)) {
79652                         buf[pos++] = 0xEF;
79653                         buf[pos++] = 0xBF;
79654                         buf[pos++] = 0xBD;
79655                     } else {
79656                         lead = c;
79657                     }
79658                     continue;
79659                 }
79660             } else if (lead) {
79661                 buf[pos++] = 0xEF;
79662                 buf[pos++] = 0xBF;
79663                 buf[pos++] = 0xBD;
79664                 lead = null;
79665             }
79666
79667             if (c < 0x80) {
79668                 buf[pos++] = c;
79669             } else {
79670                 if (c < 0x800) {
79671                     buf[pos++] = c >> 0x6 | 0xC0;
79672                 } else {
79673                     if (c < 0x10000) {
79674                         buf[pos++] = c >> 0xC | 0xE0;
79675                     } else {
79676                         buf[pos++] = c >> 0x12 | 0xF0;
79677                         buf[pos++] = c >> 0xC & 0x3F | 0x80;
79678                     }
79679                     buf[pos++] = c >> 0x6 & 0x3F | 0x80;
79680                 }
79681                 buf[pos++] = c & 0x3F | 0x80;
79682             }
79683         }
79684         return pos;
79685     }
79686
79687     /**
79688      * Decompress and parse an array buffer containing zipped
79689      * json data and return as a json object.
79690      *
79691      * @description Handles array buffers continaing zipped json
79692      * data.
79693      *
79694      * @param {ArrayBuffer} buffer - Array buffer to decompress.
79695      * @returns {Object} Parsed object.
79696      */
79697     function decompress(buffer) {
79698         const inflated = inflate_1$2(buffer, { to: "string" });
79699         return JSON.parse(inflated);
79700     }
79701     /**
79702      * Retrieves a resource as an array buffer and returns a promise
79703      * to the buffer.
79704      *
79705      * @description Rejects the promise on request failure.
79706      *
79707      * @param {string} url - URL for resource to retrieve.
79708      * @param {Promise} [abort] - Optional promise for aborting
79709      * the request through rejection.
79710      * @returns {Promise<ArrayBuffer>} Promise to the array buffer
79711      * resource.
79712      */
79713     function fetchArrayBuffer(url, abort) {
79714         const method = "GET";
79715         const responseType = "arraybuffer";
79716         return xhrFetch(url, method, responseType, [], null, abort);
79717     }
79718     function xhrFetch(url, method, responseType, headers, body, abort) {
79719         const xhr = new XMLHttpRequest();
79720         const promise = new Promise((resolve, reject) => {
79721             xhr.open(method, url, true);
79722             for (const header of headers) {
79723                 xhr.setRequestHeader(header.name, header.value);
79724             }
79725             xhr.responseType = responseType;
79726             xhr.timeout = 15000;
79727             xhr.onload = () => {
79728                 var _a;
79729                 if (xhr.status !== 200) {
79730                     const error = (_a = xhr.response) !== null && _a !== void 0 ? _a : new MapillaryError(`Response status error: ${url}`);
79731                     reject(error);
79732                 }
79733                 if (!xhr.response) {
79734                     reject(new MapillaryError(`Response empty: ${url}`));
79735                 }
79736                 resolve(xhr.response);
79737             };
79738             xhr.onerror = () => {
79739                 reject(new MapillaryError(`Request error: ${url}`));
79740             };
79741             xhr.ontimeout = () => {
79742                 reject(new MapillaryError(`Request timeout: ${url}`));
79743             };
79744             xhr.onabort = () => {
79745                 reject(new MapillaryError(`Request aborted: ${url}`));
79746             };
79747             xhr.send(method === "POST" ? body : null);
79748         });
79749         if (!!abort) {
79750             abort.catch(() => { xhr.abort(); });
79751         }
79752         return promise;
79753     }
79754     /**
79755      * Read the fields of a protobuf array buffer into a mesh
79756      * object.
79757      *
79758      * @param {ArrayBuffer} buffer - Protobuf array buffer
79759      * to read from.
79760      * @returns {MeshContract} Mesh object.
79761      */
79762     function readMeshPbf(buffer) {
79763         const pbf$1 = new pbf(buffer);
79764         const mesh = { faces: [], vertices: [] };
79765         return pbf$1.readFields(readMeshPbfField, mesh);
79766     }
79767     function readMeshPbfField(tag, mesh, pbf) {
79768         if (tag === 1) {
79769             mesh.vertices.push(pbf.readFloat());
79770         }
79771         else if (tag === 2) {
79772             mesh.faces.push(pbf.readVarint());
79773         }
79774         else {
79775             console.warn(`Unsupported pbf tag (${tag})`);
79776         }
79777     }
79778
79779     /**
79780      * @class GeometryProviderBase
79781      *
79782      * @classdesc Base class to extend if implementing a geometry
79783      * provider class.
79784      *
79785      * @example
79786      * ```js
79787      * class MyGeometryProvider extends GeometryProviderBase {
79788      *      ...
79789      * }
79790      * ```
79791      */
79792     class GeometryProviderBase {
79793         /**
79794          * Create a new geometry provider base instance.
79795          */
79796         constructor() { }
79797         /**
79798          * Convert a geodetic bounding box to the the minimum set
79799          * of cell ids containing the bounding box.
79800          *
79801          * @description The bounding box needs
79802          * to be sufficiently small to be contained in an area with the size
79803          * of maximally four tiles. Up to nine adjacent tiles may be returned.
79804          *
79805          * @param {LngLat} sw - South west corner of bounding box.
79806          * @param {LngLat} ne - North east corner of bounding box.
79807          *
79808          * @returns {Array<string>} Array of cell ids.
79809          */
79810         bboxToCellIds(sw, ne) {
79811             throw new MapillaryError("Not implemented");
79812         }
79813         /**
79814          * Get the cell ids of all adjacent cells.
79815          *
79816          * @description In the case of approximately rectangular cells
79817          * this is typically the eight orthogonally and diagonally adjacent
79818          * cells.
79819          *
79820          * @param {string} cellId - Id of cell.
79821          * @returns {Array<string>} Array of cell ids. No specific
79822          * order is guaranteed.
79823          */
79824         getAdjacent(cellId) {
79825             throw new MapillaryError("Not implemented");
79826         }
79827         /**
79828          * Get the vertices of a cell.
79829          *
79830          * @description The vertices form an unclosed
79831          * clockwise polygon in the 2D longitude, latitude
79832          * space. No assumption on the position of the first
79833          * vertex relative to the others can be made.
79834          *
79835          * @param {string} cellId - Id of cell.
79836          * @returns {Array<LngLat>} Unclosed clockwise polygon.
79837          */
79838         getVertices(cellId) {
79839             throw new MapillaryError("Not implemented");
79840         }
79841         /**
79842          * Convert geodetic coordinates to a cell id.
79843          *
79844          * @param {LngLat} lngLat - Longitude, latitude to convert.
79845          * @returns {string} Cell id for the longitude, latitude.
79846          */
79847         lngLatToCellId(lngLat) {
79848             throw new MapillaryError("Not implemented");
79849         }
79850         /** @ignore */
79851         _approxBboxToCellIds(sw, ne) {
79852             if (ne.lat <= sw.lat || ne.lng <= sw.lng) {
79853                 throw new MapillaryError("North east needs to be top right of south west");
79854             }
79855             const centerLat = (sw.lat + ne.lat) / 2;
79856             const centerLng = (sw.lng + ne.lng) / 2;
79857             const enu = geodeticToEnu(ne.lng, ne.lat, 0, centerLng, centerLat, 0);
79858             const threshold = Math.max(enu[0], enu[1]);
79859             return this._lngLatToCellIds({ lat: centerLat, lng: centerLng }, threshold);
79860         }
79861         /** @ignore */
79862         _enuToGeodetic(point, reference) {
79863             const [lng, lat] = enuToGeodetic(point[0], point[1], point[2], reference.lng, reference.lat, 0);
79864             return { lat, lng };
79865         }
79866         /** @ignore */
79867         _getLngLatBoundingBoxCorners(lngLat, threshold) {
79868             return [
79869                 [-threshold, threshold, 0],
79870                 [threshold, threshold, 0],
79871                 [threshold, -threshold, 0],
79872                 [-threshold, -threshold, 0],
79873             ].map((point) => {
79874                 return this._enuToGeodetic(point, lngLat);
79875             });
79876         }
79877         /**
79878          * Convert a geodetic square to cell ids.
79879          *
79880          * The square is specified as a longitude, latitude
79881          * and a threshold from the position using Manhattan distance.
79882          *
79883          * @param {LngLat} lngLat - Longitude, latitude.
79884          * @param {number} threshold - Threshold of the conversion in meters.
79885          *
79886          * @returns {Array<string>} Array of cell ids reachable within
79887          * the threshold.
79888          *
79889          * @ignore
79890          */
79891         _lngLatToCellIds(lngLat, threshold) {
79892             const cellId = this.lngLatToCellId(lngLat);
79893             const bboxCorners = this._getLngLatBoundingBoxCorners(lngLat, threshold);
79894             for (const corner of bboxCorners) {
79895                 const cid = this.lngLatToCellId(corner);
79896                 if (cid !== cellId) {
79897                     return [cellId, ...this.getAdjacent(cellId)];
79898                 }
79899             }
79900             return [cellId];
79901         }
79902     }
79903
79904     /**
79905      * @class DataProviderBase
79906      *
79907      * @classdesc Base class to extend if implementing a data provider
79908      * class.
79909      *
79910      * @fires datacreate
79911      *
79912      * @example
79913      * ```js
79914      * class MyDataProvider extends DataProviderBase {
79915      *   constructor() {
79916      *     super(new S2GeometryProvider());
79917      *   }
79918      *   ...
79919      * }
79920      * ```
79921      */
79922     class DataProviderBase extends EventEmitter {
79923         /**
79924          * Create a new data provider base instance.
79925          *
79926          * @param {GeometryProviderBase} geometry - Geometry
79927          * provider instance.
79928          */
79929         constructor(_geometry) {
79930             super();
79931             this._geometry = _geometry;
79932             if (!(this._geometry instanceof GeometryProviderBase)) {
79933                 throw new MapillaryError("The data provider requires a geometry provider base instance.");
79934             }
79935         }
79936         /**
79937          * Get geometry property.
79938          *
79939          * @returns {GeometryProviderBase} Geometry provider instance.
79940          */
79941         get geometry() {
79942             return this._geometry;
79943         }
79944         fire(type, event) {
79945             super.fire(type, event);
79946         }
79947         /**
79948          * Get core images in a geometry cell.
79949          *
79950          * @param {string} cellId - The id of the geometry cell.
79951          * @returns {Promise<CoreImagesContract>} Promise to
79952          * the core images of the requested geometry cell id.
79953          * @throws Rejects the promise on errors.
79954          */
79955         getCoreImages(cellId) {
79956             return Promise.reject(new MapillaryError("Not implemented"));
79957         }
79958         /**
79959          * Get a cluster reconstruction.
79960          *
79961          * @param {string} url - URL for the cluster reconstruction
79962          * to retrieve.
79963          * @param {Promise} [abort] - Optional promise for aborting
79964          * the request through rejection.
79965          * @returns {Promise<ClusterContract>} Promise to the
79966          * cluster reconstruction.
79967          * @throws Rejects the promise on errors.
79968          */
79969         getCluster(url, abort) {
79970             return Promise.reject(new MapillaryError("Not implemented"));
79971         }
79972         /**
79973          * Get spatial images.
79974          *
79975          * @param {Array<string>} imageIds - The ids for the
79976          * images to retrieve.
79977          * @returns {Promise<SpatialImagesContract>} Promise to
79978          * the spatial images of the requested image ids.
79979          * @throws Rejects the promise on errors.
79980          */
79981         getSpatialImages(imageIds) {
79982             return Promise.reject(new MapillaryError("Not implemented"));
79983         }
79984         /**
79985          * Get complete images.
79986          *
79987          * @param {Array<string>} imageIds - The ids for the
79988          * images to retrieve.
79989          * @returns {Promise<ImagesContract>} Promise to the images of the
79990          * requested image ids.
79991          * @throws Rejects the promise on errors.
79992          */
79993         getImages(imageIds) {
79994             return Promise.reject(new MapillaryError("Not implemented"));
79995         }
79996         /**
79997          * Get an image as an array buffer.
79998          *
79999          * @param {string} url - URL for image to retrieve.
80000          * @param {Promise<void>} [abort] - Optional promise for aborting
80001          * the request through rejection.
80002          * @returns {Promise<ArrayBuffer>} Promise to the array
80003          * buffer containing the image.
80004          * @throws Rejects the promise on errors.
80005          */
80006         getImageBuffer(url, abort) {
80007             return Promise.reject(new MapillaryError("Not implemented"));
80008         }
80009         /**
80010          * Get image tiles urls for a tile level.
80011          *
80012          * @param {ImageTilesRequestContract} tiles - Tiles to request
80013          * @returns {Promise<ImageTilesContract>} Promise to the
80014          * image tiles response contract
80015          *
80016          * @throws Rejects the promise on errors.
80017          *
80018          * @example
80019          * ```js
80020          * var tileRequest = { imageId: 'image-id', z: 12 };
80021          * provider.getImageTiles(tileRequest)
80022          *   .then((response) => console.log(response));
80023          * ```
80024          */
80025         getImageTiles(tiles) {
80026             return Promise.reject(new MapillaryError("Not implemented"));
80027         }
80028         /**
80029          * Get a mesh.
80030          *
80031          * @param {string} url - URL for mesh to retrieve.
80032          * @param {Promise<void>} [abort] - Optional promise for aborting
80033          * the request through rejection.
80034          * @returns {Promise<MeshContract>} Promise to the mesh.
80035          * @throws Rejects the promise on errors.
80036          */
80037         getMesh(url, abort) {
80038             return Promise.reject(new MapillaryError("Not implemented"));
80039         }
80040         /**
80041          * Get sequence.
80042          *
80043          * @param {Array<string>} sequenceId - The id for the
80044          * sequence to retrieve.
80045          * @returns {Promise} Promise to the sequences of the
80046          * requested image ids.
80047          * @throws Rejects the promise on errors.
80048          */
80049         getSequence(sequenceId) {
80050             return Promise.reject(new MapillaryError("Not implemented"));
80051         }
80052         off(type, handler) {
80053             super.off(type, handler);
80054         }
80055         on(type, handler) {
80056             super.on(type, handler);
80057         }
80058         /**
80059          * Set an access token for authenticated API requests of
80060          * protected resources.
80061          *
80062          * @param {string} [accessToken] accessToken - User access
80063          * token or client access token.
80064          */
80065         setAccessToken(accessToken) {
80066             throw new MapillaryError("Not implemented");
80067         }
80068     }
80069
80070     /*
80071      Copyright 2013 Daniel Wirtz <dcode@dcode.io>
80072      Copyright 2009 The Closure Library Authors. All Rights Reserved.
80073
80074      Licensed under the Apache License, Version 2.0 (the "License");
80075      you may not use this file except in compliance with the License.
80076      You may obtain a copy of the License at
80077
80078      http://www.apache.org/licenses/LICENSE-2.0
80079
80080      Unless required by applicable law or agreed to in writing, software
80081      distributed under the License is distributed on an "AS-IS" BASIS,
80082      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80083      See the License for the specific language governing permissions and
80084      limitations under the License.
80085      */
80086
80087     var long = createCommonjsModule(function (module) {
80088     /**
80089      * @license long.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
80090      * Released under the Apache License, Version 2.0
80091      * see: https://github.com/dcodeIO/long.js for details
80092      */
80093     (function(global, factory) {
80094
80095         /* AMD */ if (typeof commonjsRequire === 'function' && 'object' === "object" && module && module["exports"])
80096             module["exports"] = factory();
80097         /* Global */ else
80098             (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = factory();
80099
80100     })(commonjsGlobal, function() {
80101
80102         /**
80103          * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
80104          *  See the from* functions below for more convenient ways of constructing Longs.
80105          * @exports Long
80106          * @class A Long class for representing a 64 bit two's-complement integer value.
80107          * @param {number} low The low (signed) 32 bits of the long
80108          * @param {number} high The high (signed) 32 bits of the long
80109          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
80110          * @constructor
80111          */
80112         function Long(low, high, unsigned) {
80113
80114             /**
80115              * The low 32 bits as a signed value.
80116              * @type {number}
80117              */
80118             this.low = low | 0;
80119
80120             /**
80121              * The high 32 bits as a signed value.
80122              * @type {number}
80123              */
80124             this.high = high | 0;
80125
80126             /**
80127              * Whether unsigned or not.
80128              * @type {boolean}
80129              */
80130             this.unsigned = !!unsigned;
80131         }
80132
80133         // The internal representation of a long is the two given signed, 32-bit values.
80134         // We use 32-bit pieces because these are the size of integers on which
80135         // Javascript performs bit-operations.  For operations like addition and
80136         // multiplication, we split each number into 16 bit pieces, which can easily be
80137         // multiplied within Javascript's floating-point representation without overflow
80138         // or change in sign.
80139         //
80140         // In the algorithms below, we frequently reduce the negative case to the
80141         // positive case by negating the input(s) and then post-processing the result.
80142         // Note that we must ALWAYS check specially whether those values are MIN_VALUE
80143         // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
80144         // a positive number, it overflows back into a negative).  Not handling this
80145         // case would often result in infinite recursion.
80146         //
80147         // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
80148         // methods on which they depend.
80149
80150         /**
80151          * An indicator used to reliably determine if an object is a Long or not.
80152          * @type {boolean}
80153          * @const
80154          * @private
80155          */
80156         Long.prototype.__isLong__;
80157
80158         Object.defineProperty(Long.prototype, "__isLong__", {
80159             value: true,
80160             enumerable: false,
80161             configurable: false
80162         });
80163
80164         /**
80165          * @function
80166          * @param {*} obj Object
80167          * @returns {boolean}
80168          * @inner
80169          */
80170         function isLong(obj) {
80171             return (obj && obj["__isLong__"]) === true;
80172         }
80173
80174         /**
80175          * Tests if the specified object is a Long.
80176          * @function
80177          * @param {*} obj Object
80178          * @returns {boolean}
80179          */
80180         Long.isLong = isLong;
80181
80182         /**
80183          * A cache of the Long representations of small integer values.
80184          * @type {!Object}
80185          * @inner
80186          */
80187         var INT_CACHE = {};
80188
80189         /**
80190          * A cache of the Long representations of small unsigned integer values.
80191          * @type {!Object}
80192          * @inner
80193          */
80194         var UINT_CACHE = {};
80195
80196         /**
80197          * @param {number} value
80198          * @param {boolean=} unsigned
80199          * @returns {!Long}
80200          * @inner
80201          */
80202         function fromInt(value, unsigned) {
80203             var obj, cachedObj, cache;
80204             if (unsigned) {
80205                 value >>>= 0;
80206                 if (cache = (0 <= value && value < 256)) {
80207                     cachedObj = UINT_CACHE[value];
80208                     if (cachedObj)
80209                         return cachedObj;
80210                 }
80211                 obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
80212                 if (cache)
80213                     UINT_CACHE[value] = obj;
80214                 return obj;
80215             } else {
80216                 value |= 0;
80217                 if (cache = (-128 <= value && value < 128)) {
80218                     cachedObj = INT_CACHE[value];
80219                     if (cachedObj)
80220                         return cachedObj;
80221                 }
80222                 obj = fromBits(value, value < 0 ? -1 : 0, false);
80223                 if (cache)
80224                     INT_CACHE[value] = obj;
80225                 return obj;
80226             }
80227         }
80228
80229         /**
80230          * Returns a Long representing the given 32 bit integer value.
80231          * @function
80232          * @param {number} value The 32 bit integer in question
80233          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
80234          * @returns {!Long} The corresponding Long value
80235          */
80236         Long.fromInt = fromInt;
80237
80238         /**
80239          * @param {number} value
80240          * @param {boolean=} unsigned
80241          * @returns {!Long}
80242          * @inner
80243          */
80244         function fromNumber(value, unsigned) {
80245             if (isNaN(value) || !isFinite(value))
80246                 return unsigned ? UZERO : ZERO;
80247             if (unsigned) {
80248                 if (value < 0)
80249                     return UZERO;
80250                 if (value >= TWO_PWR_64_DBL)
80251                     return MAX_UNSIGNED_VALUE;
80252             } else {
80253                 if (value <= -TWO_PWR_63_DBL)
80254                     return MIN_VALUE;
80255                 if (value + 1 >= TWO_PWR_63_DBL)
80256                     return MAX_VALUE;
80257             }
80258             if (value < 0)
80259                 return fromNumber(-value, unsigned).neg();
80260             return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
80261         }
80262
80263         /**
80264          * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
80265          * @function
80266          * @param {number} value The number in question
80267          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
80268          * @returns {!Long} The corresponding Long value
80269          */
80270         Long.fromNumber = fromNumber;
80271
80272         /**
80273          * @param {number} lowBits
80274          * @param {number} highBits
80275          * @param {boolean=} unsigned
80276          * @returns {!Long}
80277          * @inner
80278          */
80279         function fromBits(lowBits, highBits, unsigned) {
80280             return new Long(lowBits, highBits, unsigned);
80281         }
80282
80283         /**
80284          * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
80285          *  assumed to use 32 bits.
80286          * @function
80287          * @param {number} lowBits The low 32 bits
80288          * @param {number} highBits The high 32 bits
80289          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
80290          * @returns {!Long} The corresponding Long value
80291          */
80292         Long.fromBits = fromBits;
80293
80294         /**
80295          * @function
80296          * @param {number} base
80297          * @param {number} exponent
80298          * @returns {number}
80299          * @inner
80300          */
80301         var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
80302
80303         /**
80304          * @param {string} str
80305          * @param {(boolean|number)=} unsigned
80306          * @param {number=} radix
80307          * @returns {!Long}
80308          * @inner
80309          */
80310         function fromString(str, unsigned, radix) {
80311             if (str.length === 0)
80312                 throw Error('empty string');
80313             if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
80314                 return ZERO;
80315             if (typeof unsigned === 'number') {
80316                 // For goog.math.long compatibility
80317                 radix = unsigned,
80318                 unsigned = false;
80319             } else {
80320                 unsigned = !! unsigned;
80321             }
80322             radix = radix || 10;
80323             if (radix < 2 || 36 < radix)
80324                 throw RangeError('radix');
80325
80326             var p;
80327             if ((p = str.indexOf('-')) > 0)
80328                 throw Error('interior hyphen');
80329             else if (p === 0) {
80330                 return fromString(str.substring(1), unsigned, radix).neg();
80331             }
80332
80333             // Do several (8) digits each time through the loop, so as to
80334             // minimize the calls to the very expensive emulated div.
80335             var radixToPower = fromNumber(pow_dbl(radix, 8));
80336
80337             var result = ZERO;
80338             for (var i = 0; i < str.length; i += 8) {
80339                 var size = Math.min(8, str.length - i),
80340                     value = parseInt(str.substring(i, i + size), radix);
80341                 if (size < 8) {
80342                     var power = fromNumber(pow_dbl(radix, size));
80343                     result = result.mul(power).add(fromNumber(value));
80344                 } else {
80345                     result = result.mul(radixToPower);
80346                     result = result.add(fromNumber(value));
80347                 }
80348             }
80349             result.unsigned = unsigned;
80350             return result;
80351         }
80352
80353         /**
80354          * Returns a Long representation of the given string, written using the specified radix.
80355          * @function
80356          * @param {string} str The textual representation of the Long
80357          * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
80358          * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
80359          * @returns {!Long} The corresponding Long value
80360          */
80361         Long.fromString = fromString;
80362
80363         /**
80364          * @function
80365          * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val
80366          * @returns {!Long}
80367          * @inner
80368          */
80369         function fromValue(val) {
80370             if (val /* is compatible */ instanceof Long)
80371                 return val;
80372             if (typeof val === 'number')
80373                 return fromNumber(val);
80374             if (typeof val === 'string')
80375                 return fromString(val);
80376             // Throws for non-objects, converts non-instanceof Long:
80377             return fromBits(val.low, val.high, val.unsigned);
80378         }
80379
80380         /**
80381          * Converts the specified value to a Long.
80382          * @function
80383          * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
80384          * @returns {!Long}
80385          */
80386         Long.fromValue = fromValue;
80387
80388         // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
80389         // no runtime penalty for these.
80390
80391         /**
80392          * @type {number}
80393          * @const
80394          * @inner
80395          */
80396         var TWO_PWR_16_DBL = 1 << 16;
80397
80398         /**
80399          * @type {number}
80400          * @const
80401          * @inner
80402          */
80403         var TWO_PWR_24_DBL = 1 << 24;
80404
80405         /**
80406          * @type {number}
80407          * @const
80408          * @inner
80409          */
80410         var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
80411
80412         /**
80413          * @type {number}
80414          * @const
80415          * @inner
80416          */
80417         var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
80418
80419         /**
80420          * @type {number}
80421          * @const
80422          * @inner
80423          */
80424         var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
80425
80426         /**
80427          * @type {!Long}
80428          * @const
80429          * @inner
80430          */
80431         var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
80432
80433         /**
80434          * @type {!Long}
80435          * @inner
80436          */
80437         var ZERO = fromInt(0);
80438
80439         /**
80440          * Signed zero.
80441          * @type {!Long}
80442          */
80443         Long.ZERO = ZERO;
80444
80445         /**
80446          * @type {!Long}
80447          * @inner
80448          */
80449         var UZERO = fromInt(0, true);
80450
80451         /**
80452          * Unsigned zero.
80453          * @type {!Long}
80454          */
80455         Long.UZERO = UZERO;
80456
80457         /**
80458          * @type {!Long}
80459          * @inner
80460          */
80461         var ONE = fromInt(1);
80462
80463         /**
80464          * Signed one.
80465          * @type {!Long}
80466          */
80467         Long.ONE = ONE;
80468
80469         /**
80470          * @type {!Long}
80471          * @inner
80472          */
80473         var UONE = fromInt(1, true);
80474
80475         /**
80476          * Unsigned one.
80477          * @type {!Long}
80478          */
80479         Long.UONE = UONE;
80480
80481         /**
80482          * @type {!Long}
80483          * @inner
80484          */
80485         var NEG_ONE = fromInt(-1);
80486
80487         /**
80488          * Signed negative one.
80489          * @type {!Long}
80490          */
80491         Long.NEG_ONE = NEG_ONE;
80492
80493         /**
80494          * @type {!Long}
80495          * @inner
80496          */
80497         var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
80498
80499         /**
80500          * Maximum signed value.
80501          * @type {!Long}
80502          */
80503         Long.MAX_VALUE = MAX_VALUE;
80504
80505         /**
80506          * @type {!Long}
80507          * @inner
80508          */
80509         var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
80510
80511         /**
80512          * Maximum unsigned value.
80513          * @type {!Long}
80514          */
80515         Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
80516
80517         /**
80518          * @type {!Long}
80519          * @inner
80520          */
80521         var MIN_VALUE = fromBits(0, 0x80000000|0, false);
80522
80523         /**
80524          * Minimum signed value.
80525          * @type {!Long}
80526          */
80527         Long.MIN_VALUE = MIN_VALUE;
80528
80529         /**
80530          * @alias Long.prototype
80531          * @inner
80532          */
80533         var LongPrototype = Long.prototype;
80534
80535         /**
80536          * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
80537          * @returns {number}
80538          */
80539         LongPrototype.toInt = function toInt() {
80540             return this.unsigned ? this.low >>> 0 : this.low;
80541         };
80542
80543         /**
80544          * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
80545          * @returns {number}
80546          */
80547         LongPrototype.toNumber = function toNumber() {
80548             if (this.unsigned)
80549                 return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
80550             return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
80551         };
80552
80553         /**
80554          * Converts the Long to a string written in the specified radix.
80555          * @param {number=} radix Radix (2-36), defaults to 10
80556          * @returns {string}
80557          * @override
80558          * @throws {RangeError} If `radix` is out of range
80559          */
80560         LongPrototype.toString = function toString(radix) {
80561             radix = radix || 10;
80562             if (radix < 2 || 36 < radix)
80563                 throw RangeError('radix');
80564             if (this.isZero())
80565                 return '0';
80566             if (this.isNegative()) { // Unsigned Longs are never negative
80567                 if (this.eq(MIN_VALUE)) {
80568                     // We need to change the Long value before it can be negated, so we remove
80569                     // the bottom-most digit in this base and then recurse to do the rest.
80570                     var radixLong = fromNumber(radix),
80571                         div = this.div(radixLong),
80572                         rem1 = div.mul(radixLong).sub(this);
80573                     return div.toString(radix) + rem1.toInt().toString(radix);
80574                 } else
80575                     return '-' + this.neg().toString(radix);
80576             }
80577
80578             // Do several (6) digits each time through the loop, so as to
80579             // minimize the calls to the very expensive emulated div.
80580             var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
80581                 rem = this;
80582             var result = '';
80583             while (true) {
80584                 var remDiv = rem.div(radixToPower),
80585                     intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
80586                     digits = intval.toString(radix);
80587                 rem = remDiv;
80588                 if (rem.isZero())
80589                     return digits + result;
80590                 else {
80591                     while (digits.length < 6)
80592                         digits = '0' + digits;
80593                     result = '' + digits + result;
80594                 }
80595             }
80596         };
80597
80598         /**
80599          * Gets the high 32 bits as a signed integer.
80600          * @returns {number} Signed high bits
80601          */
80602         LongPrototype.getHighBits = function getHighBits() {
80603             return this.high;
80604         };
80605
80606         /**
80607          * Gets the high 32 bits as an unsigned integer.
80608          * @returns {number} Unsigned high bits
80609          */
80610         LongPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
80611             return this.high >>> 0;
80612         };
80613
80614         /**
80615          * Gets the low 32 bits as a signed integer.
80616          * @returns {number} Signed low bits
80617          */
80618         LongPrototype.getLowBits = function getLowBits() {
80619             return this.low;
80620         };
80621
80622         /**
80623          * Gets the low 32 bits as an unsigned integer.
80624          * @returns {number} Unsigned low bits
80625          */
80626         LongPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
80627             return this.low >>> 0;
80628         };
80629
80630         /**
80631          * Gets the number of bits needed to represent the absolute value of this Long.
80632          * @returns {number}
80633          */
80634         LongPrototype.getNumBitsAbs = function getNumBitsAbs() {
80635             if (this.isNegative()) // Unsigned Longs are never negative
80636                 return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
80637             var val = this.high != 0 ? this.high : this.low;
80638             for (var bit = 31; bit > 0; bit--)
80639                 if ((val & (1 << bit)) != 0)
80640                     break;
80641             return this.high != 0 ? bit + 33 : bit + 1;
80642         };
80643
80644         /**
80645          * Tests if this Long's value equals zero.
80646          * @returns {boolean}
80647          */
80648         LongPrototype.isZero = function isZero() {
80649             return this.high === 0 && this.low === 0;
80650         };
80651
80652         /**
80653          * Tests if this Long's value is negative.
80654          * @returns {boolean}
80655          */
80656         LongPrototype.isNegative = function isNegative() {
80657             return !this.unsigned && this.high < 0;
80658         };
80659
80660         /**
80661          * Tests if this Long's value is positive.
80662          * @returns {boolean}
80663          */
80664         LongPrototype.isPositive = function isPositive() {
80665             return this.unsigned || this.high >= 0;
80666         };
80667
80668         /**
80669          * Tests if this Long's value is odd.
80670          * @returns {boolean}
80671          */
80672         LongPrototype.isOdd = function isOdd() {
80673             return (this.low & 1) === 1;
80674         };
80675
80676         /**
80677          * Tests if this Long's value is even.
80678          * @returns {boolean}
80679          */
80680         LongPrototype.isEven = function isEven() {
80681             return (this.low & 1) === 0;
80682         };
80683
80684         /**
80685          * Tests if this Long's value equals the specified's.
80686          * @param {!Long|number|string} other Other value
80687          * @returns {boolean}
80688          */
80689         LongPrototype.equals = function equals(other) {
80690             if (!isLong(other))
80691                 other = fromValue(other);
80692             if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
80693                 return false;
80694             return this.high === other.high && this.low === other.low;
80695         };
80696
80697         /**
80698          * Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}.
80699          * @function
80700          * @param {!Long|number|string} other Other value
80701          * @returns {boolean}
80702          */
80703         LongPrototype.eq = LongPrototype.equals;
80704
80705         /**
80706          * Tests if this Long's value differs from the specified's.
80707          * @param {!Long|number|string} other Other value
80708          * @returns {boolean}
80709          */
80710         LongPrototype.notEquals = function notEquals(other) {
80711             return !this.eq(/* validates */ other);
80712         };
80713
80714         /**
80715          * Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
80716          * @function
80717          * @param {!Long|number|string} other Other value
80718          * @returns {boolean}
80719          */
80720         LongPrototype.neq = LongPrototype.notEquals;
80721
80722         /**
80723          * Tests if this Long's value is less than the specified's.
80724          * @param {!Long|number|string} other Other value
80725          * @returns {boolean}
80726          */
80727         LongPrototype.lessThan = function lessThan(other) {
80728             return this.comp(/* validates */ other) < 0;
80729         };
80730
80731         /**
80732          * Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}.
80733          * @function
80734          * @param {!Long|number|string} other Other value
80735          * @returns {boolean}
80736          */
80737         LongPrototype.lt = LongPrototype.lessThan;
80738
80739         /**
80740          * Tests if this Long's value is less than or equal the specified's.
80741          * @param {!Long|number|string} other Other value
80742          * @returns {boolean}
80743          */
80744         LongPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
80745             return this.comp(/* validates */ other) <= 0;
80746         };
80747
80748         /**
80749          * Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
80750          * @function
80751          * @param {!Long|number|string} other Other value
80752          * @returns {boolean}
80753          */
80754         LongPrototype.lte = LongPrototype.lessThanOrEqual;
80755
80756         /**
80757          * Tests if this Long's value is greater than the specified's.
80758          * @param {!Long|number|string} other Other value
80759          * @returns {boolean}
80760          */
80761         LongPrototype.greaterThan = function greaterThan(other) {
80762             return this.comp(/* validates */ other) > 0;
80763         };
80764
80765         /**
80766          * Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}.
80767          * @function
80768          * @param {!Long|number|string} other Other value
80769          * @returns {boolean}
80770          */
80771         LongPrototype.gt = LongPrototype.greaterThan;
80772
80773         /**
80774          * Tests if this Long's value is greater than or equal the specified's.
80775          * @param {!Long|number|string} other Other value
80776          * @returns {boolean}
80777          */
80778         LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
80779             return this.comp(/* validates */ other) >= 0;
80780         };
80781
80782         /**
80783          * Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
80784          * @function
80785          * @param {!Long|number|string} other Other value
80786          * @returns {boolean}
80787          */
80788         LongPrototype.gte = LongPrototype.greaterThanOrEqual;
80789
80790         /**
80791          * Compares this Long's value with the specified's.
80792          * @param {!Long|number|string} other Other value
80793          * @returns {number} 0 if they are the same, 1 if the this is greater and -1
80794          *  if the given one is greater
80795          */
80796         LongPrototype.compare = function compare(other) {
80797             if (!isLong(other))
80798                 other = fromValue(other);
80799             if (this.eq(other))
80800                 return 0;
80801             var thisNeg = this.isNegative(),
80802                 otherNeg = other.isNegative();
80803             if (thisNeg && !otherNeg)
80804                 return -1;
80805             if (!thisNeg && otherNeg)
80806                 return 1;
80807             // At this point the sign bits are the same
80808             if (!this.unsigned)
80809                 return this.sub(other).isNegative() ? -1 : 1;
80810             // Both are positive if at least one is unsigned
80811             return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
80812         };
80813
80814         /**
80815          * Compares this Long's value with the specified's. This is an alias of {@link Long#compare}.
80816          * @function
80817          * @param {!Long|number|string} other Other value
80818          * @returns {number} 0 if they are the same, 1 if the this is greater and -1
80819          *  if the given one is greater
80820          */
80821         LongPrototype.comp = LongPrototype.compare;
80822
80823         /**
80824          * Negates this Long's value.
80825          * @returns {!Long} Negated Long
80826          */
80827         LongPrototype.negate = function negate() {
80828             if (!this.unsigned && this.eq(MIN_VALUE))
80829                 return MIN_VALUE;
80830             return this.not().add(ONE);
80831         };
80832
80833         /**
80834          * Negates this Long's value. This is an alias of {@link Long#negate}.
80835          * @function
80836          * @returns {!Long} Negated Long
80837          */
80838         LongPrototype.neg = LongPrototype.negate;
80839
80840         /**
80841          * Returns the sum of this and the specified Long.
80842          * @param {!Long|number|string} addend Addend
80843          * @returns {!Long} Sum
80844          */
80845         LongPrototype.add = function add(addend) {
80846             if (!isLong(addend))
80847                 addend = fromValue(addend);
80848
80849             // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
80850
80851             var a48 = this.high >>> 16;
80852             var a32 = this.high & 0xFFFF;
80853             var a16 = this.low >>> 16;
80854             var a00 = this.low & 0xFFFF;
80855
80856             var b48 = addend.high >>> 16;
80857             var b32 = addend.high & 0xFFFF;
80858             var b16 = addend.low >>> 16;
80859             var b00 = addend.low & 0xFFFF;
80860
80861             var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
80862             c00 += a00 + b00;
80863             c16 += c00 >>> 16;
80864             c00 &= 0xFFFF;
80865             c16 += a16 + b16;
80866             c32 += c16 >>> 16;
80867             c16 &= 0xFFFF;
80868             c32 += a32 + b32;
80869             c48 += c32 >>> 16;
80870             c32 &= 0xFFFF;
80871             c48 += a48 + b48;
80872             c48 &= 0xFFFF;
80873             return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
80874         };
80875
80876         /**
80877          * Returns the difference of this and the specified Long.
80878          * @param {!Long|number|string} subtrahend Subtrahend
80879          * @returns {!Long} Difference
80880          */
80881         LongPrototype.subtract = function subtract(subtrahend) {
80882             if (!isLong(subtrahend))
80883                 subtrahend = fromValue(subtrahend);
80884             return this.add(subtrahend.neg());
80885         };
80886
80887         /**
80888          * Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}.
80889          * @function
80890          * @param {!Long|number|string} subtrahend Subtrahend
80891          * @returns {!Long} Difference
80892          */
80893         LongPrototype.sub = LongPrototype.subtract;
80894
80895         /**
80896          * Returns the product of this and the specified Long.
80897          * @param {!Long|number|string} multiplier Multiplier
80898          * @returns {!Long} Product
80899          */
80900         LongPrototype.multiply = function multiply(multiplier) {
80901             if (this.isZero())
80902                 return ZERO;
80903             if (!isLong(multiplier))
80904                 multiplier = fromValue(multiplier);
80905             if (multiplier.isZero())
80906                 return ZERO;
80907             if (this.eq(MIN_VALUE))
80908                 return multiplier.isOdd() ? MIN_VALUE : ZERO;
80909             if (multiplier.eq(MIN_VALUE))
80910                 return this.isOdd() ? MIN_VALUE : ZERO;
80911
80912             if (this.isNegative()) {
80913                 if (multiplier.isNegative())
80914                     return this.neg().mul(multiplier.neg());
80915                 else
80916                     return this.neg().mul(multiplier).neg();
80917             } else if (multiplier.isNegative())
80918                 return this.mul(multiplier.neg()).neg();
80919
80920             // If both longs are small, use float multiplication
80921             if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
80922                 return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
80923
80924             // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
80925             // We can skip products that would overflow.
80926
80927             var a48 = this.high >>> 16;
80928             var a32 = this.high & 0xFFFF;
80929             var a16 = this.low >>> 16;
80930             var a00 = this.low & 0xFFFF;
80931
80932             var b48 = multiplier.high >>> 16;
80933             var b32 = multiplier.high & 0xFFFF;
80934             var b16 = multiplier.low >>> 16;
80935             var b00 = multiplier.low & 0xFFFF;
80936
80937             var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
80938             c00 += a00 * b00;
80939             c16 += c00 >>> 16;
80940             c00 &= 0xFFFF;
80941             c16 += a16 * b00;
80942             c32 += c16 >>> 16;
80943             c16 &= 0xFFFF;
80944             c16 += a00 * b16;
80945             c32 += c16 >>> 16;
80946             c16 &= 0xFFFF;
80947             c32 += a32 * b00;
80948             c48 += c32 >>> 16;
80949             c32 &= 0xFFFF;
80950             c32 += a16 * b16;
80951             c48 += c32 >>> 16;
80952             c32 &= 0xFFFF;
80953             c32 += a00 * b32;
80954             c48 += c32 >>> 16;
80955             c32 &= 0xFFFF;
80956             c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
80957             c48 &= 0xFFFF;
80958             return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
80959         };
80960
80961         /**
80962          * Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}.
80963          * @function
80964          * @param {!Long|number|string} multiplier Multiplier
80965          * @returns {!Long} Product
80966          */
80967         LongPrototype.mul = LongPrototype.multiply;
80968
80969         /**
80970          * Returns this Long divided by the specified. The result is signed if this Long is signed or
80971          *  unsigned if this Long is unsigned.
80972          * @param {!Long|number|string} divisor Divisor
80973          * @returns {!Long} Quotient
80974          */
80975         LongPrototype.divide = function divide(divisor) {
80976             if (!isLong(divisor))
80977                 divisor = fromValue(divisor);
80978             if (divisor.isZero())
80979                 throw Error('division by zero');
80980             if (this.isZero())
80981                 return this.unsigned ? UZERO : ZERO;
80982             var approx, rem, res;
80983             if (!this.unsigned) {
80984                 // This section is only relevant for signed longs and is derived from the
80985                 // closure library as a whole.
80986                 if (this.eq(MIN_VALUE)) {
80987                     if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
80988                         return MIN_VALUE;  // recall that -MIN_VALUE == MIN_VALUE
80989                     else if (divisor.eq(MIN_VALUE))
80990                         return ONE;
80991                     else {
80992                         // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
80993                         var halfThis = this.shr(1);
80994                         approx = halfThis.div(divisor).shl(1);
80995                         if (approx.eq(ZERO)) {
80996                             return divisor.isNegative() ? ONE : NEG_ONE;
80997                         } else {
80998                             rem = this.sub(divisor.mul(approx));
80999                             res = approx.add(rem.div(divisor));
81000                             return res;
81001                         }
81002                     }
81003                 } else if (divisor.eq(MIN_VALUE))
81004                     return this.unsigned ? UZERO : ZERO;
81005                 if (this.isNegative()) {
81006                     if (divisor.isNegative())
81007                         return this.neg().div(divisor.neg());
81008                     return this.neg().div(divisor).neg();
81009                 } else if (divisor.isNegative())
81010                     return this.div(divisor.neg()).neg();
81011                 res = ZERO;
81012             } else {
81013                 // The algorithm below has not been made for unsigned longs. It's therefore
81014                 // required to take special care of the MSB prior to running it.
81015                 if (!divisor.unsigned)
81016                     divisor = divisor.toUnsigned();
81017                 if (divisor.gt(this))
81018                     return UZERO;
81019                 if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
81020                     return UONE;
81021                 res = UZERO;
81022             }
81023
81024             // Repeat the following until the remainder is less than other:  find a
81025             // floating-point that approximates remainder / other *from below*, add this
81026             // into the result, and subtract it from the remainder.  It is critical that
81027             // the approximate value is less than or equal to the real value so that the
81028             // remainder never becomes negative.
81029             rem = this;
81030             while (rem.gte(divisor)) {
81031                 // Approximate the result of division. This may be a little greater or
81032                 // smaller than the actual value.
81033                 approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
81034
81035                 // We will tweak the approximate result by changing it in the 48-th digit or
81036                 // the smallest non-fractional digit, whichever is larger.
81037                 var log2 = Math.ceil(Math.log(approx) / Math.LN2),
81038                     delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
81039
81040                 // Decrease the approximation until it is smaller than the remainder.  Note
81041                 // that if it is too large, the product overflows and is negative.
81042                     approxRes = fromNumber(approx),
81043                     approxRem = approxRes.mul(divisor);
81044                 while (approxRem.isNegative() || approxRem.gt(rem)) {
81045                     approx -= delta;
81046                     approxRes = fromNumber(approx, this.unsigned);
81047                     approxRem = approxRes.mul(divisor);
81048                 }
81049
81050                 // We know the answer can't be zero... and actually, zero would cause
81051                 // infinite recursion since we would make no progress.
81052                 if (approxRes.isZero())
81053                     approxRes = ONE;
81054
81055                 res = res.add(approxRes);
81056                 rem = rem.sub(approxRem);
81057             }
81058             return res;
81059         };
81060
81061         /**
81062          * Returns this Long divided by the specified. This is an alias of {@link Long#divide}.
81063          * @function
81064          * @param {!Long|number|string} divisor Divisor
81065          * @returns {!Long} Quotient
81066          */
81067         LongPrototype.div = LongPrototype.divide;
81068
81069         /**
81070          * Returns this Long modulo the specified.
81071          * @param {!Long|number|string} divisor Divisor
81072          * @returns {!Long} Remainder
81073          */
81074         LongPrototype.modulo = function modulo(divisor) {
81075             if (!isLong(divisor))
81076                 divisor = fromValue(divisor);
81077             return this.sub(this.div(divisor).mul(divisor));
81078         };
81079
81080         /**
81081          * Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
81082          * @function
81083          * @param {!Long|number|string} divisor Divisor
81084          * @returns {!Long} Remainder
81085          */
81086         LongPrototype.mod = LongPrototype.modulo;
81087
81088         /**
81089          * Returns the bitwise NOT of this Long.
81090          * @returns {!Long}
81091          */
81092         LongPrototype.not = function not() {
81093             return fromBits(~this.low, ~this.high, this.unsigned);
81094         };
81095
81096         /**
81097          * Returns the bitwise AND of this Long and the specified.
81098          * @param {!Long|number|string} other Other Long
81099          * @returns {!Long}
81100          */
81101         LongPrototype.and = function and(other) {
81102             if (!isLong(other))
81103                 other = fromValue(other);
81104             return fromBits(this.low & other.low, this.high & other.high, this.unsigned);
81105         };
81106
81107         /**
81108          * Returns the bitwise OR of this Long and the specified.
81109          * @param {!Long|number|string} other Other Long
81110          * @returns {!Long}
81111          */
81112         LongPrototype.or = function or(other) {
81113             if (!isLong(other))
81114                 other = fromValue(other);
81115             return fromBits(this.low | other.low, this.high | other.high, this.unsigned);
81116         };
81117
81118         /**
81119          * Returns the bitwise XOR of this Long and the given one.
81120          * @param {!Long|number|string} other Other Long
81121          * @returns {!Long}
81122          */
81123         LongPrototype.xor = function xor(other) {
81124             if (!isLong(other))
81125                 other = fromValue(other);
81126             return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
81127         };
81128
81129         /**
81130          * Returns this Long with bits shifted to the left by the given amount.
81131          * @param {number|!Long} numBits Number of bits
81132          * @returns {!Long} Shifted Long
81133          */
81134         LongPrototype.shiftLeft = function shiftLeft(numBits) {
81135             if (isLong(numBits))
81136                 numBits = numBits.toInt();
81137             if ((numBits &= 63) === 0)
81138                 return this;
81139             else if (numBits < 32)
81140                 return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
81141             else
81142                 return fromBits(0, this.low << (numBits - 32), this.unsigned);
81143         };
81144
81145         /**
81146          * Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}.
81147          * @function
81148          * @param {number|!Long} numBits Number of bits
81149          * @returns {!Long} Shifted Long
81150          */
81151         LongPrototype.shl = LongPrototype.shiftLeft;
81152
81153         /**
81154          * Returns this Long with bits arithmetically shifted to the right by the given amount.
81155          * @param {number|!Long} numBits Number of bits
81156          * @returns {!Long} Shifted Long
81157          */
81158         LongPrototype.shiftRight = function shiftRight(numBits) {
81159             if (isLong(numBits))
81160                 numBits = numBits.toInt();
81161             if ((numBits &= 63) === 0)
81162                 return this;
81163             else if (numBits < 32)
81164                 return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
81165             else
81166                 return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
81167         };
81168
81169         /**
81170          * Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}.
81171          * @function
81172          * @param {number|!Long} numBits Number of bits
81173          * @returns {!Long} Shifted Long
81174          */
81175         LongPrototype.shr = LongPrototype.shiftRight;
81176
81177         /**
81178          * Returns this Long with bits logically shifted to the right by the given amount.
81179          * @param {number|!Long} numBits Number of bits
81180          * @returns {!Long} Shifted Long
81181          */
81182         LongPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
81183             if (isLong(numBits))
81184                 numBits = numBits.toInt();
81185             numBits &= 63;
81186             if (numBits === 0)
81187                 return this;
81188             else {
81189                 var high = this.high;
81190                 if (numBits < 32) {
81191                     var low = this.low;
81192                     return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
81193                 } else if (numBits === 32)
81194                     return fromBits(high, 0, this.unsigned);
81195                 else
81196                     return fromBits(high >>> (numBits - 32), 0, this.unsigned);
81197             }
81198         };
81199
81200         /**
81201          * Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
81202          * @function
81203          * @param {number|!Long} numBits Number of bits
81204          * @returns {!Long} Shifted Long
81205          */
81206         LongPrototype.shru = LongPrototype.shiftRightUnsigned;
81207
81208         /**
81209          * Converts this Long to signed.
81210          * @returns {!Long} Signed long
81211          */
81212         LongPrototype.toSigned = function toSigned() {
81213             if (!this.unsigned)
81214                 return this;
81215             return fromBits(this.low, this.high, false);
81216         };
81217
81218         /**
81219          * Converts this Long to unsigned.
81220          * @returns {!Long} Unsigned long
81221          */
81222         LongPrototype.toUnsigned = function toUnsigned() {
81223             if (this.unsigned)
81224                 return this;
81225             return fromBits(this.low, this.high, true);
81226         };
81227
81228         /**
81229          * Converts this Long to its byte representation.
81230          * @param {boolean=} le Whether little or big endian, defaults to big endian
81231          * @returns {!Array.<number>} Byte representation
81232          */
81233         LongPrototype.toBytes = function(le) {
81234             return le ? this.toBytesLE() : this.toBytesBE();
81235         };
81236
81237         /**
81238          * Converts this Long to its little endian byte representation.
81239          * @returns {!Array.<number>} Little endian byte representation
81240          */
81241         LongPrototype.toBytesLE = function() {
81242             var hi = this.high,
81243                 lo = this.low;
81244             return [
81245                  lo         & 0xff,
81246                 (lo >>>  8) & 0xff,
81247                 (lo >>> 16) & 0xff,
81248                 (lo >>> 24) & 0xff,
81249                  hi         & 0xff,
81250                 (hi >>>  8) & 0xff,
81251                 (hi >>> 16) & 0xff,
81252                 (hi >>> 24) & 0xff
81253             ];
81254         };
81255
81256         /**
81257          * Converts this Long to its big endian byte representation.
81258          * @returns {!Array.<number>} Big endian byte representation
81259          */
81260         LongPrototype.toBytesBE = function() {
81261             var hi = this.high,
81262                 lo = this.low;
81263             return [
81264                 (hi >>> 24) & 0xff,
81265                 (hi >>> 16) & 0xff,
81266                 (hi >>>  8) & 0xff,
81267                  hi         & 0xff,
81268                 (lo >>> 24) & 0xff,
81269                 (lo >>> 16) & 0xff,
81270                 (lo >>>  8) & 0xff,
81271                  lo         & 0xff
81272             ];
81273         };
81274
81275         return Long;
81276     });
81277     });
81278
81279     var s2geometry = createCommonjsModule(function (module) {
81280     /// S2 Geometry functions
81281     // the regional scoreboard is based on a level 6 S2 Cell
81282     // - https://docs.google.com/presentation/d/1Hl4KapfAENAOf4gv-pSngKwvS_jwNVHRPZTTDzXXn6Q/view?pli=1#slide=id.i22
81283     // at the time of writing there's no actual API for the intel map to retrieve scoreboard data,
81284     // but it's still useful to plot the score cells on the intel map
81285
81286
81287     // the S2 geometry is based on projecting the earth sphere onto a cube, with some scaling of face coordinates to
81288     // keep things close to approximate equal area for adjacent cells
81289     // to convert a lat,lng into a cell id:
81290     // - convert lat,lng to x,y,z
81291     // - convert x,y,z into face,u,v
81292     // - u,v scaled to s,t with quadratic formula
81293     // - s,t converted to integer i,j offsets
81294     // - i,j converted to a position along a Hubbert space-filling curve
81295     // - combine face,position to get the cell id
81296
81297     //NOTE: compared to the google S2 geometry library, we vary from their code in the following ways
81298     // - cell IDs: they combine face and the hilbert curve position into a single 64 bit number. this gives efficient space
81299     //             and speed. javascript doesn't have appropriate data types, and speed is not cricical, so we use
81300     //             as [face,[bitpair,bitpair,...]] instead
81301     // - i,j: they always use 30 bits, adjusting as needed. we use 0 to (1<<level)-1 instead
81302     //        (so GetSizeIJ for a cell is always 1)
81303
81304     (function (exports) {
81305
81306     var S2 = exports.S2 = { L: {} };
81307
81308     S2.L.LatLng = function (/*Number*/ rawLat, /*Number*/ rawLng, /*Boolean*/ noWrap) {
81309       var lat = parseFloat(rawLat, 10);
81310       var lng = parseFloat(rawLng, 10);
81311
81312       if (isNaN(lat) || isNaN(lng)) {
81313         throw new Error('Invalid LatLng object: (' + rawLat + ', ' + rawLng + ')');
81314       }
81315
81316       if (noWrap !== true) {
81317         lat = Math.max(Math.min(lat, 90), -90);                 // clamp latitude into -90..90
81318         lng = (lng + 180) % 360 + ((lng < -180 || lng === 180) ? 180 : -180);   // wrap longtitude into -180..180
81319       }
81320
81321       return { lat: lat, lng: lng };
81322     };
81323
81324     S2.L.LatLng.DEG_TO_RAD = Math.PI / 180;
81325     S2.L.LatLng.RAD_TO_DEG = 180 / Math.PI;
81326
81327     /*
81328     S2.LatLngToXYZ = function(latLng) {
81329       // http://stackoverflow.com/questions/8981943/lat-long-to-x-y-z-position-in-js-not-working
81330       var lat = latLng.lat;
81331       var lon = latLng.lng;
81332       var DEG_TO_RAD = Math.PI / 180.0;
81333
81334       var phi = lat * DEG_TO_RAD;
81335       var theta = lon * DEG_TO_RAD;
81336
81337       var cosLat = Math.cos(phi);
81338       var sinLat = Math.sin(phi);
81339       var cosLon = Math.cos(theta);
81340       var sinLon = Math.sin(theta);
81341       var rad = 500.0;
81342
81343       return [
81344         rad * cosLat * cosLon
81345       , rad * cosLat * sinLon
81346       , rad * sinLat
81347       ];
81348     };
81349     */
81350     S2.LatLngToXYZ = function(latLng) {
81351       var d2r = S2.L.LatLng.DEG_TO_RAD;
81352
81353       var phi = latLng.lat*d2r;
81354       var theta = latLng.lng*d2r;
81355
81356       var cosphi = Math.cos(phi);
81357
81358       return [Math.cos(theta)*cosphi, Math.sin(theta)*cosphi, Math.sin(phi)];
81359     };
81360
81361     S2.XYZToLatLng = function(xyz) {
81362       var r2d = S2.L.LatLng.RAD_TO_DEG;
81363
81364       var lat = Math.atan2(xyz[2], Math.sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]));
81365       var lng = Math.atan2(xyz[1], xyz[0]);
81366
81367       return S2.L.LatLng(lat*r2d, lng*r2d);
81368     };
81369
81370     var largestAbsComponent = function(xyz) {
81371       var temp = [Math.abs(xyz[0]), Math.abs(xyz[1]), Math.abs(xyz[2])];
81372
81373       if (temp[0] > temp[1]) {
81374         if (temp[0] > temp[2]) {
81375           return 0;
81376         } else {
81377           return 2;
81378         }
81379       } else {
81380         if (temp[1] > temp[2]) {
81381           return 1;
81382         } else {
81383           return 2;
81384         }
81385       }
81386
81387     };
81388
81389     var faceXYZToUV = function(face,xyz) {
81390       var u,v;
81391
81392       switch (face) {
81393         case 0: u =  xyz[1]/xyz[0]; v =  xyz[2]/xyz[0]; break;
81394         case 1: u = -xyz[0]/xyz[1]; v =  xyz[2]/xyz[1]; break;
81395         case 2: u = -xyz[0]/xyz[2]; v = -xyz[1]/xyz[2]; break;
81396         case 3: u =  xyz[2]/xyz[0]; v =  xyz[1]/xyz[0]; break;
81397         case 4: u =  xyz[2]/xyz[1]; v = -xyz[0]/xyz[1]; break;
81398         case 5: u = -xyz[1]/xyz[2]; v = -xyz[0]/xyz[2]; break;
81399         default: throw {error: 'Invalid face'};
81400       }
81401
81402       return [u,v];
81403     };
81404
81405
81406
81407
81408     S2.XYZToFaceUV = function(xyz) {
81409       var face = largestAbsComponent(xyz);
81410
81411       if (xyz[face] < 0) {
81412         face += 3;
81413       }
81414
81415       var uv = faceXYZToUV (face,xyz);
81416
81417       return [face, uv];
81418     };
81419
81420     S2.FaceUVToXYZ = function(face,uv) {
81421       var u = uv[0];
81422       var v = uv[1];
81423
81424       switch (face) {
81425         case 0: return [ 1, u, v];
81426         case 1: return [-u, 1, v];
81427         case 2: return [-u,-v, 1];
81428         case 3: return [-1,-v,-u];
81429         case 4: return [ v,-1,-u];
81430         case 5: return [ v, u,-1];
81431         default: throw {error: 'Invalid face'};
81432       }
81433     };
81434
81435     var singleSTtoUV = function(st) {
81436       if (st >= 0.5) {
81437         return (1/3.0) * (4*st*st - 1);
81438       } else {
81439         return (1/3.0) * (1 - (4*(1-st)*(1-st)));
81440       }
81441     };
81442
81443     S2.STToUV = function(st) {
81444       return [singleSTtoUV(st[0]), singleSTtoUV(st[1])];
81445     };
81446
81447
81448     var singleUVtoST = function(uv) {
81449       if (uv >= 0) {
81450         return 0.5 * Math.sqrt (1 + 3*uv);
81451       } else {
81452         return 1 - 0.5 * Math.sqrt (1 - 3*uv);
81453       }
81454     };
81455     S2.UVToST = function(uv) {
81456       return [singleUVtoST(uv[0]), singleUVtoST(uv[1])];
81457     };
81458
81459
81460     S2.STToIJ = function(st,order) {
81461       var maxSize = (1<<order);
81462
81463       var singleSTtoIJ = function(st) {
81464         var ij = Math.floor(st * maxSize);
81465         return Math.max(0, Math.min(maxSize-1, ij));
81466       };
81467
81468       return [singleSTtoIJ(st[0]), singleSTtoIJ(st[1])];
81469     };
81470
81471
81472     S2.IJToST = function(ij,order,offsets) {
81473       var maxSize = (1<<order);
81474
81475       return [
81476         (ij[0]+offsets[0])/maxSize,
81477         (ij[1]+offsets[1])/maxSize
81478       ];
81479     };
81480
81481
81482
81483     var rotateAndFlipQuadrant = function(n, point, rx, ry)
81484     {
81485         if(ry == 0)
81486         {
81487                 if(rx == 1){
81488                         point.x = n - 1 - point.x;
81489                         point.y = n - 1 - point.y;
81490
81491                 }
81492
81493         var x = point.x;
81494                 point.x = point.y;
81495                 point.y = x;
81496         }
81497
81498     };
81499
81500
81501
81502
81503
81504     // hilbert space-filling curve
81505     // based on http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves
81506     // note: rather then calculating the final integer hilbert position, we just return the list of quads
81507     // this ensures no precision issues whth large orders (S3 cell IDs use up to 30), and is more
81508     // convenient for pulling out the individual bits as needed later
81509     var pointToHilbertQuadList = function(x,y,order,face) {
81510       var hilbertMap = {
81511         'a': [ [0,'d'], [1,'a'], [3,'b'], [2,'a'] ],
81512         'b': [ [2,'b'], [1,'b'], [3,'a'], [0,'c'] ],
81513         'c': [ [2,'c'], [3,'d'], [1,'c'], [0,'b'] ],
81514         'd': [ [0,'a'], [3,'c'], [1,'d'], [2,'d'] ]
81515       };
81516
81517       if ('number' !== typeof face) {
81518         console.warn(new Error("called pointToHilbertQuadList without face value, defaulting to '0'").stack);
81519       }
81520       var currentSquare = (face % 2) ? 'd' : 'a';
81521       var positions = [];
81522
81523       for (var i=order-1; i>=0; i--) {
81524
81525         var mask = 1<<i;
81526
81527         var quad_x = x&mask ? 1 : 0;
81528         var quad_y = y&mask ? 1 : 0;
81529
81530         var t = hilbertMap[currentSquare][quad_x*2+quad_y];
81531
81532         positions.push(t[0]);
81533
81534         currentSquare = t[1];
81535       }
81536
81537       return positions;
81538     };
81539
81540     // S2Cell class
81541
81542     S2.S2Cell = function(){};
81543
81544     S2.S2Cell.FromHilbertQuadKey = function(hilbertQuadkey) {
81545       var parts = hilbertQuadkey.split('/');
81546       var face = parseInt(parts[0]);
81547       var position = parts[1];
81548       var maxLevel = position.length;
81549       var point = {
81550         x : 0,
81551         y: 0
81552       };
81553       var i;
81554       var level;
81555       var bit;
81556       var rx, ry;
81557       var val;
81558
81559         for(i = maxLevel - 1; i >= 0; i--) {
81560
81561                 level = maxLevel - i;
81562                 bit = position[i];
81563                 rx = 0;
81564         ry = 0;
81565                 if (bit === '1') {
81566                         ry = 1;
81567                 }
81568                 else if (bit === '2') {
81569                         rx = 1;
81570                         ry = 1;
81571                 }
81572                 else if (bit === '3') {
81573                         rx = 1;
81574                 }
81575
81576                 val = Math.pow(2, level - 1);
81577                 rotateAndFlipQuadrant(val, point, rx, ry);
81578
81579                 point.x += val * rx;
81580                 point.y += val * ry;
81581
81582         }
81583
81584       if (face % 2 === 1) {
81585         var t = point.x;
81586         point.x = point.y;
81587         point.y = t;
81588       }
81589
81590
81591       return S2.S2Cell.FromFaceIJ(parseInt(face), [point.x, point.y], level);
81592     };
81593
81594     //static method to construct
81595     S2.S2Cell.FromLatLng = function(latLng, level) {
81596       if ((!latLng.lat && latLng.lat !== 0) || (!latLng.lng && latLng.lng !== 0)) {
81597         throw new Error("Pass { lat: lat, lng: lng } to S2.S2Cell.FromLatLng");
81598       }
81599       var xyz = S2.LatLngToXYZ(latLng);
81600
81601       var faceuv = S2.XYZToFaceUV(xyz);
81602       var st = S2.UVToST(faceuv[1]);
81603
81604       var ij = S2.STToIJ(st,level);
81605
81606       return S2.S2Cell.FromFaceIJ (faceuv[0], ij, level);
81607     };
81608
81609     /*
81610     S2.faceIjLevelToXyz = function (face, ij, level) {
81611       var st = S2.IJToST(ij, level, [0.5, 0.5]);
81612       var uv = S2.STToUV(st);
81613       var xyz = S2.FaceUVToXYZ(face, uv);
81614
81615       return S2.XYZToLatLng(xyz);
81616       return xyz;
81617     };
81618     */
81619
81620     S2.S2Cell.FromFaceIJ = function(face,ij,level) {
81621       var cell = new S2.S2Cell();
81622       cell.face = face;
81623       cell.ij = ij;
81624       cell.level = level;
81625
81626       return cell;
81627     };
81628
81629
81630     S2.S2Cell.prototype.toString = function() {
81631       return 'F'+this.face+'ij['+this.ij[0]+','+this.ij[1]+']@'+this.level;
81632     };
81633
81634     S2.S2Cell.prototype.getLatLng = function() {
81635       var st = S2.IJToST(this.ij,this.level, [0.5,0.5]);
81636       var uv = S2.STToUV(st);
81637       var xyz = S2.FaceUVToXYZ(this.face, uv);
81638
81639       return S2.XYZToLatLng(xyz);
81640     };
81641
81642     S2.S2Cell.prototype.getCornerLatLngs = function() {
81643       var result = [];
81644       var offsets = [
81645         [ 0.0, 0.0 ],
81646         [ 0.0, 1.0 ],
81647         [ 1.0, 1.0 ],
81648         [ 1.0, 0.0 ]
81649       ];
81650
81651       for (var i=0; i<4; i++) {
81652         var st = S2.IJToST(this.ij, this.level, offsets[i]);
81653         var uv = S2.STToUV(st);
81654         var xyz = S2.FaceUVToXYZ(this.face, uv);
81655
81656         result.push ( S2.XYZToLatLng(xyz) );
81657       }
81658       return result;
81659     };
81660
81661
81662     S2.S2Cell.prototype.getFaceAndQuads = function () {
81663       var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face);
81664
81665       return [this.face,quads];
81666     };
81667     S2.S2Cell.prototype.toHilbertQuadkey = function () {
81668       var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face);
81669
81670       return this.face.toString(10) + '/' + quads.join('');
81671     };
81672
81673     S2.latLngToNeighborKeys = S2.S2Cell.latLngToNeighborKeys = function (lat, lng, level) {
81674       return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).getNeighbors().map(function (cell) {
81675         return cell.toHilbertQuadkey();
81676       });
81677     };
81678     S2.S2Cell.prototype.getNeighbors = function() {
81679
81680       var fromFaceIJWrap = function(face,ij,level) {
81681         var maxSize = (1<<level);
81682         if (ij[0]>=0 && ij[1]>=0 && ij[0]<maxSize && ij[1]<maxSize) {
81683           // no wrapping out of bounds
81684           return S2.S2Cell.FromFaceIJ(face,ij,level);
81685         } else {
81686           // the new i,j are out of range.
81687           // with the assumption that they're only a little past the borders we can just take the points as
81688           // just beyond the cube face, project to XYZ, then re-create FaceUV from the XYZ vector
81689
81690           var st = S2.IJToST(ij,level,[0.5,0.5]);
81691           var uv = S2.STToUV(st);
81692           var xyz = S2.FaceUVToXYZ(face,uv);
81693           var faceuv = S2.XYZToFaceUV(xyz);
81694           face = faceuv[0];
81695           uv = faceuv[1];
81696           st = S2.UVToST(uv);
81697           ij = S2.STToIJ(st,level);
81698           return S2.S2Cell.FromFaceIJ (face, ij, level);
81699         }
81700       };
81701
81702       var face = this.face;
81703       var i = this.ij[0];
81704       var j = this.ij[1];
81705       var level = this.level;
81706
81707
81708       return [
81709         fromFaceIJWrap(face, [i-1,j], level),
81710         fromFaceIJWrap(face, [i,j-1], level),
81711         fromFaceIJWrap(face, [i+1,j], level),
81712         fromFaceIJWrap(face, [i,j+1], level)
81713       ];
81714
81715     };
81716
81717     //
81718     // Functional Style
81719     //
81720     S2.FACE_BITS = 3;
81721     S2.MAX_LEVEL = 30;
81722     S2.POS_BITS = (2 * S2.MAX_LEVEL) + 1; // 61 (60 bits of data, 1 bit lsb marker)
81723
81724     S2.facePosLevelToId = S2.S2Cell.facePosLevelToId = S2.fromFacePosLevel = function (faceN, posS, levelN) {
81725       var Long = exports.dcodeIO && exports.dcodeIO.Long || long;
81726       var faceB;
81727       var posB;
81728       var bin;
81729
81730       if (!levelN) {
81731         levelN = posS.length;
81732       }
81733       if (posS.length > levelN) {
81734         posS = posS.substr(0, levelN);
81735       }
81736
81737       // 3-bit face value
81738       faceB = Long.fromString(faceN.toString(10), true, 10).toString(2);
81739       while (faceB.length < S2.FACE_BITS) {
81740         faceB = '0' + faceB;
81741       }
81742
81743       // 60-bit position value
81744       posB = Long.fromString(posS, true, 4).toString(2);
81745       while (posB.length < (2 * levelN)) {
81746         posB = '0' + posB;
81747       }
81748
81749       bin = faceB + posB;
81750       // 1-bit lsb marker
81751       bin += '1';
81752       // n-bit padding to 64-bits
81753       while (bin.length < (S2.FACE_BITS + S2.POS_BITS)) {
81754         bin += '0';
81755       }
81756
81757       return Long.fromString(bin, true, 2).toString(10);
81758     };
81759
81760     S2.keyToId = S2.S2Cell.keyToId
81761     = S2.toId = S2.toCellId = S2.fromKey
81762     = function (key) {
81763       var parts = key.split('/');
81764
81765       return S2.fromFacePosLevel(parts[0], parts[1], parts[1].length);
81766     };
81767
81768     S2.idToKey = S2.S2Cell.idToKey
81769     = S2.S2Cell.toKey = S2.toKey
81770     = S2.fromId = S2.fromCellId
81771     = S2.S2Cell.toHilbertQuadkey  = S2.toHilbertQuadkey
81772     = function (idS) {
81773       var Long = exports.dcodeIO && exports.dcodeIO.Long || long;
81774       var bin = Long.fromString(idS, true, 10).toString(2);
81775
81776       while (bin.length < (S2.FACE_BITS + S2.POS_BITS)) {
81777         bin = '0' + bin;
81778       }
81779
81780       // MUST come AFTER binstr has been left-padded with '0's
81781       var lsbIndex = bin.lastIndexOf('1');
81782       // substr(start, len)
81783       // substring(start, end) // includes start, does not include end
81784       var faceB = bin.substring(0, 3);
81785       // posB will always be a multiple of 2 (or it's invalid)
81786       var posB = bin.substring(3, lsbIndex);
81787       var levelN = posB.length / 2;
81788
81789       var faceS = Long.fromString(faceB, true, 2).toString(10);
81790       var posS = Long.fromString(posB, true, 2).toString(4);
81791
81792       while (posS.length < levelN) {
81793         posS = '0' + posS;
81794       }
81795
81796       return faceS + '/' + posS;
81797     };
81798
81799     S2.keyToLatLng = S2.S2Cell.keyToLatLng = function (key) {
81800       var cell2 = S2.S2Cell.FromHilbertQuadKey(key);
81801       return cell2.getLatLng();
81802     };
81803
81804     S2.idToLatLng = S2.S2Cell.idToLatLng = function (id) {
81805       var key = S2.idToKey(id);
81806       return S2.keyToLatLng(key);
81807     };
81808
81809     S2.S2Cell.latLngToKey = S2.latLngToKey
81810     = S2.latLngToQuadkey = function (lat, lng, level) {
81811       if (isNaN(level) || level < 1 || level > 30) {
81812         throw new Error("'level' is not a number between 1 and 30 (but it should be)");
81813       }
81814       // TODO
81815       //
81816       // S2.idToLatLng(id)
81817       // S2.keyToLatLng(key)
81818       // S2.nextFace(key)     // prevent wrapping on nextKey
81819       // S2.prevFace(key)     // prevent wrapping on prevKey
81820       //
81821       // .toKeyArray(id)  // face,quadtree
81822       // .toKey(id)       // hilbert
81823       // .toPoint(id)     // ij
81824       // .toId(key)       // uint64 (as string)
81825       // .toLong(key)     // long.js
81826       // .toLatLng(id)    // object? or array?, or string (with comma)?
81827       //
81828       // maybe S2.HQ.x, S2.GPS.x, S2.CI.x?
81829       return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).toHilbertQuadkey();
81830     };
81831
81832     S2.stepKey = function (key, num) {
81833       var Long = exports.dcodeIO && exports.dcodeIO.Long || long;
81834       var parts = key.split('/');
81835
81836       var faceS = parts[0];
81837       var posS = parts[1];
81838       var level = parts[1].length;
81839
81840       var posL = Long.fromString(posS, true, 4);
81841       // TODO handle wrapping (0 === pos + 1)
81842       // (only on the 12 edges of the globe)
81843       var otherL;
81844       if (num > 0) {
81845         otherL = posL.add(Math.abs(num));
81846       }
81847       else if (num < 0) {
81848         otherL = posL.subtract(Math.abs(num));
81849       }
81850       var otherS = otherL.toString(4);
81851
81852       if ('0' === otherS) {
81853         console.warning(new Error("face/position wrapping is not yet supported"));
81854       }
81855
81856       while (otherS.length < level) {
81857         otherS = '0' + otherS;
81858       }
81859
81860       return faceS + '/' + otherS;
81861     };
81862
81863     S2.S2Cell.prevKey = S2.prevKey = function (key) {
81864       return S2.stepKey(key, -1);
81865     };
81866
81867     S2.S2Cell.nextKey = S2.nextKey = function (key) {
81868       return S2.stepKey(key, 1);
81869     };
81870
81871     })(module.exports );
81872     });
81873
81874     /**
81875      * @class S2GeometryProvider
81876      *
81877      * @classdesc Geometry provider based on S2 cells.
81878      *
81879      * @example
81880      * ```js
81881      * class MyDataProvider extends DataProviderBase {
81882      *      ...
81883      * }
81884      *
81885      * const geometryProvider = new S2GeometryProvider();
81886      * const dataProvider = new MyDataProvider(geometryProvider);
81887      * ```
81888      */
81889     class S2GeometryProvider extends GeometryProviderBase {
81890         /**
81891          * Create a new S2 geometry provider instance.
81892          */
81893         constructor(_level = 17) {
81894             super();
81895             this._level = _level;
81896         }
81897         /** @inheritdoc */
81898         bboxToCellIds(sw, ne) {
81899             return this._approxBboxToCellIds(sw, ne);
81900         }
81901         /** @inheritdoc */
81902         getAdjacent(cellId) {
81903             const k = s2geometry.S2.idToKey(cellId);
81904             const position = k.split('/')[1];
81905             const level = position.length;
81906             const [a0, a1, a2, a3] = this._getNeighbors(k, level);
81907             const existing = [k, a0, a1, a2, a3];
81908             const others = Array
81909                 .from(new Set([
81910                 ...this._getNeighbors(a0, level),
81911                 ...this._getNeighbors(a1, level),
81912                 ...this._getNeighbors(a2, level),
81913                 ...this._getNeighbors(a3, level),
81914             ].filter((o) => {
81915                 return !existing.includes(o);
81916             })));
81917             const adjacent = [a0, a1, a2, a3];
81918             for (const other of others) {
81919                 let count = 0;
81920                 for (const n of this._getNeighbors(other, level)) {
81921                     if (existing.includes(n)) {
81922                         count++;
81923                     }
81924                 }
81925                 if (count === 2) {
81926                     adjacent.push(other);
81927                 }
81928             }
81929             return adjacent.map((a) => s2geometry.S2.keyToId(a));
81930         }
81931         /** @inheritdoc */
81932         getVertices(cellId) {
81933             const key = s2geometry.S2.idToKey(cellId);
81934             const cell = s2geometry.S2.S2Cell.FromHilbertQuadKey(key);
81935             return cell
81936                 .getCornerLatLngs()
81937                 .map((c) => {
81938                 return { lat: c.lat, lng: c.lng };
81939             });
81940         }
81941         /** @inheritdoc */
81942         lngLatToCellId(lngLat) {
81943             return this._lngLatToId(lngLat, this._level);
81944         }
81945         _getNeighbors(s2key, level) {
81946             const latlng = s2geometry.S2.keyToLatLng(s2key);
81947             const neighbors = s2geometry.S2.latLngToNeighborKeys(latlng.lat, latlng.lng, level);
81948             return neighbors;
81949         }
81950         _lngLatToId(lngLat, level) {
81951             const s2key = s2geometry.S2.latLngToKey(lngLat.lat, lngLat.lng, level);
81952             return s2geometry.S2.keyToId(s2key);
81953         }
81954     }
81955
81956     function convertCameraType(graphCameraType) {
81957         switch (graphCameraType) {
81958             case "equirectangular":
81959             case "spherical":
81960                 return "spherical";
81961             case "fisheye":
81962                 return "fisheye";
81963             default:
81964                 return "perspective";
81965         }
81966     }
81967     class GraphConverter {
81968         clusterReconstruction(source) {
81969             const id = null;
81970             const points = source.points;
81971             const normalize = 1 / 255;
81972             for (const pointId in points) {
81973                 if (!points.hasOwnProperty(pointId)) {
81974                     continue;
81975                 }
81976                 const color = points[pointId].color;
81977                 color[0] *= normalize;
81978                 color[1] *= normalize;
81979                 color[2] *= normalize;
81980             }
81981             const lla = source.reference_lla;
81982             const reference = {
81983                 alt: lla.altitude,
81984                 lat: lla.latitude,
81985                 lng: lla.longitude,
81986             };
81987             return {
81988                 id,
81989                 points,
81990                 reference,
81991             };
81992         }
81993         coreImage(source) {
81994             const geometry = this._geometry(source.geometry);
81995             const computedGeometry = this._geometry(source.computed_geometry);
81996             const sequence = { id: source.sequence };
81997             const id = source.id;
81998             return {
81999                 computed_geometry: computedGeometry,
82000                 geometry,
82001                 id,
82002                 sequence,
82003             };
82004         }
82005         spatialImage(source) {
82006             var _a, _b, _c, _d;
82007             source.camera_type = convertCameraType(source.camera_type);
82008             source.merge_id = source.merge_cc ? source.merge_cc.toString() : null;
82009             source.private = null;
82010             const thumbUrl = source.camera_type === 'spherical' ?
82011                 source.thumb_2048_url : source.thumb_1024_url;
82012             source.thumb = (_a = source.thumb) !== null && _a !== void 0 ? _a : { id: null, url: thumbUrl };
82013             source.cluster = (_b = source.sfm_cluster) !== null && _b !== void 0 ? _b : { id: null, url: null };
82014             source.creator = { id: null, username: null };
82015             source.owner = (_c = source.owner) !== null && _c !== void 0 ? _c : { id: null };
82016             source.mesh = (_d = source.mesh) !== null && _d !== void 0 ? _d : { id: null, url: null };
82017             return source;
82018         }
82019         _geometry(geometry) {
82020             const coords = geometry === null || geometry === void 0 ? void 0 : geometry.coordinates;
82021             const lngLat = coords ?
82022                 {
82023                     lat: coords[1],
82024                     lng: coords[0],
82025                 } : null;
82026             return lngLat;
82027         }
82028     }
82029
82030     class GraphQueryCreator {
82031         constructor() {
82032             this.imagesPath = 'images';
82033             this.sequencePath = 'image_ids';
82034             this._imageTilesPath = 'tiles';
82035             this.coreFields = ['computed_geometry', 'geometry', 'sequence'];
82036             this.idFields = ['id'];
82037             this.spatialFields = [
82038                 'altitude',
82039                 'atomic_scale',
82040                 'camera_parameters',
82041                 'camera_type',
82042                 'captured_at',
82043                 'compass_angle',
82044                 'computed_altitude',
82045                 'computed_compass_angle',
82046                 'computed_rotation',
82047                 'exif_orientation',
82048                 'height',
82049                 'merge_cc',
82050                 'mesh',
82051                 'quality_score',
82052                 'sfm_cluster',
82053                 'thumb_1024_url',
82054                 'thumb_2048_url',
82055                 'width',
82056             ];
82057             this.imageTileFields = ['url', 'z', 'x', 'y'];
82058         }
82059         images(imageIds, fields) {
82060             return `image_ids=${imageIds.join(',')}&fields=${fields.join(',')}`;
82061         }
82062         imagesS2(cellId, fields) {
82063             return `s2=${cellId}&fields=${fields.join(',')}`;
82064         }
82065         imageTiles(z, fields) {
82066             return `z=${z}&fields=${fields.join(',')}`;
82067         }
82068         imageTilesPath(imageId) {
82069             return `${imageId}/${this._imageTilesPath}`;
82070         }
82071         sequence(sequenceId) {
82072             return `sequence_id=${sequenceId}`;
82073         }
82074     }
82075
82076     class GraphDataProvider extends DataProviderBase {
82077         constructor(options, geometry, converter, queryCreator) {
82078             var _a;
82079             super(geometry !== null && geometry !== void 0 ? geometry : new S2GeometryProvider());
82080             this._convert = converter !== null && converter !== void 0 ? converter : new GraphConverter();
82081             this._query = queryCreator !== null && queryCreator !== void 0 ? queryCreator : new GraphQueryCreator();
82082             this._method = 'GET';
82083             const opts = options !== null && options !== void 0 ? options : {};
82084             this._endpoint = (_a = opts.endpoint) !== null && _a !== void 0 ? _a : "https://graph.mapillary.com";
82085             this._accessToken = opts.accessToken;
82086         }
82087         getCluster(url, abort) {
82088             return fetchArrayBuffer(url, abort)
82089                 .then((buffer) => {
82090                 const reconstructions = decompress(buffer);
82091                 if (reconstructions.length < 1) {
82092                     throw new Error('Cluster reconstruction empty');
82093                 }
82094                 return this._convert
82095                     .clusterReconstruction(reconstructions[0]);
82096             });
82097         }
82098         getCoreImages(cellId) {
82099             const fields = [
82100                 ...this._query.idFields,
82101                 ...this._query.coreFields,
82102             ];
82103             const query = this._query.imagesS2(cellId, fields);
82104             const url = new URL(this._query.imagesPath, this._endpoint).href;
82105             return this
82106                 ._fetchGraphContract(query, url)
82107                 .then(r => {
82108                 const result = {
82109                     cell_id: cellId,
82110                     images: [],
82111                 };
82112                 const items = r.data;
82113                 for (const item of items) {
82114                     const coreImage = this._convert.coreImage(item);
82115                     result.images.push(coreImage);
82116                 }
82117                 return result;
82118             });
82119         }
82120         getImageBuffer(url, abort) {
82121             return fetchArrayBuffer(url, abort);
82122         }
82123         getImages(imageIds) {
82124             const fields = [
82125                 ...this._query.idFields,
82126                 ...this._query.coreFields,
82127                 ...this._query.spatialFields,
82128             ];
82129             const query = this._query.images(imageIds, fields);
82130             const url = new URL(this._query.imagesPath, this._endpoint).href;
82131             return this
82132                 ._fetchGraphContract(query, url)
82133                 .then(r => {
82134                 const result = [];
82135                 const items = r.data;
82136                 for (const item of items) {
82137                     const coreImage = this._convert.coreImage(item);
82138                     const spatialImage = this._convert.spatialImage(item);
82139                     const image = Object.assign({}, spatialImage, coreImage);
82140                     const contract = {
82141                         node: image,
82142                         node_id: item.id,
82143                     };
82144                     result.push(contract);
82145                 }
82146                 return result;
82147             });
82148         }
82149         getImageTiles(request) {
82150             const fields = [
82151                 ...this._query.imageTileFields,
82152             ];
82153             const query = this._query.imageTiles(request.z, fields);
82154             const url = new URL(this._query.imageTilesPath(request.imageId), this._endpoint).href;
82155             return this
82156                 ._fetchGraphContract(query, url)
82157                 .then(r => {
82158                 const result = {
82159                     node: r.data,
82160                     node_id: request.imageId,
82161                 };
82162                 return result;
82163             });
82164         }
82165         getMesh(url, abort) {
82166             return fetchArrayBuffer(url, abort)
82167                 .then((buffer) => {
82168                 return readMeshPbf(buffer);
82169             });
82170         }
82171         getSequence(sequenceId) {
82172             const query = this._query.sequence(sequenceId);
82173             const url = new URL(this._query.sequencePath, this._endpoint).href;
82174             return this
82175                 ._fetchGraphContract(query, url)
82176                 .then(r => {
82177                 const result = {
82178                     id: sequenceId,
82179                     image_ids: r.data.map(item => item.id),
82180                 };
82181                 return result;
82182             });
82183         }
82184         getSpatialImages(imageIds) {
82185             const fields = [
82186                 ...this._query.idFields,
82187                 ...this._query.coreFields,
82188                 ...this._query.spatialFields,
82189             ];
82190             const query = this._query.images(imageIds, fields);
82191             const url = new URL(this._query.imagesPath, this._endpoint).href;
82192             return this
82193                 ._fetchGraphContract(query, url)
82194                 .then(r => {
82195                 const result = [];
82196                 const items = r.data;
82197                 for (const item of items) {
82198                     const spatialImage = this._convert.spatialImage(item);
82199                     const contract = {
82200                         node: spatialImage,
82201                         node_id: item.id,
82202                     };
82203                     result.push(contract);
82204                 }
82205                 return result;
82206             });
82207         }
82208         setAccessToken(accessToken) {
82209             this._accessToken = accessToken;
82210         }
82211         _createHeaders() {
82212             const headers = [
82213                 { name: 'Accept', value: 'application/json' },
82214                 {
82215                     name: 'Content-Type',
82216                     value: 'application/x-www-form-urlencoded',
82217                 },
82218             ];
82219             if (this._accessToken) {
82220                 headers.push({
82221                     name: 'Authorization',
82222                     value: `OAuth ${this._accessToken}`,
82223                 });
82224             }
82225             return headers;
82226         }
82227         _fetchGraphContract(body, url) {
82228             const method = this._method;
82229             const headers = this._createHeaders();
82230             const query = `${url}?${body}`;
82231             return xhrFetch(query, method, "json", headers, null, null)
82232                 .catch((error) => {
82233                 const message = this._makeErrorMessage(error);
82234                 throw new MapillaryError(message);
82235             });
82236         }
82237         _makeErrorMessage(graphError) {
82238             const error = graphError.error;
82239             const message = error ?
82240                 `${error.code} (${error.type}, ${error.fbtrace_id}): ${error.message}` :
82241                 "Failed to fetch data";
82242             return message;
82243         }
82244     }
82245
82246     /**
82247      * @class Marker
82248      *
82249      * @classdesc Represents an abstract marker class that should be extended
82250      * by marker implementations used in the marker component.
82251      */
82252     class Marker {
82253         constructor(id, lngLat) {
82254             this._id = id;
82255             this._lngLat = lngLat;
82256         }
82257         /**
82258          * Get id.
82259          * @returns {string} The id of the marker.
82260          */
82261         get id() {
82262             return this._id;
82263         }
82264         /**
82265          * Get geometry.
82266          *
82267          * @ignore
82268          */
82269         get geometry() {
82270             return this._geometry;
82271         }
82272         /**
82273          * Get lngLat.
82274          * @returns {LngLat} The geographic coordinates of the marker.
82275          */
82276         get lngLat() {
82277             return this._lngLat;
82278         }
82279         /** @ignore */
82280         createGeometry(position) {
82281             if (!!this._geometry) {
82282                 return;
82283             }
82284             this._createGeometry(position);
82285             // update matrix world if raycasting occurs before first render
82286             this._geometry.updateMatrixWorld(true);
82287         }
82288         /** @ignore */
82289         disposeGeometry() {
82290             if (!this._geometry) {
82291                 return;
82292             }
82293             this._disposeGeometry();
82294             this._geometry = undefined;
82295         }
82296         /** @ignore */
82297         getInteractiveObjects() {
82298             if (!this._geometry) {
82299                 return [];
82300             }
82301             return this._getInteractiveObjects();
82302         }
82303         /** @ignore */
82304         lerpAltitude(alt, alpha) {
82305             if (!this._geometry) {
82306                 return;
82307             }
82308             this._geometry.position.z =
82309                 (1 - alpha) * this._geometry.position.z + alpha * alt;
82310         }
82311         /** @ignore */
82312         updatePosition(position, lngLat) {
82313             if (!!lngLat) {
82314                 this._lngLat.lat = lngLat.lat;
82315                 this._lngLat.lng = lngLat.lng;
82316             }
82317             if (!this._geometry) {
82318                 return;
82319             }
82320             this._geometry.position.fromArray(position);
82321             this._geometry.updateMatrixWorld(true);
82322         }
82323     }
82324
82325     /**
82326      * @class CircleMarker
82327      *
82328      * @classdesc Non-interactive marker with a flat circle shape. The circle
82329      * marker can not be configured to be interactive.
82330      *
82331      * Circle marker properties can not be updated after creation.
82332      *
82333      * To create and add one `CircleMarker` with default configuration
82334      * and one with configuration use
82335      *
82336      * @example
82337      * ```js
82338      * var defaultMarker = new CircleMarker(
82339      *     "id-1",
82340      *     { lat: 0, lng: 0, });
82341      *
82342      * var configuredMarker = new CircleMarker(
82343      *     "id-2",
82344      *     { lat: 0, lng: 0, },
82345      *     {
82346      *         color: "#0ff",
82347      *         opacity: 0.3,
82348      *         radius: 0.7,
82349      *     });
82350      *
82351      * markerComponent.add([defaultMarker, configuredMarker]);
82352      * ```
82353      */
82354     class CircleMarker extends Marker {
82355         constructor(id, lngLat, options) {
82356             super(id, lngLat);
82357             options = !!options ? options : {};
82358             this._color = options.color != null ? options.color : 0xffffff;
82359             this._opacity = options.opacity != null ? options.opacity : 0.4;
82360             this._radius = options.radius != null ? options.radius : 1;
82361         }
82362         _createGeometry(position) {
82363             const circle = new Mesh(new CircleGeometry(this._radius, 16), new MeshBasicMaterial({
82364                 color: this._color,
82365                 opacity: this._opacity,
82366                 transparent: true,
82367             }));
82368             circle.up.fromArray([0, 0, 1]);
82369             circle.renderOrder = -1;
82370             const group = new Object3D();
82371             group.add(circle);
82372             group.position.fromArray(position);
82373             this._geometry = group;
82374         }
82375         _disposeGeometry() {
82376             for (let mesh of this._geometry.children) {
82377                 mesh.geometry.dispose();
82378                 mesh.material.dispose();
82379             }
82380         }
82381         _getInteractiveObjects() {
82382             return [];
82383         }
82384     }
82385
82386     /**
82387      * @class SimpleMarker
82388      *
82389      * @classdesc Interactive marker with ice cream shape. The sphere
82390      * inside the ice cream can be configured to be interactive.
82391      *
82392      * Simple marker properties can not be updated after creation.
82393      *
82394      * To create and add one `SimpleMarker` with default configuration
82395      * (non-interactive) and one interactive with configuration use
82396      *
82397      * @example
82398      * ```js
82399      * var defaultMarker = new SimpleMarker(
82400      *     "id-1",
82401      *     { lat: 0, lng: 0, });
82402      *
82403      * var interactiveMarker = new SimpleMarker(
82404      *     "id-2",
82405      *     { lat: 0, lng: 0, },
82406      *     {
82407      *         ballColor: "#00f",
82408      *         ballOpacity: 0.5,
82409      *         color: "#00f",
82410      *         interactive: true,
82411      *         opacity: 0.3,
82412      *         radius: 0.7,
82413      *     });
82414      *
82415      * markerComponent.add([defaultMarker, interactiveMarker]);
82416      * ```
82417      */
82418     class SimpleMarker extends Marker {
82419         constructor(id, lngLat, options) {
82420             super(id, lngLat);
82421             options = !!options ? options : {};
82422             this._ballColor = options.ballColor != null ? options.ballColor : 0xff0000;
82423             this._ballOpacity = options.ballOpacity != null ? options.ballOpacity : 0.8;
82424             this._circleToRayAngle = 2;
82425             this._color = options.color != null ? options.color : 0xff0000;
82426             this._interactive = !!options.interactive;
82427             this._opacity = options.opacity != null ? options.opacity : 0.4;
82428             this._radius = options.radius != null ? options.radius : 1;
82429         }
82430         _createGeometry(position) {
82431             const radius = this._radius;
82432             const height = this._markerHeight(radius);
82433             const markerMaterial = new MeshBasicMaterial({
82434                 color: this._color,
82435                 opacity: this._opacity,
82436                 transparent: true,
82437                 depthWrite: false,
82438             });
82439             const marker = new Mesh(this._createMarkerGeometry(radius, 8, 8), markerMaterial);
82440             const interactive = new Mesh(new SphereGeometry(radius / 2, 8, 8), new MeshBasicMaterial({
82441                 color: this._ballColor,
82442                 opacity: this._ballOpacity,
82443                 transparent: true,
82444             }));
82445             interactive.position.z = height;
82446             interactive.renderOrder = 1;
82447             const group = new Object3D();
82448             group.add(interactive);
82449             group.add(marker);
82450             group.position.fromArray(position);
82451             this._geometry = group;
82452         }
82453         _disposeGeometry() {
82454             for (const mesh of this._geometry.children) {
82455                 mesh.geometry.dispose();
82456                 mesh.material.dispose();
82457             }
82458         }
82459         _getInteractiveObjects() {
82460             return this._interactive ? [this._geometry.children[0]] : [];
82461         }
82462         _markerHeight(radius) {
82463             const t = Math.tan(Math.PI - this._circleToRayAngle);
82464             return radius * Math.sqrt(1 + t * t);
82465         }
82466         _createMarkerGeometry(radius, widthSegments, heightSegments) {
82467             const height = this._markerHeight(radius);
82468             const circleToRayAngle = this._circleToRayAngle;
82469             const indexRows = [];
82470             const positions = new Float32Array(3 * (widthSegments + 1) * (heightSegments + 1));
82471             let positionIndex = 0;
82472             for (let y = 0; y <= heightSegments; ++y) {
82473                 const indexRow = [];
82474                 for (let x = 0; x <= widthSegments; ++x) {
82475                     const u = x / widthSegments * Math.PI * 2;
82476                     const v = y / heightSegments * Math.PI;
82477                     let r = radius;
82478                     if (v > circleToRayAngle) {
82479                         const t = Math.tan(v - circleToRayAngle);
82480                         r = radius * Math.sqrt(1 + t * t);
82481                     }
82482                     const arrayIndex = 3 * positionIndex;
82483                     const sinv = Math.sin(v);
82484                     positions[arrayIndex + 0] = r * Math.cos(u) * sinv;
82485                     positions[arrayIndex + 1] = r * Math.sin(u) * sinv;
82486                     positions[arrayIndex + 2] = r * Math.cos(v) + height;
82487                     indexRow.push(positionIndex++);
82488                 }
82489                 indexRows.push(indexRow);
82490             }
82491             const indices = new Uint16Array(6 * widthSegments * heightSegments);
82492             let index = 0;
82493             for (let y = 0; y < heightSegments; ++y) {
82494                 for (let x = 0; x < widthSegments; ++x) {
82495                     const pi1 = indexRows[y][x + 1];
82496                     const pi2 = indexRows[y][x];
82497                     const pi3 = indexRows[y + 1][x];
82498                     const pi4 = indexRows[y + 1][x + 1];
82499                     indices[index++] = pi1;
82500                     indices[index++] = pi2;
82501                     indices[index++] = pi4;
82502                     indices[index++] = pi2;
82503                     indices[index++] = pi3;
82504                     indices[index++] = pi4;
82505                 }
82506             }
82507             const geometry = new BufferGeometry();
82508             const positionAttribute = new BufferAttribute(positions, 3);
82509             geometry.setAttribute("position", positionAttribute);
82510             geometry.setIndex(new BufferAttribute(indices, 1));
82511             return geometry;
82512         }
82513     }
82514
82515     /**
82516      * @class Popup
82517      *
82518      * @classdesc Popup instance for rendering custom HTML content
82519      * on top of images. Popups are based on 2D basic image coordinates
82520      * (see the {@link Viewer} class documentation for more information about coordinate
82521      * systems) and a certain popup is therefore only relevant to a single image.
82522      * Popups related to a certain image should be removed when moving
82523      * to another image.
82524      *
82525      * A popup must have both its content and its point or rect set to be
82526      * rendered. Popup options can not be updated after creation but the
82527      * basic point or rect as well as its content can be changed by calling
82528      * the appropriate methods.
82529      *
82530      * To create and add one `Popup` with default configuration
82531      * (tooltip visuals and automatic float) and one with specific options
82532      * use
82533      *
82534      * @example
82535      * ```js
82536      * var defaultSpan = document.createElement('span');
82537      * defaultSpan.innerHTML = 'hello default';
82538      *
82539      * var defaultPopup = new Popup();
82540      * defaultPopup.setDOMContent(defaultSpan);
82541      * defaultPopup.setBasicPoint([0.3, 0.3]);
82542      *
82543      * var cleanSpan = document.createElement('span');
82544      * cleanSpan.innerHTML = 'hello clean';
82545      *
82546      * var cleanPopup = new Popup({
82547      *     clean: true,
82548      *     float: Alignment.Top,
82549      *     offset: 10,
82550      *     opacity: 0.7,
82551      * });
82552      *
82553      * cleanPopup.setDOMContent(cleanSpan);
82554      * cleanPopup.setBasicPoint([0.6, 0.6]);
82555      *
82556      * popupComponent.add([defaultPopup, cleanPopup]);
82557      * ```
82558      *
82559      * @description Implementation of API methods and API documentation inspired
82560      * by/used from https://github.com/mapbox/mapbox-gl-js/blob/v0.38.0/src/ui/popup.js
82561      */
82562     class Popup {
82563         constructor(options, viewportCoords, dom) {
82564             this._options = {};
82565             options = !!options ? options : {};
82566             this._options.capturePointer = options.capturePointer === false ?
82567                 options.capturePointer : true;
82568             this._options.clean = options.clean;
82569             this._options.float = options.float;
82570             this._options.offset = options.offset;
82571             this._options.opacity = options.opacity;
82572             this._options.position = options.position;
82573             this._dom = !!dom ? dom : new DOM();
82574             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
82575             this._notifyChanged$ = new Subject();
82576         }
82577         /**
82578          * @description Internal observable used by the component to
82579          * render the popup when its position or content has changed.
82580          * @ignore
82581          */
82582         get changed$() {
82583             return this._notifyChanged$;
82584         }
82585         /**
82586          * @description Internal method used by the component to
82587          * remove all references to the popup.
82588          * @ignore
82589          */
82590         remove() {
82591             if (this._content && this._content.parentNode) {
82592                 this._content.parentNode.removeChild(this._content);
82593             }
82594             if (this._container) {
82595                 this._container.parentNode.removeChild(this._container);
82596                 delete this._container;
82597             }
82598             if (this._parentContainer) {
82599                 delete this._parentContainer;
82600             }
82601         }
82602         /**
82603          * Sets a 2D basic image coordinates point to the popup's anchor, and
82604          * moves the popup to it.
82605          *
82606          * @description Overwrites any previously set point or rect.
82607          *
82608          * @param {Array<number>} basicPoint - Point in 2D basic image coordinates.
82609          *
82610          * @example
82611          * ```js
82612          * var popup = new Popup();
82613          * popup.setText('hello image');
82614          * popup.setBasicPoint([0.3, 0.3]);
82615          *
82616          * popupComponent.add([popup]);
82617          * ```
82618          */
82619         setBasicPoint(basicPoint) {
82620             this._point = basicPoint.slice();
82621             this._rect = null;
82622             this._notifyChanged$.next(this);
82623         }
82624         /**
82625          * Sets a 2D basic image coordinates rect to the popup's anchor, and
82626          * moves the popup to it.
82627          *
82628          * @description Overwrites any previously set point or rect.
82629          *
82630          * @param {Array<number>} basicRect - Rect in 2D basic image
82631          * coordinates ([topLeftX, topLeftY, bottomRightX, bottomRightY]) .
82632          *
82633          * @example
82634          * ```js
82635          * var popup = new Popup();
82636          * popup.setText('hello image');
82637          * popup.setBasicRect([0.3, 0.3, 0.5, 0.6]);
82638          *
82639          * popupComponent.add([popup]);
82640          * ```
82641          */
82642         setBasicRect(basicRect) {
82643             this._rect = basicRect.slice();
82644             this._point = null;
82645             this._notifyChanged$.next(this);
82646         }
82647         /**
82648          * Sets the popup's content to the element provided as a DOM node.
82649          *
82650          * @param {Node} htmlNode - A DOM node to be used as content for the popup.
82651          *
82652          * @example
82653          * ```js
82654          * var div = document.createElement('div');
82655          * div.innerHTML = 'hello image';
82656          *
82657          * var popup = new Popup();
82658          * popup.setDOMContent(div);
82659          * popup.setBasicPoint([0.3, 0.3]);
82660          *
82661          * popupComponent.add([popup]);
82662          * ```
82663          */
82664         setDOMContent(htmlNode) {
82665             if (this._content && this._content.parentNode) {
82666                 this._content.parentNode.removeChild(this._content);
82667             }
82668             const className = "mapillary-popup-content" +
82669                 (this._options.clean === true ? "-clean" : "") +
82670                 (this._options.capturePointer === true ? " mapillary-popup-capture-pointer" : "");
82671             this._content = this._dom.createElement("div", className, this._container);
82672             this._content.appendChild(htmlNode);
82673             this._notifyChanged$.next(this);
82674         }
82675         /**
82676          * Sets the popup's content to the HTML provided as a string.
82677          *
82678          * @description This method does not perform HTML filtering or sanitization,
82679          * and must be used only with trusted content. Consider
82680          * {@link Popup.setText} if the
82681          * content is an untrusted text string.
82682          *
82683          * @param {string} html - A string representing HTML content for the popup.
82684          *
82685          * @example
82686          * ```js
82687          * var popup = new Popup();
82688          * popup.setHTML('<div>hello image</div>');
82689          * popup.setBasicPoint([0.3, 0.3]);
82690          *
82691          * popupComponent.add([popup]);
82692          * ```
82693          */
82694         setHTML(html) {
82695             const frag = this._dom.document.createDocumentFragment();
82696             const temp = this._dom.createElement("body");
82697             let child;
82698             temp.innerHTML = html;
82699             while (true) {
82700                 child = temp.firstChild;
82701                 if (!child) {
82702                     break;
82703                 }
82704                 frag.appendChild(child);
82705             }
82706             this.setDOMContent(frag);
82707         }
82708         /**
82709          * Sets the popup's content to a string of text.
82710          *
82711          * @description This function creates a Text node in the DOM, so it cannot insert raw HTML.
82712          * Use this method for security against XSS if the popup content is user-provided.
82713          *
82714          * @param {string} text - Textual content for the popup.
82715          *
82716          * @example
82717          * ```js
82718          * var popup = new Popup();
82719          * popup.setText('hello image');
82720          * popup.setBasicPoint([0.3, 0.3]);
82721          *
82722          * popupComponent.add([popup]);
82723          * ```
82724          */
82725         setText(text) {
82726             this.setDOMContent(this._dom.document.createTextNode(text));
82727         }
82728         /**
82729          * @description Internal method for attaching the popup to
82730          * its parent container so that it is rendered in the DOM tree.
82731          * @ignore
82732          */
82733         setParentContainer(parentContainer) {
82734             this._parentContainer = parentContainer;
82735         }
82736         /**
82737          * @description Internal method for updating the rendered
82738          * position of the popup called by the popup component.
82739          * @ignore
82740          */
82741         update(renderCamera, size, transform) {
82742             if (!this._parentContainer || !this._content) {
82743                 return;
82744             }
82745             if (!this._point && !this._rect) {
82746                 return;
82747             }
82748             if (!this._container) {
82749                 this._container = this._dom.createElement("div", "mapillary-popup", this._parentContainer);
82750                 const showTip = this._options.clean !== true &&
82751                     this._options.float !== exports.Alignment.Center;
82752                 if (showTip) {
82753                     const tipClassName = "mapillary-popup-tip" +
82754                         (this._options.capturePointer === true ? " mapillary-popup-capture-pointer" : "");
82755                     this._tip = this._dom.createElement("div", tipClassName, this._container);
82756                     this._dom.createElement("div", "mapillary-popup-tip-inner", this._tip);
82757                 }
82758                 this._container.appendChild(this._content);
82759                 this._parentContainer.appendChild(this._container);
82760                 if (this._options.opacity != null) {
82761                     this._container.style.opacity = this._options.opacity.toString();
82762                 }
82763             }
82764             let pointPixel = null;
82765             let position = this._alignmentToPopupAligment(this._options.position);
82766             let float = this._alignmentToPopupAligment(this._options.float);
82767             const classList = this._container.classList;
82768             if (this._point != null) {
82769                 pointPixel =
82770                     this._viewportCoords.basicToCanvasSafe(this._point[0], this._point[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
82771             }
82772             else {
82773                 const alignments = ["center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right"];
82774                 let appliedPosition = null;
82775                 for (const alignment of alignments) {
82776                     if (classList.contains(`mapillary-popup-float-${alignment}`)) {
82777                         appliedPosition = alignment;
82778                         break;
82779                     }
82780                 }
82781                 [pointPixel, position] = this._rectToPixel(this._rect, position, appliedPosition, renderCamera, size, transform);
82782                 if (!float) {
82783                     float = position;
82784                 }
82785             }
82786             if (pointPixel == null) {
82787                 this._container.style.display = "none";
82788                 return;
82789             }
82790             this._container.style.display = "";
82791             if (!float) {
82792                 const width = this._container.offsetWidth;
82793                 const height = this._container.offsetHeight;
82794                 const floats = this._pixelToFloats(pointPixel, size, width, height);
82795                 float = floats.length === 0 ? "top" : floats.join("-");
82796             }
82797             const offset = this._normalizeOffset(this._options.offset);
82798             pointPixel = [pointPixel[0] + offset[float][0], pointPixel[1] + offset[float][1]];
82799             pointPixel = [Math.round(pointPixel[0]), Math.round(pointPixel[1])];
82800             const floatTranslate = {
82801                 "bottom": "translate(-50%,0)",
82802                 "bottom-left": "translate(-100%,0)",
82803                 "bottom-right": "translate(0,0)",
82804                 "center": "translate(-50%,-50%)",
82805                 "left": "translate(-100%,-50%)",
82806                 "right": "translate(0,-50%)",
82807                 "top": "translate(-50%,-100%)",
82808                 "top-left": "translate(-100%,-100%)",
82809                 "top-right": "translate(0,-100%)",
82810             };
82811             for (const key in floatTranslate) {
82812                 if (!floatTranslate.hasOwnProperty(key)) {
82813                     continue;
82814                 }
82815                 classList.remove(`mapillary-popup-float-${key}`);
82816             }
82817             classList.add(`mapillary-popup-float-${float}`);
82818             this._container.style.transform = `${floatTranslate[float]} translate(${pointPixel[0]}px,${pointPixel[1]}px)`;
82819         }
82820         _rectToPixel(rect, position, appliedPosition, renderCamera, size, transform) {
82821             if (!position) {
82822                 const width = this._container.offsetWidth;
82823                 const height = this._container.offsetHeight;
82824                 const floatOffsets = {
82825                     "bottom": [0, height / 2],
82826                     "bottom-left": [-width / 2, height / 2],
82827                     "bottom-right": [width / 2, height / 2],
82828                     "left": [-width / 2, 0],
82829                     "right": [width / 2, 0],
82830                     "top": [0, -height / 2],
82831                     "top-left": [-width / 2, -height / 2],
82832                     "top-right": [width / 2, -height / 2],
82833                 };
82834                 const automaticPositions = ["top", "bottom", "left", "right"];
82835                 let largestVisibleArea = [0, null, null];
82836                 for (const automaticPosition of automaticPositions) {
82837                     const autoPointBasic = this._pointFromRectPosition(rect, automaticPosition);
82838                     const autoPointPixel = this._viewportCoords.basicToCanvasSafe(autoPointBasic[0], autoPointBasic[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
82839                     if (autoPointPixel == null) {
82840                         continue;
82841                     }
82842                     const floatOffset = floatOffsets[automaticPosition];
82843                     const offsetedPosition = [autoPointPixel[0] + floatOffset[0], autoPointPixel[1] + floatOffset[1]];
82844                     const staticCoeff = appliedPosition != null && appliedPosition === automaticPosition ? 1 : 0.7;
82845                     const floats = this._pixelToFloats(offsetedPosition, size, width / staticCoeff, height / (2 * staticCoeff));
82846                     if (floats.length === 0 &&
82847                         autoPointPixel[0] > 0 &&
82848                         autoPointPixel[0] < size.width &&
82849                         autoPointPixel[1] > 0 &&
82850                         autoPointPixel[1] < size.height) {
82851                         return [autoPointPixel, automaticPosition];
82852                     }
82853                     const minX = Math.max(offsetedPosition[0] - width / 2, 0);
82854                     const maxX = Math.min(offsetedPosition[0] + width / 2, size.width);
82855                     const minY = Math.max(offsetedPosition[1] - height / 2, 0);
82856                     const maxY = Math.min(offsetedPosition[1] + height / 2, size.height);
82857                     const visibleX = Math.max(0, maxX - minX);
82858                     const visibleY = Math.max(0, maxY - minY);
82859                     const visibleArea = staticCoeff * visibleX * visibleY;
82860                     if (visibleArea > largestVisibleArea[0]) {
82861                         largestVisibleArea[0] = visibleArea;
82862                         largestVisibleArea[1] = autoPointPixel;
82863                         largestVisibleArea[2] = automaticPosition;
82864                     }
82865                 }
82866                 if (largestVisibleArea[0] > 0) {
82867                     return [largestVisibleArea[1], largestVisibleArea[2]];
82868                 }
82869             }
82870             const pointBasic = this._pointFromRectPosition(rect, position);
82871             const pointPixel = this._viewportCoords.basicToCanvasSafe(pointBasic[0], pointBasic[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
82872             return [pointPixel, position != null ? position : "top"];
82873         }
82874         _alignmentToPopupAligment(float) {
82875             switch (float) {
82876                 case exports.Alignment.Bottom:
82877                     return "bottom";
82878                 case exports.Alignment.BottomLeft:
82879                     return "bottom-left";
82880                 case exports.Alignment.BottomRight:
82881                     return "bottom-right";
82882                 case exports.Alignment.Center:
82883                     return "center";
82884                 case exports.Alignment.Left:
82885                     return "left";
82886                 case exports.Alignment.Right:
82887                     return "right";
82888                 case exports.Alignment.Top:
82889                     return "top";
82890                 case exports.Alignment.TopLeft:
82891                     return "top-left";
82892                 case exports.Alignment.TopRight:
82893                     return "top-right";
82894                 default:
82895                     return null;
82896             }
82897         }
82898         _normalizeOffset(offset) {
82899             if (offset == null) {
82900                 return this._normalizeOffset(0);
82901             }
82902             if (typeof offset === "number") {
82903                 // input specifies a radius
82904                 const sideOffset = offset;
82905                 const sign = sideOffset >= 0 ? 1 : -1;
82906                 const cornerOffset = sign * Math.round(Math.sqrt(0.5 * Math.pow(sideOffset, 2)));
82907                 return {
82908                     "bottom": [0, sideOffset],
82909                     "bottom-left": [-cornerOffset, cornerOffset],
82910                     "bottom-right": [cornerOffset, cornerOffset],
82911                     "center": [0, 0],
82912                     "left": [-sideOffset, 0],
82913                     "right": [sideOffset, 0],
82914                     "top": [0, -sideOffset],
82915                     "top-left": [-cornerOffset, -cornerOffset],
82916                     "top-right": [cornerOffset, -cornerOffset],
82917                 };
82918             }
82919             else {
82920                 // input specifes a value for each position
82921                 return {
82922                     "bottom": offset.bottom || [0, 0],
82923                     "bottom-left": offset.bottomLeft || [0, 0],
82924                     "bottom-right": offset.bottomRight || [0, 0],
82925                     "center": offset.center || [0, 0],
82926                     "left": offset.left || [0, 0],
82927                     "right": offset.right || [0, 0],
82928                     "top": offset.top || [0, 0],
82929                     "top-left": offset.topLeft || [0, 0],
82930                     "top-right": offset.topRight || [0, 0],
82931                 };
82932             }
82933         }
82934         _pixelToFloats(pointPixel, size, width, height) {
82935             const floats = [];
82936             if (pointPixel[1] < height) {
82937                 floats.push("bottom");
82938             }
82939             else if (pointPixel[1] > size.height - height) {
82940                 floats.push("top");
82941             }
82942             if (pointPixel[0] < width / 2) {
82943                 floats.push("right");
82944             }
82945             else if (pointPixel[0] > size.width - width / 2) {
82946                 floats.push("left");
82947             }
82948             return floats;
82949         }
82950         _pointFromRectPosition(rect, position) {
82951             const x0 = rect[0];
82952             const x1 = rect[0] < rect[2] ? rect[2] : rect[2] + 1;
82953             const y0 = rect[1];
82954             const y1 = rect[3];
82955             switch (position) {
82956                 case "bottom":
82957                     return [(x0 + x1) / 2, y1];
82958                 case "bottom-left":
82959                     return [x0, y1];
82960                 case "bottom-right":
82961                     return [x1, y1];
82962                 case "center":
82963                     return [(x0 + x1) / 2, (y0 + y1) / 2];
82964                 case "left":
82965                     return [x0, (y0 + y1) / 2];
82966                 case "right":
82967                     return [x1, (y0 + y1) / 2];
82968                 case "top":
82969                     return [(x0 + x1) / 2, y0];
82970                 case "top-left":
82971                     return [x0, y0];
82972                 case "top-right":
82973                     return [x1, y0];
82974                 default:
82975                     return [(x0 + x1) / 2, y1];
82976             }
82977         }
82978     }
82979
82980     function isBrowser() {
82981         return (typeof window !== "undefined" &&
82982             typeof document !== "undefined");
82983     }
82984     function isArraySupported() {
82985         return !!(Array.prototype &&
82986             Array.prototype.concat &&
82987             Array.prototype.filter &&
82988             Array.prototype.includes &&
82989             Array.prototype.indexOf &&
82990             Array.prototype.join &&
82991             Array.prototype.map &&
82992             Array.prototype.push &&
82993             Array.prototype.pop &&
82994             Array.prototype.reverse &&
82995             Array.prototype.shift &&
82996             Array.prototype.slice &&
82997             Array.prototype.splice &&
82998             Array.prototype.sort &&
82999             Array.prototype.unshift);
83000     }
83001     function isBlobSupported() {
83002         return ("Blob" in window &&
83003             "URL" in window);
83004     }
83005     function isFunctionSupported() {
83006         return !!(Function.prototype &&
83007             Function.prototype.apply &&
83008             Function.prototype.bind);
83009     }
83010     function isJSONSupported() {
83011         return ("JSON" in window &&
83012             "parse" in JSON &&
83013             "stringify" in JSON);
83014     }
83015     function isMapSupported() {
83016         return "Map" in window;
83017     }
83018     function isObjectSupported() {
83019         return !!(Object.assign &&
83020             Object.keys &&
83021             Object.values);
83022     }
83023     function isPromiseSupported() {
83024         return !!("Promise" in window &&
83025             Promise.resolve &&
83026             Promise.reject &&
83027             Promise.prototype &&
83028             Promise.prototype.catch &&
83029             Promise.prototype.then);
83030     }
83031     function isSetSupported() {
83032         return "Set" in window;
83033     }
83034     let isWebGLSupportedCache = undefined;
83035     function isWebGLSupportedCached() {
83036         if (isWebGLSupportedCache === undefined) {
83037             isWebGLSupportedCache = isWebGLSupported();
83038         }
83039         return isWebGLSupportedCache;
83040     }
83041     function isWebGLSupported() {
83042         const attributes = {
83043             alpha: false,
83044             antialias: false,
83045             depth: true,
83046             failIfMajorPerformanceCaveat: false,
83047             premultipliedAlpha: true,
83048             preserveDrawingBuffer: false,
83049             stencil: true,
83050         };
83051         const canvas = document.createElement("canvas");
83052         const webGL2Context = canvas.getContext("webgl2", attributes);
83053         if (!!webGL2Context) {
83054             return true;
83055         }
83056         const context = canvas.getContext("webgl", attributes) ||
83057             canvas
83058                 .getContext("experimental-webgl", attributes);
83059         if (!context) {
83060             return false;
83061         }
83062         const requiredExtensions = ["OES_standard_derivatives"];
83063         const supportedExtensions = context.getSupportedExtensions();
83064         for (const requiredExtension of requiredExtensions) {
83065             if (supportedExtensions.indexOf(requiredExtension) === -1) {
83066                 return false;
83067             }
83068         }
83069         return true;
83070     }
83071     /**
83072      * Test whether the current browser supports the full
83073      * functionality of MapillaryJS.
83074      *
83075      * @description The full functionality includes WebGL rendering.
83076      *
83077      * @return {boolean}
83078      *
83079      * @example `var supported = isSupported();`
83080      */
83081     function isSupported() {
83082         return isFallbackSupported() &&
83083             isWebGLSupportedCached();
83084     }
83085     /**
83086      * Test whether the current browser supports the fallback
83087      * functionality of MapillaryJS.
83088      *
83089      * @description The fallback functionality does not include WebGL
83090      * rendering, only 2D canvas rendering.
83091      *
83092      * @return {boolean}
83093      *
83094      * @example `var fallbackSupported = isFallbackSupported();`
83095      */
83096     function isFallbackSupported() {
83097         return isBrowser() &&
83098             isArraySupported() &&
83099             isBlobSupported() &&
83100             isFunctionSupported() &&
83101             isJSONSupported() &&
83102             isMapSupported() &&
83103             isObjectSupported() &&
83104             isPromiseSupported() &&
83105             isSetSupported();
83106     }
83107
83108     /**
83109      * Enumeration for camera controls.
83110      *
83111      * @description Specifies different modes for how the
83112      * camera is controlled through pointer, keyboard or
83113      * other modes of input.
83114      *
83115      * @enum {number}
83116      * @readonly
83117      */
83118     exports.CameraControls = void 0;
83119     (function (CameraControls) {
83120         /**
83121          * Control the camera with custom logic by
83122          * attaching a custom camera controls
83123          * instance to the {@link Viewer}.
83124          */
83125         CameraControls[CameraControls["Custom"] = 0] = "Custom";
83126         /**
83127          * Control the camera from a birds perspective
83128          * to get an overview.
83129          */
83130         CameraControls[CameraControls["Earth"] = 1] = "Earth";
83131         /**
83132          * Control the camera in a first person view
83133          * from the street level perspective.
83134          */
83135         CameraControls[CameraControls["Street"] = 2] = "Street";
83136     })(exports.CameraControls || (exports.CameraControls = {}));
83137
83138     /**
83139      * Enumeration for render mode
83140      * @enum {number}
83141      * @readonly
83142      * @description Modes for specifying how rendering is done
83143      * in the viewer. All modes preserves the original aspect
83144      * ratio of the images.
83145      */
83146     exports.RenderMode = void 0;
83147     (function (RenderMode) {
83148         /**
83149          * Displays all content within the viewer.
83150          *
83151          * @description Black bars shown on both
83152          * sides of the content. Bars are shown
83153          * either below and above or to the left
83154          * and right of the content depending on
83155          * the aspect ratio relation between the
83156          * image and the viewer.
83157          */
83158         RenderMode[RenderMode["Letterbox"] = 0] = "Letterbox";
83159         /**
83160          * Fills the viewer by cropping content.
83161          *
83162          * @description Cropping is done either
83163          * in horizontal or vertical direction
83164          * depending on the aspect ratio relation
83165          * between the image and the viewer.
83166          */
83167         RenderMode[RenderMode["Fill"] = 1] = "Fill";
83168     })(exports.RenderMode || (exports.RenderMode = {}));
83169
83170     exports.RenderPass = void 0;
83171     (function (RenderPass) {
83172         /**
83173          * Occurs after the background render pass.
83174          */
83175         RenderPass[RenderPass["Opaque"] = 0] = "Opaque";
83176     })(exports.RenderPass || (exports.RenderPass = {}));
83177
83178     class ComponentController {
83179         constructor(container, navigator, observer, key, options, componentService) {
83180             this._container = container;
83181             this._observer = observer;
83182             this._navigator = navigator;
83183             this._options = options != null ? options : {};
83184             this._key = key;
83185             this._navigable = key == null;
83186             this._componentService = !!componentService ?
83187                 componentService :
83188                 new ComponentService(this._container, this._navigator);
83189             this._coverComponent = this._componentService.getCover();
83190             this._initializeComponents();
83191             if (key) {
83192                 this._initilizeCoverComponent();
83193                 this._subscribeCoverComponent();
83194             }
83195             else {
83196                 this._navigator.movedToId$.pipe(first((k) => {
83197                     return k != null;
83198                 }))
83199                     .subscribe((k) => {
83200                     this._key = k;
83201                     this._componentService.deactivateCover();
83202                     this._coverComponent.configure({
83203                         id: this._key,
83204                         state: CoverState.Hidden,
83205                     });
83206                     this._subscribeCoverComponent();
83207                     this._navigator.stateService.start();
83208                     this._navigator.cacheService.start();
83209                     this._navigator.panService.start();
83210                     this._observer.startEmit();
83211                 });
83212             }
83213         }
83214         get navigable() {
83215             return this._navigable;
83216         }
83217         get(name) {
83218             return this._componentService.get(name);
83219         }
83220         activate(name) {
83221             this._componentService.activate(name);
83222         }
83223         activateCover() {
83224             this._coverComponent.configure({ state: CoverState.Visible });
83225         }
83226         deactivate(name) {
83227             this._componentService.deactivate(name);
83228         }
83229         deactivateCover() {
83230             this._coverComponent.configure({ state: CoverState.Loading });
83231         }
83232         remove() {
83233             this._componentService.remove();
83234             if (this._configurationSubscription != null) {
83235                 this._configurationSubscription.unsubscribe();
83236             }
83237         }
83238         _initializeComponents() {
83239             var _a, _b;
83240             const options = this._options;
83241             this._uFalse((_a = options.fallback) === null || _a === void 0 ? void 0 : _a.image, "imagefallback");
83242             this._uFalse((_b = options.fallback) === null || _b === void 0 ? void 0 : _b.navigation, "navigationfallback");
83243             this._uFalse(options.marker, "marker");
83244             this._uFalse(options.popup, "popup");
83245             this._uFalse(options.slider, "slider");
83246             this._uFalse(options.spatial, "spatial");
83247             this._uFalse(options.tag, "tag");
83248             this._uTrue(options.attribution, "attribution");
83249             this._uTrue(options.bearing, "bearing");
83250             this._uTrue(options.cache, "cache");
83251             this._uTrue(options.direction, "direction");
83252             this._uTrue(options.image, "image");
83253             this._uTrue(options.keyboard, "keyboard");
83254             this._uTrue(options.pointer, "pointer");
83255             this._uTrue(options.sequence, "sequence");
83256             this._uTrue(options.zoom, "zoom");
83257         }
83258         _initilizeCoverComponent() {
83259             let options = this._options;
83260             this._coverComponent.configure({ id: this._key });
83261             if (options.cover === undefined || options.cover) {
83262                 this.activateCover();
83263             }
83264             else {
83265                 this.deactivateCover();
83266             }
83267         }
83268         _setNavigable(navigable) {
83269             if (this._navigable === navigable) {
83270                 return;
83271             }
83272             this._navigable = navigable;
83273             this._observer.navigable$.next(navigable);
83274         }
83275         _subscribeCoverComponent() {
83276             this._configurationSubscription =
83277                 this._coverComponent.configuration$.pipe(distinctUntilChanged(undefined, (c) => {
83278                     return c.state;
83279                 }))
83280                     .subscribe((conf) => {
83281                     if (conf.state === CoverState.Loading) {
83282                         this._navigator.stateService.currentId$.pipe(first(), switchMap((key) => {
83283                             const keyChanged = key == null || key !== conf.id;
83284                             if (keyChanged) {
83285                                 this._setNavigable(false);
83286                             }
83287                             return keyChanged ?
83288                                 this._navigator.moveTo$(conf.id) :
83289                                 this._navigator.stateService.currentImage$.pipe(first());
83290                         }))
83291                             .subscribe(() => {
83292                             this._navigator.stateService.start();
83293                             this._navigator.cacheService.start();
83294                             this._navigator.panService.start();
83295                             this._observer.startEmit();
83296                             this._coverComponent.configure({ state: CoverState.Hidden });
83297                             this._componentService.deactivateCover();
83298                             this._setNavigable(true);
83299                         }, (error) => {
83300                             console.error("Failed to deactivate cover.", error);
83301                             this._coverComponent.configure({ state: CoverState.Visible });
83302                         });
83303                     }
83304                     else if (conf.state === CoverState.Visible) {
83305                         this._observer.stopEmit();
83306                         this._navigator.stateService.stop();
83307                         this._navigator.cacheService.stop();
83308                         this._navigator.playService.stop();
83309                         this._navigator.panService.stop();
83310                         this._componentService.activateCover();
83311                         this._setNavigable(conf.id == null);
83312                     }
83313                 });
83314         }
83315         _uFalse(option, name) {
83316             if (option === undefined) {
83317                 this._componentService.deactivate(name);
83318                 return;
83319             }
83320             if (typeof option === "boolean") {
83321                 if (option) {
83322                     this._componentService.activate(name);
83323                 }
83324                 else {
83325                     this._componentService.deactivate(name);
83326                 }
83327                 return;
83328             }
83329             this._componentService.configure(name, option);
83330             this._componentService.activate(name);
83331         }
83332         _uTrue(option, name) {
83333             if (option === undefined) {
83334                 this._componentService.activate(name);
83335                 return;
83336             }
83337             if (typeof option === "boolean") {
83338                 if (option) {
83339                     this._componentService.activate(name);
83340                 }
83341                 else {
83342                     this._componentService.deactivate(name);
83343                 }
83344                 return;
83345             }
83346             this._componentService.configure(name, option);
83347             this._componentService.activate(name);
83348         }
83349     }
83350
83351     class DOMRenderer {
83352         constructor(element, renderService, currentFrame$) {
83353             this._adaptiveOperation$ = new Subject();
83354             this._render$ = new Subject();
83355             this._renderAdaptive$ = new Subject();
83356             this._subscriptions = new SubscriptionHolder();
83357             this._renderService = renderService;
83358             this._currentFrame$ = currentFrame$;
83359             const subs = this._subscriptions;
83360             const rootNode = virtualDom.create(virtualDom.h("div.mapillary-dom-renderer", []));
83361             element.appendChild(rootNode);
83362             this._offset$ = this._adaptiveOperation$.pipe(scan((adaptive, operation) => {
83363                 return operation(adaptive);
83364             }, {
83365                 elementHeight: element.offsetHeight,
83366                 elementWidth: element.offsetWidth,
83367                 imageAspect: 0,
83368                 renderMode: exports.RenderMode.Fill,
83369             }), filter((adaptive) => {
83370                 return adaptive.imageAspect > 0 && adaptive.elementWidth > 0 && adaptive.elementHeight > 0;
83371             }), map((adaptive) => {
83372                 const elementAspect = adaptive.elementWidth / adaptive.elementHeight;
83373                 const ratio = adaptive.imageAspect / elementAspect;
83374                 let verticalOffset = 0;
83375                 let horizontalOffset = 0;
83376                 if (adaptive.renderMode === exports.RenderMode.Letterbox) {
83377                     if (adaptive.imageAspect > elementAspect) {
83378                         verticalOffset = adaptive.elementHeight * (1 - 1 / ratio) / 2;
83379                     }
83380                     else {
83381                         horizontalOffset = adaptive.elementWidth * (1 - ratio) / 2;
83382                     }
83383                 }
83384                 else {
83385                     if (adaptive.imageAspect > elementAspect) {
83386                         horizontalOffset = -adaptive.elementWidth * (ratio - 1) / 2;
83387                     }
83388                     else {
83389                         verticalOffset = -adaptive.elementHeight * (1 / ratio - 1) / 2;
83390                     }
83391                 }
83392                 return {
83393                     bottom: verticalOffset,
83394                     left: horizontalOffset,
83395                     right: horizontalOffset,
83396                     top: verticalOffset,
83397                 };
83398             }));
83399             const imageAspectSubscription = this._currentFrame$.pipe(filter((frame) => {
83400                 return frame.state.currentImage != null;
83401             }), distinctUntilChanged((k1, k2) => {
83402                 return k1 === k2;
83403             }, (frame) => {
83404                 return frame.state.currentImage.id;
83405             }), map((frame) => {
83406                 return frame.state.currentTransform.basicAspect;
83407             }), map((aspect) => {
83408                 return (adaptive) => {
83409                     adaptive.imageAspect = aspect;
83410                     return adaptive;
83411                 };
83412             }))
83413                 .subscribe(this._adaptiveOperation$);
83414             const renderAdaptiveSubscription = combineLatest(this._renderAdaptive$.pipe(scan((vNodeHashes, vNodeHash) => {
83415                 if (vNodeHash.vNode == null) {
83416                     delete vNodeHashes[vNodeHash.name];
83417                 }
83418                 else {
83419                     vNodeHashes[vNodeHash.name] = vNodeHash.vNode;
83420                 }
83421                 return vNodeHashes;
83422             }, {})), this._offset$).pipe(map((vo) => {
83423                 const vNodes = [];
83424                 const hashes = vo[0];
83425                 for (const name in hashes) {
83426                     if (!hashes.hasOwnProperty(name)) {
83427                         continue;
83428                     }
83429                     vNodes.push(hashes[name]);
83430                 }
83431                 const offset = vo[1];
83432                 const properties = {
83433                     style: {
83434                         bottom: offset.bottom + "px",
83435                         left: offset.left + "px",
83436                         "pointer-events": "none",
83437                         position: "absolute",
83438                         right: offset.right + "px",
83439                         top: offset.top + "px",
83440                     },
83441                 };
83442                 return {
83443                     name: "mapillary-dom-adaptive-renderer",
83444                     vNode: virtualDom.h("div.mapillary-dom-adaptive-renderer", properties, vNodes),
83445                 };
83446             }))
83447                 .subscribe(this._render$);
83448             this._vNode$ = this._render$.pipe(scan((vNodeHashes, vNodeHash) => {
83449                 if (vNodeHash.vNode == null) {
83450                     delete vNodeHashes[vNodeHash.name];
83451                 }
83452                 else {
83453                     vNodeHashes[vNodeHash.name] = vNodeHash.vNode;
83454                 }
83455                 return vNodeHashes;
83456             }, {}), map((hashes) => {
83457                 const vNodes = [];
83458                 for (const name in hashes) {
83459                     if (!hashes.hasOwnProperty(name)) {
83460                         continue;
83461                     }
83462                     vNodes.push(hashes[name]);
83463                 }
83464                 return virtualDom.h("div.mapillary-dom-renderer", vNodes);
83465             }));
83466             this._vPatch$ = this._vNode$.pipe(scan((nodePatch, vNode) => {
83467                 nodePatch.vpatch = virtualDom.diff(nodePatch.vNode, vNode);
83468                 nodePatch.vNode = vNode;
83469                 return nodePatch;
83470             }, { vNode: virtualDom.h("div.mapillary-dom-renderer", []), vpatch: null }), pluck("vpatch"));
83471             this._element$ = this._vPatch$.pipe(scan((oldElement, vPatch) => {
83472                 return virtualDom.patch(oldElement, vPatch);
83473             }, rootNode), publishReplay(1), refCount());
83474             subs.push(imageAspectSubscription);
83475             subs.push(renderAdaptiveSubscription);
83476             subs.push(this._element$.subscribe(() => { }));
83477             subs.push(this._renderService.size$.pipe(map((size) => {
83478                 return (adaptive) => {
83479                     adaptive.elementWidth = size.width;
83480                     adaptive.elementHeight = size.height;
83481                     return adaptive;
83482                 };
83483             }))
83484                 .subscribe(this._adaptiveOperation$));
83485             subs.push(this._renderService.renderMode$.pipe(map((renderMode) => {
83486                 return (adaptive) => {
83487                     adaptive.renderMode = renderMode;
83488                     return adaptive;
83489                 };
83490             }))
83491                 .subscribe(this._adaptiveOperation$));
83492         }
83493         get element$() {
83494             return this._element$;
83495         }
83496         get render$() {
83497             return this._render$;
83498         }
83499         get renderAdaptive$() {
83500             return this._renderAdaptive$;
83501         }
83502         clear(name) {
83503             this._renderAdaptive$.next({ name: name, vNode: null });
83504             this._render$.next({ name: name, vNode: null });
83505         }
83506         remove() {
83507             this._subscriptions.unsubscribe();
83508         }
83509     }
83510
83511     class GLRenderer {
83512         constructor(canvas, canvasContainer, renderService) {
83513             this._renderFrame$ = new Subject();
83514             this._renderCameraOperation$ = new Subject();
83515             this._render$ = new Subject();
83516             this._clear$ = new Subject();
83517             this._renderOperation$ = new Subject();
83518             this._rendererOperation$ = new Subject();
83519             this._eraserOperation$ = new Subject();
83520             this._triggerOperation$ = new Subject();
83521             this._subscriptions = new SubscriptionHolder();
83522             this._opaqueRender$ = new Subject();
83523             this._renderService = renderService;
83524             const subs = this._subscriptions;
83525             this._renderer$ = this._rendererOperation$.pipe(scan((renderer, operation) => {
83526                 return operation(renderer);
83527             }, { needsRender: false, renderer: null }), filter((renderer) => {
83528                 return !!renderer.renderer;
83529             }));
83530             this._renderCollection$ = this._renderOperation$.pipe(scan((hashes, operation) => {
83531                 return operation(hashes);
83532             }, {}), share());
83533             this._renderCamera$ = this._renderCameraOperation$.pipe(scan((rc, operation) => {
83534                 return operation(rc);
83535             }, { frameId: -1, needsRender: false, perspective: null }));
83536             this._eraser$ = this._eraserOperation$.pipe(startWith((eraser) => {
83537                 return eraser;
83538             }), scan((eraser, operation) => {
83539                 return operation(eraser);
83540             }, { needsRender: false }));
83541             const trigger$ = this._triggerOperation$.pipe(startWith((trigger) => {
83542                 return trigger;
83543             }), scan((trigger, operation) => {
83544                 return operation(trigger);
83545             }, { needsRender: false }));
83546             const clearColor = new Color(0x0F0F0F);
83547             const renderSubscription = combineLatest(this._renderer$, this._renderCollection$, this._renderCamera$, this._eraser$, trigger$).pipe(map(([renderer, hashes, rc, eraser, trigger]) => {
83548                 const renders = Object.keys(hashes)
83549                     .map((key) => {
83550                     return hashes[key];
83551                 });
83552                 return { camera: rc, eraser: eraser, trigger: trigger, renderer: renderer, renders: renders };
83553             }), filter((co) => {
83554                 let needsRender = co.renderer.needsRender ||
83555                     co.camera.needsRender ||
83556                     co.eraser.needsRender ||
83557                     co.trigger.needsRender;
83558                 const frameId = co.camera.frameId;
83559                 for (const render of co.renders) {
83560                     if (render.frameId !== frameId) {
83561                         return false;
83562                     }
83563                     needsRender = needsRender || render.needsRender;
83564                 }
83565                 return needsRender;
83566             }), distinctUntilChanged((n1, n2) => {
83567                 return n1 === n2;
83568             }, (co) => {
83569                 return co.eraser.needsRender ||
83570                     co.trigger.needsRender ? -co.camera.frameId : co.camera.frameId;
83571             }))
83572                 .subscribe((co) => {
83573                 co.renderer.needsRender = false;
83574                 co.camera.needsRender = false;
83575                 co.eraser.needsRender = false;
83576                 co.trigger.needsRender = false;
83577                 const perspectiveCamera = co.camera.perspective;
83578                 const backgroundRenders = [];
83579                 const opaqueRenders = [];
83580                 for (const render of co.renders) {
83581                     if (render.pass === RenderPass.Background) {
83582                         backgroundRenders.push(render.render);
83583                     }
83584                     else if (render.pass === RenderPass.Opaque) {
83585                         opaqueRenders.push(render.render);
83586                     }
83587                 }
83588                 const renderer = co.renderer.renderer;
83589                 renderer.resetState();
83590                 renderer.setClearColor(clearColor, 1.0);
83591                 renderer.clear();
83592                 for (const renderBackground of backgroundRenders) {
83593                     renderBackground(perspectiveCamera, renderer);
83594                 }
83595                 renderer.clearDepth();
83596                 for (const renderOpaque of opaqueRenders) {
83597                     renderOpaque(perspectiveCamera, renderer);
83598                 }
83599                 renderer.resetState();
83600                 this._opaqueRender$.next();
83601             });
83602             subs.push(renderSubscription);
83603             subs.push(this._renderFrame$.pipe(map((rc) => {
83604                 return (irc) => {
83605                     irc.frameId = rc.frameId;
83606                     irc.perspective = rc.perspective;
83607                     if (rc.changed === true) {
83608                         irc.needsRender = true;
83609                     }
83610                     return irc;
83611                 };
83612             }))
83613                 .subscribe(this._renderCameraOperation$));
83614             this._renderFrameSubscribe();
83615             const renderHash$ = this._render$.pipe(map((hash) => {
83616                 return (hashes) => {
83617                     hashes[hash.name] = hash.renderer;
83618                     return hashes;
83619                 };
83620             }));
83621             const clearHash$ = this._clear$.pipe(map((name) => {
83622                 return (hashes) => {
83623                     delete hashes[name];
83624                     return hashes;
83625                 };
83626             }));
83627             subs.push(merge(renderHash$, clearHash$)
83628                 .subscribe(this._renderOperation$));
83629             this._webGLRenderer$ = this._render$.pipe(first(), map(() => {
83630                 canvasContainer.appendChild(canvas);
83631                 const element = renderService.element;
83632                 const webGLRenderer = new WebGLRenderer({ canvas: canvas });
83633                 webGLRenderer.setPixelRatio(window.devicePixelRatio);
83634                 webGLRenderer.setSize(element.offsetWidth, element.offsetHeight);
83635                 webGLRenderer.autoClear = false;
83636                 return webGLRenderer;
83637             }), publishReplay(1), refCount());
83638             subs.push(this._webGLRenderer$
83639                 .subscribe(() => { }));
83640             const createRenderer$ = this._webGLRenderer$.pipe(first(), map((webGLRenderer) => {
83641                 return (renderer) => {
83642                     renderer.needsRender = true;
83643                     renderer.renderer = webGLRenderer;
83644                     return renderer;
83645                 };
83646             }));
83647             const resizeRenderer$ = this._renderService.size$.pipe(map((size) => {
83648                 return (renderer) => {
83649                     if (renderer.renderer == null) {
83650                         return renderer;
83651                     }
83652                     renderer.renderer.setSize(size.width, size.height);
83653                     renderer.needsRender = true;
83654                     return renderer;
83655                 };
83656             }));
83657             const clearRenderer$ = this._clear$.pipe(map(() => {
83658                 return (renderer) => {
83659                     if (renderer.renderer == null) {
83660                         return renderer;
83661                     }
83662                     renderer.needsRender = true;
83663                     return renderer;
83664                 };
83665             }));
83666             subs.push(merge(createRenderer$, resizeRenderer$, clearRenderer$)
83667                 .subscribe(this._rendererOperation$));
83668             const renderCollectionEmpty$ = this._renderCollection$.pipe(filter((hashes) => {
83669                 return Object.keys(hashes).length === 0;
83670             }), share());
83671             subs.push(renderCollectionEmpty$
83672                 .subscribe(() => {
83673                 if (this._renderFrameSubscription == null) {
83674                     return;
83675                 }
83676                 this._renderFrameSubscription.unsubscribe();
83677                 this._renderFrameSubscription = null;
83678                 this._renderFrameSubscribe();
83679             }));
83680             subs.push(renderCollectionEmpty$.pipe(map(() => {
83681                 return (eraser) => {
83682                     eraser.needsRender = true;
83683                     return eraser;
83684                 };
83685             }))
83686                 .subscribe(this._eraserOperation$));
83687         }
83688         get render$() {
83689             return this._render$;
83690         }
83691         get opaqueRender$() {
83692             return this._opaqueRender$;
83693         }
83694         get webGLRenderer$() {
83695             return this._webGLRenderer$;
83696         }
83697         clear(name) {
83698             this._clear$.next(name);
83699         }
83700         remove() {
83701             this._rendererOperation$.next((renderer) => {
83702                 if (renderer.renderer != null) {
83703                     const extension = renderer.renderer
83704                         .getContext()
83705                         .getExtension('WEBGL_lose_context');
83706                     if (!!extension) {
83707                         extension.loseContext();
83708                     }
83709                     renderer.renderer = null;
83710                 }
83711                 return renderer;
83712             });
83713             if (this._renderFrameSubscription != null) {
83714                 this._renderFrameSubscription.unsubscribe();
83715             }
83716             this._subscriptions.unsubscribe();
83717         }
83718         triggerRerender() {
83719             this._renderService.renderCameraFrame$
83720                 .pipe(skip(1), first())
83721                 .subscribe(() => {
83722                 this._triggerOperation$.next((trigger) => {
83723                     trigger.needsRender = true;
83724                     return trigger;
83725                 });
83726             });
83727         }
83728         _renderFrameSubscribe() {
83729             this._render$.pipe(first(), map(() => {
83730                 return (irc) => {
83731                     irc.needsRender = true;
83732                     return irc;
83733                 };
83734             }))
83735                 .subscribe((operation) => {
83736                 this._renderCameraOperation$.next(operation);
83737             });
83738             this._renderFrameSubscription = this._render$.pipe(first(), mergeMap(() => {
83739                 return this._renderService.renderCameraFrame$;
83740             }))
83741                 .subscribe(this._renderFrame$);
83742         }
83743     }
83744
83745     class RenderCamera {
83746         constructor(elementWidth, elementHeight, renderMode) {
83747             this._spatial = new Spatial();
83748             this._viewportCoords = new ViewportCoords();
83749             this._size = { width: elementWidth, height: elementHeight };
83750             this._initialFov = 60;
83751             this._alpha = -1;
83752             this._renderMode = renderMode;
83753             this._zoom = 0;
83754             this._frameId = -1;
83755             this._changed = false;
83756             this._changedForFrame = -1;
83757             this._currentImageId = null;
83758             this._previousImageId = null;
83759             this._currentSpherical = false;
83760             this._previousSpherical = false;
83761             this._state = null;
83762             this._currentProjectedPoints = [];
83763             this._previousProjectedPoints = [];
83764             this._currentFov = this._initialFov;
83765             this._previousFov = this._initialFov;
83766             this._camera = new Camera();
83767             this._perspective = new PerspectiveCamera(this._initialFov, this._computeAspect(elementWidth, elementHeight), 0.16, 10000);
83768             this._perspective.position.copy(this._camera.position);
83769             this._perspective.up.copy(this._camera.up);
83770             this._perspective.lookAt(this._camera.lookat);
83771             this._perspective.updateMatrixWorld(true);
83772             this._perspective.matrixAutoUpdate = false;
83773             this._rotation = { phi: 0, theta: 0 };
83774         }
83775         get alpha() {
83776             return this._alpha;
83777         }
83778         get camera() {
83779             return this._camera;
83780         }
83781         get changed() {
83782             return this._frameId === this._changedForFrame;
83783         }
83784         get frameId() {
83785             return this._frameId;
83786         }
83787         get perspective() {
83788             return this._perspective;
83789         }
83790         get renderMode() {
83791             return this._renderMode;
83792         }
83793         get rotation() {
83794             return this._rotation;
83795         }
83796         get zoom() {
83797             return this._zoom;
83798         }
83799         get size() {
83800             return this._size;
83801         }
83802         getTilt() {
83803             return 90 - this._spatial.radToDeg(this._rotation.theta);
83804         }
83805         fovToZoom(fov) {
83806             fov = Math.min(90, Math.max(0, fov));
83807             const currentFov = this._computeCurrentFov(0);
83808             const actualFov = this._alpha === 1 ?
83809                 currentFov :
83810                 this._interpolateFov(currentFov, this._computePreviousFov(0), this._alpha);
83811             const y0 = Math.tan(actualFov / 2 * Math.PI / 180);
83812             const y1 = Math.tan(fov / 2 * Math.PI / 180);
83813             const zoom = Math.log(y0 / y1) / Math.log(2);
83814             return zoom;
83815         }
83816         setFrame(frame) {
83817             const state = frame.state;
83818             if (state.state !== this._state) {
83819                 this._state = state.state;
83820                 if (this._state !== State.Custom) {
83821                     this.setRenderMode(this._renderMode);
83822                     this.setSize(this._size);
83823                 }
83824                 this._changed = true;
83825             }
83826             const currentImageId = state.currentImage.id;
83827             const previousImageId = !!state.previousImage ? state.previousImage.id : null;
83828             if (currentImageId !== this._currentImageId) {
83829                 this._currentImageId = currentImageId;
83830                 this._currentSpherical = isSpherical(state.currentTransform.cameraType);
83831                 this._currentProjectedPoints = this._computeProjectedPoints(state.currentTransform);
83832                 this._changed = true;
83833             }
83834             if (previousImageId !== this._previousImageId) {
83835                 this._previousImageId = previousImageId;
83836                 this._previousSpherical =
83837                     isSpherical(state.previousTransform.cameraType);
83838                 this._previousProjectedPoints = this._computeProjectedPoints(state.previousTransform);
83839                 this._changed = true;
83840             }
83841             const zoom = state.zoom;
83842             if (zoom !== this._zoom) {
83843                 this._zoom = zoom;
83844                 this._changed = true;
83845             }
83846             if (this._changed) {
83847                 this._currentFov = this._computeCurrentFov(this.zoom);
83848                 this._previousFov = this._computePreviousFov(this._zoom);
83849             }
83850             const alpha = state.alpha;
83851             if (this._changed || alpha !== this._alpha) {
83852                 this._alpha = alpha;
83853                 switch (this._state) {
83854                     case State.Earth:
83855                         this._perspective.fov = 60;
83856                         this._changed = true;
83857                         break;
83858                     case State.Custom:
83859                         break;
83860                     default:
83861                         this._perspective.fov =
83862                             this._interpolateFov(this._currentFov, this._previousFov, this._alpha);
83863                         this._changed = true;
83864                         break;
83865                 }
83866                 if (this._state !== State.Custom) {
83867                     this._perspective.updateProjectionMatrix();
83868                 }
83869             }
83870             const camera = state.camera;
83871             if (this._camera.diff(camera) > 1e-9) {
83872                 this._camera.copy(camera);
83873                 this._rotation = this._computeRotation(camera);
83874                 this._perspective.up.copy(camera.up);
83875                 this._perspective.position.copy(camera.position);
83876                 // Workaround for shaking camera
83877                 this._perspective.matrixAutoUpdate = true;
83878                 this._perspective.lookAt(camera.lookat);
83879                 this._perspective.matrixAutoUpdate = false;
83880                 this._perspective.updateMatrix();
83881                 this._perspective.updateMatrixWorld(false);
83882                 this._changed = true;
83883             }
83884             this._setFrameId(frame.id);
83885         }
83886         setProjectionMatrix(matrix) {
83887             this._perspective.projectionMatrix.fromArray(matrix);
83888             this._perspective.projectionMatrixInverse
83889                 .copy(this._perspective.projectionMatrix)
83890                 .invert();
83891             this._changed = true;
83892         }
83893         setRenderMode(renderMode) {
83894             this._renderMode = renderMode;
83895             if (this._state === State.Custom) {
83896                 return;
83897             }
83898             this._perspective.fov = this._computeFov();
83899             this._perspective.updateProjectionMatrix();
83900             this._changed = true;
83901         }
83902         setSize(size) {
83903             this._size = size;
83904             if (this._state === State.Custom) {
83905                 return;
83906             }
83907             this._perspective.aspect = this._computeAspect(size.width, size.height);
83908             this._perspective.fov = this._computeFov();
83909             this._perspective.updateProjectionMatrix();
83910             this._changed = true;
83911         }
83912         _computeAspect(elementWidth, elementHeight) {
83913             return elementWidth === 0 ? 0 : elementWidth / elementHeight;
83914         }
83915         _computeCurrentFov(zoom) {
83916             if (this._perspective.aspect === 0) {
83917                 return 0;
83918             }
83919             if (!this._currentImageId) {
83920                 return this._initialFov;
83921             }
83922             return this._currentSpherical ?
83923                 this._yToFov(1, zoom) :
83924                 this._computeVerticalFov(this._currentProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
83925         }
83926         _computeFov() {
83927             this._currentFov = this._computeCurrentFov(this._zoom);
83928             this._previousFov = this._computePreviousFov(this._zoom);
83929             return this._interpolateFov(this._currentFov, this._previousFov, this._alpha);
83930         }
83931         _computePreviousFov(zoom) {
83932             if (this._perspective.aspect === 0) {
83933                 return 0;
83934             }
83935             if (!this._currentImageId) {
83936                 return this._initialFov;
83937             }
83938             return !this._previousImageId ?
83939                 this._currentFov :
83940                 this._previousSpherical ?
83941                     this._yToFov(1, zoom) :
83942                     this._computeVerticalFov(this._previousProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
83943         }
83944         _computeProjectedPoints(transform) {
83945             const vertices = [[0.5, 0], [1, 0]];
83946             const directions = [[0.5, 0], [0, 0.5]];
83947             const pointsPerLine = 100;
83948             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
83949         }
83950         _computeRequiredVerticalFov(projectedPoint, zoom, aspect) {
83951             const maxY = Math.max(projectedPoint[0] / aspect, projectedPoint[1]);
83952             return this._yToFov(maxY, zoom);
83953         }
83954         _computeRotation(camera) {
83955             let direction = camera.lookat.clone().sub(camera.position);
83956             let up = camera.up.clone();
83957             let phi = this._spatial.azimuthal(direction.toArray(), up.toArray());
83958             let theta = Math.PI / 2 - this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
83959             return { phi: phi, theta: theta };
83960         }
83961         _computeVerticalFov(projectedPoints, renderMode, zoom, aspect) {
83962             const fovs = projectedPoints
83963                 .map((projectedPoint) => {
83964                 return this._computeRequiredVerticalFov(projectedPoint, zoom, aspect);
83965             });
83966             const fov = renderMode === exports.RenderMode.Fill ?
83967                 Math.min(...fovs) * 0.995 :
83968                 Math.max(...fovs);
83969             return fov;
83970         }
83971         _yToFov(y, zoom) {
83972             return 2 * Math.atan(y / Math.pow(2, zoom)) * 180 / Math.PI;
83973         }
83974         _interpolateFov(v1, v2, alpha) {
83975             return alpha * v1 + (1 - alpha) * v2;
83976         }
83977         _setFrameId(frameId) {
83978             this._frameId = frameId;
83979             if (this._changed) {
83980                 this._changed = false;
83981                 this._changedForFrame = frameId;
83982             }
83983         }
83984     }
83985
83986     class RenderService {
83987         constructor(element, currentFrame$, renderMode, renderCamera) {
83988             this._subscriptions = new SubscriptionHolder();
83989             this._element = element;
83990             this._currentFrame$ = currentFrame$;
83991             this._spatial = new Spatial();
83992             renderMode = renderMode != null ? renderMode : exports.RenderMode.Fill;
83993             this._resize$ = new Subject();
83994             this._projectionMatrix$ = new Subject();
83995             this._renderCameraOperation$ =
83996                 new Subject();
83997             this._size$ =
83998                 new BehaviorSubject({
83999                     height: this._element.offsetHeight,
84000                     width: this._element.offsetWidth,
84001                 });
84002             const subs = this._subscriptions;
84003             subs.push(this._resize$.pipe(map(() => {
84004                 return {
84005                     height: this._element.offsetHeight,
84006                     width: this._element.offsetWidth,
84007                 };
84008             }))
84009                 .subscribe(this._size$));
84010             this._renderMode$ = new BehaviorSubject(renderMode);
84011             this._renderCameraHolder$ = this._renderCameraOperation$.pipe(startWith((rc) => {
84012                 return rc;
84013             }), scan((rc, operation) => {
84014                 return operation(rc);
84015             }, renderCamera !== null && renderCamera !== void 0 ? renderCamera : new RenderCamera(this._element.offsetWidth, this._element.offsetHeight, renderMode)), publishReplay(1), refCount());
84016             this._renderCameraFrame$ = this._currentFrame$.pipe(withLatestFrom(this._renderCameraHolder$), tap(([frame, rc]) => {
84017                 rc.setFrame(frame);
84018             }), map((args) => {
84019                 return args[1];
84020             }), publishReplay(1), refCount());
84021             this._renderCamera$ = this._renderCameraFrame$.pipe(filter((rc) => {
84022                 return rc.changed;
84023             }), publishReplay(1), refCount());
84024             this._bearing$ = this._renderCamera$.pipe(map((rc) => {
84025                 let bearing = this._spatial.radToDeg(this._spatial.azimuthalToBearing(rc.rotation.phi));
84026                 return this._spatial.wrap(bearing, 0, 360);
84027             }), publishReplay(1), refCount());
84028             subs.push(this._size$.pipe(skip(1), map((size) => {
84029                 return (rc) => {
84030                     rc.setSize(size);
84031                     return rc;
84032                 };
84033             }))
84034                 .subscribe(this._renderCameraOperation$));
84035             subs.push(this._renderMode$.pipe(skip(1), map((rm) => {
84036                 return (rc) => {
84037                     rc.setRenderMode(rm);
84038                     return rc;
84039                 };
84040             }))
84041                 .subscribe(this._renderCameraOperation$));
84042             subs.push(this._projectionMatrix$.pipe(map((projectionMatrix) => {
84043                 return (rc) => {
84044                     rc.setProjectionMatrix(projectionMatrix);
84045                     return rc;
84046                 };
84047             }))
84048                 .subscribe(this._renderCameraOperation$));
84049             subs.push(this._bearing$.subscribe(() => { }));
84050             subs.push(this._renderCameraHolder$.subscribe(() => { }));
84051             subs.push(this._size$.subscribe(() => { }));
84052             subs.push(this._renderMode$.subscribe(() => { }));
84053             subs.push(this._renderCamera$.subscribe(() => { }));
84054             subs.push(this._renderCameraFrame$.subscribe(() => { }));
84055         }
84056         get bearing$() {
84057             return this._bearing$;
84058         }
84059         get element() {
84060             return this._element;
84061         }
84062         get projectionMatrix$() {
84063             return this._projectionMatrix$;
84064         }
84065         get renderCamera$() {
84066             return this._renderCamera$;
84067         }
84068         get renderCameraFrame$() {
84069             return this._renderCameraFrame$;
84070         }
84071         get renderMode$() {
84072             return this._renderMode$;
84073         }
84074         get resize$() {
84075             return this._resize$;
84076         }
84077         get size$() {
84078             return this._size$;
84079         }
84080         dispose() {
84081             this._subscriptions.unsubscribe();
84082         }
84083     }
84084
84085     class KeyboardService {
84086         constructor(canvasContainer) {
84087             this._keyDown$ = fromEvent(canvasContainer, "keydown");
84088             this._keyUp$ = fromEvent(canvasContainer, "keyup");
84089         }
84090         get keyDown$() {
84091             return this._keyDown$;
84092         }
84093         get keyUp$() {
84094             return this._keyUp$;
84095         }
84096     }
84097
84098     // MouseEvent.button
84099     const LEFT_BUTTON = 0;
84100     const RIGHT_BUTTON = 2;
84101     // MouseEvent.buttons
84102     const BUTTONS_MAP = {
84103         [LEFT_BUTTON]: 1,
84104         [RIGHT_BUTTON]: 2
84105     };
84106     class MouseService {
84107         constructor(container, canvasContainer, domContainer, doc) {
84108             this._subscriptions = new SubscriptionHolder();
84109             const subs = this._subscriptions;
84110             this._activeSubject$ = new BehaviorSubject(false);
84111             this._active$ = this._activeSubject$
84112                 .pipe(distinctUntilChanged(), publishReplay(1), refCount());
84113             this._claimMouse$ = new Subject();
84114             this._claimWheel$ = new Subject();
84115             this._deferPixelClaims$ = new Subject();
84116             this._deferPixels$ = this._deferPixelClaims$
84117                 .pipe(scan((claims, claim) => {
84118                 if (claim.deferPixels == null) {
84119                     delete claims[claim.name];
84120                 }
84121                 else {
84122                     claims[claim.name] = claim.deferPixels;
84123                 }
84124                 return claims;
84125             }, {}), map((claims) => {
84126                 let deferPixelMax = -1;
84127                 for (const key in claims) {
84128                     if (!claims.hasOwnProperty(key)) {
84129                         continue;
84130                     }
84131                     const deferPixels = claims[key];
84132                     if (deferPixels > deferPixelMax) {
84133                         deferPixelMax = deferPixels;
84134                     }
84135                 }
84136                 return deferPixelMax;
84137             }), startWith(-1), publishReplay(1), refCount());
84138             subs.push(this._deferPixels$.subscribe(() => { }));
84139             this._documentMouseMove$ =
84140                 fromEvent(doc, "pointermove")
84141                     .pipe(filter(this._isMousePen));
84142             this._documentMouseUp$ =
84143                 fromEvent(doc, "pointerup")
84144                     .pipe(filter(this._isMousePen));
84145             this._mouseDown$ =
84146                 fromEvent(canvasContainer, "pointerdown")
84147                     .pipe(filter(this._isMousePen));
84148             this._mouseEnter$ =
84149                 fromEvent(canvasContainer, "pointerenter")
84150                     .pipe(filter(this._isMousePen));
84151             this._mouseLeave$ =
84152                 fromEvent(canvasContainer, "pointerleave")
84153                     .pipe(filter(this._isMousePen));
84154             this._mouseMove$ =
84155                 fromEvent(canvasContainer, "pointermove")
84156                     .pipe(filter(this._isMousePen));
84157             this._mouseUp$ =
84158                 fromEvent(canvasContainer, "pointerup")
84159                     .pipe(filter(this._isMousePen));
84160             this._mouseOut$ =
84161                 fromEvent(canvasContainer, "pointerout")
84162                     .pipe(filter(this._isMousePen));
84163             this._mouseOver$ =
84164                 fromEvent(canvasContainer, "pointerover")
84165                     .pipe(filter(this._isMousePen));
84166             this._domMouseDown$ =
84167                 fromEvent(domContainer, "pointerdown")
84168                     .pipe(filter(this._isMousePen));
84169             this._domMouseMove$ =
84170                 fromEvent(domContainer, "pointermove")
84171                     .pipe(filter(this._isMousePen));
84172             this._click$ =
84173                 fromEvent(canvasContainer, "click");
84174             this._contextMenu$ =
84175                 fromEvent(canvasContainer, "contextmenu");
84176             this._windowBlur$ =
84177                 fromEvent(window, "blur");
84178             this._dblClick$ = merge(fromEvent(container, "click"), fromEvent(canvasContainer, "dblclick"))
84179                 .pipe(bufferCount(3, 1), filter((events) => {
84180                 const event1 = events[0];
84181                 const event2 = events[1];
84182                 const event3 = events[2];
84183                 return event1.type === "click" &&
84184                     event2.type === "click" &&
84185                     event3.type === "dblclick" &&
84186                     event1.target.parentNode === canvasContainer &&
84187                     event2.target.parentNode === canvasContainer;
84188             }), map((events) => {
84189                 return events[2];
84190             }), share());
84191             subs.push(merge(this._domMouseDown$, this._domMouseMove$, this._dblClick$, this._contextMenu$)
84192                 .subscribe((event) => {
84193                 event.preventDefault();
84194             }));
84195             this._mouseWheel$ = merge(fromEvent(canvasContainer, "wheel"), fromEvent(domContainer, "wheel"))
84196                 .pipe(share());
84197             this._consistentContextMenu$ =
84198                 merge(this._mouseDown$, this._mouseMove$, this._mouseOut$, this._mouseUp$, this._contextMenu$)
84199                     .pipe(bufferCount(3, 1), filter((events) => {
84200                     // fire context menu on mouse up both on mac and windows
84201                     return events[0].type === "pointerdown" &&
84202                         events[1].type === "contextmenu" &&
84203                         events[2].type === "pointerup";
84204                 }), map((events) => {
84205                     return events[1];
84206                 }), share());
84207             const dragStop$ = merge(this._windowBlur$, this._documentMouseMove$
84208                 .pipe(filter((e) => {
84209                 return this._buttonReleased(e, LEFT_BUTTON);
84210             })), this._documentMouseUp$
84211                 .pipe(filter((e) => {
84212                 return this._mouseButton(e) === LEFT_BUTTON;
84213             })))
84214                 .pipe(share());
84215             const mouseDragInitiate$ = this._createMouseDragInitiate$(LEFT_BUTTON, this._mouseDown$, dragStop$, true)
84216                 .pipe(share());
84217             this._mouseDragStart$ =
84218                 this._createMouseDragStart$(mouseDragInitiate$)
84219                     .pipe(share());
84220             this._mouseDrag$ =
84221                 this._createMouseDrag$(mouseDragInitiate$, dragStop$)
84222                     .pipe(share());
84223             this._mouseDragEnd$ =
84224                 this._createMouseDragEnd$(this._mouseDragStart$, dragStop$)
84225                     .pipe(share());
84226             const domMouseDragInitiate$ = this._createMouseDragInitiate$(LEFT_BUTTON, this._domMouseDown$, dragStop$, false)
84227                 .pipe(share());
84228             this._domMouseDragStart$ =
84229                 this._createMouseDragStart$(domMouseDragInitiate$)
84230                     .pipe(share());
84231             this._domMouseDrag$ =
84232                 this._createMouseDrag$(domMouseDragInitiate$, dragStop$)
84233                     .pipe(share());
84234             this._domMouseDragEnd$ =
84235                 this._createMouseDragEnd$(this._domMouseDragStart$, dragStop$)
84236                     .pipe(share());
84237             const rightDragStop$ = merge(this._windowBlur$, this._documentMouseMove$.pipe(filter((e) => {
84238                 return this._buttonReleased(e, RIGHT_BUTTON);
84239             })), this._documentMouseUp$.pipe(filter((e) => {
84240                 return this._mouseButton(e) === RIGHT_BUTTON;
84241             })))
84242                 .pipe(share());
84243             const mouseRightDragInitiate$ = this._createMouseDragInitiate$(RIGHT_BUTTON, this._mouseDown$, rightDragStop$, true)
84244                 .pipe(share());
84245             this._mouseRightDragStart$ =
84246                 this._createMouseDragStart$(mouseRightDragInitiate$)
84247                     .pipe(share());
84248             this._mouseRightDrag$ =
84249                 this._createMouseDrag$(mouseRightDragInitiate$, rightDragStop$)
84250                     .pipe(share());
84251             this._mouseRightDragEnd$ =
84252                 this._createMouseDragEnd$(this._mouseRightDragStart$, rightDragStop$)
84253                     .pipe(share());
84254             this._proximateClick$ = this._mouseDown$
84255                 .pipe(switchMap((mouseDown) => {
84256                 return this._click$.pipe(takeUntil(this._createDeferredMouseMove$(mouseDown, this._documentMouseMove$)), take(1));
84257             }), share());
84258             this._staticClick$ = this._mouseDown$
84259                 .pipe(switchMap(() => {
84260                 return this._click$.pipe(takeUntil(this._documentMouseMove$), take(1));
84261             }), share());
84262             subs.push(this._mouseDragStart$.subscribe());
84263             subs.push(this._mouseDrag$.subscribe());
84264             subs.push(this._mouseDragEnd$.subscribe());
84265             subs.push(this._domMouseDragStart$.subscribe());
84266             subs.push(this._domMouseDrag$.subscribe());
84267             subs.push(this._domMouseDragEnd$.subscribe());
84268             subs.push(this._mouseRightDragStart$.subscribe());
84269             subs.push(this._mouseRightDrag$.subscribe());
84270             subs.push(this._mouseRightDragEnd$.subscribe());
84271             subs.push(this._staticClick$.subscribe());
84272             this._mouseOwner$ = this._createOwner$(this._claimMouse$)
84273                 .pipe(publishReplay(1), refCount());
84274             this._wheelOwner$ = this._createOwner$(this._claimWheel$)
84275                 .pipe(publishReplay(1), refCount());
84276             subs.push(this._mouseOwner$.subscribe(() => { }));
84277             subs.push(this._wheelOwner$.subscribe(() => { }));
84278         }
84279         get active$() {
84280             return this._active$;
84281         }
84282         get activate$() {
84283             return this._activeSubject$;
84284         }
84285         get documentMouseMove$() {
84286             return this._documentMouseMove$;
84287         }
84288         get documentMouseUp$() {
84289             return this._documentMouseUp$;
84290         }
84291         get domMouseDragStart$() {
84292             return this._domMouseDragStart$;
84293         }
84294         get domMouseDrag$() {
84295             return this._domMouseDrag$;
84296         }
84297         get domMouseDragEnd$() {
84298             return this._domMouseDragEnd$;
84299         }
84300         get domMouseDown$() {
84301             return this._domMouseDown$;
84302         }
84303         get domMouseMove$() {
84304             return this._domMouseMove$;
84305         }
84306         get mouseOwner$() {
84307             return this._mouseOwner$;
84308         }
84309         get mouseDown$() {
84310             return this._mouseDown$;
84311         }
84312         get mouseEnter$() {
84313             return this._mouseEnter$;
84314         }
84315         get mouseMove$() {
84316             return this._mouseMove$;
84317         }
84318         get mouseLeave$() {
84319             return this._mouseLeave$;
84320         }
84321         get mouseOut$() {
84322             return this._mouseOut$;
84323         }
84324         get mouseOver$() {
84325             return this._mouseOver$;
84326         }
84327         get mouseUp$() {
84328             return this._mouseUp$;
84329         }
84330         get click$() {
84331             return this._click$;
84332         }
84333         get dblClick$() {
84334             return this._dblClick$;
84335         }
84336         get contextMenu$() {
84337             return this._consistentContextMenu$;
84338         }
84339         get mouseWheel$() {
84340             return this._mouseWheel$;
84341         }
84342         get mouseDragStart$() {
84343             return this._mouseDragStart$;
84344         }
84345         get mouseDrag$() {
84346             return this._mouseDrag$;
84347         }
84348         get mouseDragEnd$() {
84349             return this._mouseDragEnd$;
84350         }
84351         get mouseRightDragStart$() {
84352             return this._mouseRightDragStart$;
84353         }
84354         get mouseRightDrag$() {
84355             return this._mouseRightDrag$;
84356         }
84357         get mouseRightDragEnd$() {
84358             return this._mouseRightDragEnd$;
84359         }
84360         get proximateClick$() {
84361             return this._proximateClick$;
84362         }
84363         get staticClick$() {
84364             return this._staticClick$;
84365         }
84366         get windowBlur$() {
84367             return this._windowBlur$;
84368         }
84369         dispose() {
84370             this._subscriptions.unsubscribe();
84371         }
84372         claimMouse(name, zindex) {
84373             this._claimMouse$.next({ name: name, zindex: zindex });
84374         }
84375         unclaimMouse(name) {
84376             this._claimMouse$.next({ name: name, zindex: null });
84377         }
84378         deferPixels(name, deferPixels) {
84379             this._deferPixelClaims$.next({ name: name, deferPixels: deferPixels });
84380         }
84381         undeferPixels(name) {
84382             this._deferPixelClaims$.next({ name: name, deferPixels: null });
84383         }
84384         claimWheel(name, zindex) {
84385             this._claimWheel$.next({ name: name, zindex: zindex });
84386         }
84387         unclaimWheel(name) {
84388             this._claimWheel$.next({ name: name, zindex: null });
84389         }
84390         filtered$(name, observable$) {
84391             return this._filtered(name, observable$, this._mouseOwner$);
84392         }
84393         filteredWheel$(name, observable$) {
84394             return this._filtered(name, observable$, this._wheelOwner$);
84395         }
84396         _createDeferredMouseMove$(origin, mouseMove$) {
84397             return mouseMove$.pipe(map((mouseMove) => {
84398                 const deltaX = mouseMove.clientX - origin.clientX;
84399                 const deltaY = mouseMove.clientY - origin.clientY;
84400                 return [mouseMove, Math.sqrt(deltaX * deltaX + deltaY * deltaY)];
84401             }), withLatestFrom(this._deferPixels$), filter(([[, delta], deferPixels]) => {
84402                 return delta > deferPixels;
84403             }), map(([[mouseMove]]) => {
84404                 return mouseMove;
84405             }));
84406         }
84407         _createMouseDrag$(mouseDragStartInitiate$, stop$) {
84408             return mouseDragStartInitiate$.pipe(map(([, mouseMove]) => {
84409                 return mouseMove;
84410             }), switchMap((mouseMove) => {
84411                 return concat(of(mouseMove), this._documentMouseMove$).pipe(takeUntil(stop$));
84412             }));
84413         }
84414         _createMouseDragEnd$(mouseDragStart$, stop$) {
84415             return mouseDragStart$.pipe(switchMap(() => {
84416                 return stop$.pipe(first());
84417             }));
84418         }
84419         _createMouseDragStart$(mouseDragStartInitiate$) {
84420             return mouseDragStartInitiate$.pipe(map(([mouseDown]) => {
84421                 return mouseDown;
84422             }));
84423         }
84424         _createMouseDragInitiate$(button, mouseDown$, stop$, defer) {
84425             return mouseDown$.pipe(filter((mouseDown) => {
84426                 return this._mouseButton(mouseDown) === button;
84427             }), switchMap((mouseDown) => {
84428                 return combineLatest(of(mouseDown), defer ?
84429                     this._createDeferredMouseMove$(mouseDown, this._documentMouseMove$) :
84430                     this._documentMouseMove$).pipe(takeUntil(stop$), take(1));
84431             }));
84432         }
84433         _createOwner$(claim$) {
84434             return claim$.pipe(scan((claims, claim) => {
84435                 if (claim.zindex == null) {
84436                     delete claims[claim.name];
84437                 }
84438                 else {
84439                     claims[claim.name] = claim.zindex;
84440                 }
84441                 return claims;
84442             }, {}), map((claims) => {
84443                 let owner = null;
84444                 let zIndexMax = -1;
84445                 for (const name in claims) {
84446                     if (!claims.hasOwnProperty(name)) {
84447                         continue;
84448                     }
84449                     if (claims[name] > zIndexMax) {
84450                         zIndexMax = claims[name];
84451                         owner = name;
84452                     }
84453                 }
84454                 return owner;
84455             }), startWith(null));
84456         }
84457         _filtered(name, observable$, owner$) {
84458             return observable$.pipe(withLatestFrom(owner$), filter(([, owner]) => {
84459                 return owner === name;
84460             }), map(([item]) => {
84461                 return item;
84462             }));
84463         }
84464         _mouseButton(event) {
84465             const upOrDown = event.type === "pointerdown" || event.type === "pointerup";
84466             const InstallTrigger = window.InstallTrigger;
84467             if (upOrDown &&
84468                 typeof InstallTrigger !== 'undefined' &&
84469                 event.button === RIGHT_BUTTON && event.ctrlKey &&
84470                 window.navigator.platform.toUpperCase().indexOf('MAC') >= 0) {
84471                 // Fix for the fact that Firefox (detected by InstallTrigger)
84472                 // on Mac determines e.button = 2 when using Control + left click.
84473                 return LEFT_BUTTON;
84474             }
84475             return event.button;
84476         }
84477         _buttonReleased(event, button) {
84478             // Right button `mouseup` is not fired in
84479             // Chrome on Mac outside the window or iframe. If
84480             // the button is no longer pressed during move
84481             // it may have been released and drag stop
84482             // should be emitted.
84483             const flag = BUTTONS_MAP[button];
84484             return event.buttons === undefined || (event.buttons & flag) !== flag;
84485         }
84486         _isMousePen(event) {
84487             const type = event.pointerType;
84488             return type === "mouse" || type === "pen";
84489         }
84490     }
84491
84492     class SpriteAtlas {
84493         set json(value) {
84494             this._json = value;
84495         }
84496         set image(value) {
84497             this._image = value;
84498             this._texture = new Texture(this._image);
84499             this._texture.minFilter = NearestFilter;
84500         }
84501         get loaded() {
84502             return !!(this._image && this._json);
84503         }
84504         getGLSprite(name) {
84505             if (!this.loaded) {
84506                 throw new Error("Sprites cannot be retrieved before the atlas is loaded.");
84507             }
84508             let definition = this._json[name];
84509             if (!definition) {
84510                 console.warn("Sprite with key" + name + "does not exist in sprite definition.");
84511                 return new Object3D();
84512             }
84513             let texture = this._texture.clone();
84514             texture.needsUpdate = true;
84515             let width = this._image.width;
84516             let height = this._image.height;
84517             texture.offset.x = definition.x / width;
84518             texture.offset.y = (height - definition.y - definition.height) / height;
84519             texture.repeat.x = definition.width / width;
84520             texture.repeat.y = definition.height / height;
84521             let material = new SpriteMaterial({ map: texture });
84522             return new Sprite(material);
84523         }
84524         getDOMSprite(name, float) {
84525             if (!this.loaded) {
84526                 throw new Error("Sprites cannot be retrieved before the atlas is loaded.");
84527             }
84528             if (float == null) {
84529                 float = exports.Alignment.Center;
84530             }
84531             let definition = this._json[name];
84532             if (!definition) {
84533                 console.warn("Sprite with key" + name + "does not exist in sprite definition.");
84534                 return virtualDom.h("div", {}, []);
84535             }
84536             let clipTop = definition.y;
84537             let clipRigth = definition.x + definition.width;
84538             let clipBottom = definition.y + definition.height;
84539             let clipLeft = definition.x;
84540             let left = -definition.x;
84541             let top = -definition.y;
84542             let height = this._image.height;
84543             let width = this._image.width;
84544             switch (float) {
84545                 case exports.Alignment.Bottom:
84546                 case exports.Alignment.Center:
84547                 case exports.Alignment.Top:
84548                     left -= definition.width / 2;
84549                     break;
84550                 case exports.Alignment.BottomLeft:
84551                 case exports.Alignment.Left:
84552                 case exports.Alignment.TopLeft:
84553                     left -= definition.width;
84554                     break;
84555                 case exports.Alignment.BottomRight:
84556                 case exports.Alignment.Right:
84557                 case exports.Alignment.TopRight:
84558             }
84559             switch (float) {
84560                 case exports.Alignment.Center:
84561                 case exports.Alignment.Left:
84562                 case exports.Alignment.Right:
84563                     top -= definition.height / 2;
84564                     break;
84565                 case exports.Alignment.Top:
84566                 case exports.Alignment.TopLeft:
84567                 case exports.Alignment.TopRight:
84568                     top -= definition.height;
84569                     break;
84570                 case exports.Alignment.Bottom:
84571                 case exports.Alignment.BottomLeft:
84572                 case exports.Alignment.BottomRight:
84573             }
84574             let pixelRatioInverse = 1 / definition.pixelRatio;
84575             clipTop *= pixelRatioInverse;
84576             clipRigth *= pixelRatioInverse;
84577             clipBottom *= pixelRatioInverse;
84578             clipLeft *= pixelRatioInverse;
84579             left *= pixelRatioInverse;
84580             top *= pixelRatioInverse;
84581             height *= pixelRatioInverse;
84582             width *= pixelRatioInverse;
84583             let properties = {
84584                 src: this._image.src,
84585                 style: {
84586                     clip: `rect(${clipTop}px, ${clipRigth}px, ${clipBottom}px, ${clipLeft}px)`,
84587                     height: `${height}px`,
84588                     left: `${left}px`,
84589                     position: "absolute",
84590                     top: `${top}px`,
84591                     width: `${width}px`,
84592                 },
84593             };
84594             return virtualDom.h("img", properties, []);
84595         }
84596     }
84597     class SpriteService {
84598         constructor(sprite) {
84599             this._retina = window.devicePixelRatio > 1;
84600             this._spriteAtlasOperation$ = new Subject();
84601             this._spriteAtlas$ = this._spriteAtlasOperation$.pipe(startWith((atlas) => {
84602                 return atlas;
84603             }), scan((atlas, operation) => {
84604                 return operation(atlas);
84605             }, new SpriteAtlas()), publishReplay(1), refCount());
84606             this._atlasSubscription = this._spriteAtlas$
84607                 .subscribe(() => { });
84608             if (sprite == null) {
84609                 return;
84610             }
84611             let format = this._retina ? "@2x" : "";
84612             let imageXmlHTTP = new XMLHttpRequest();
84613             imageXmlHTTP.open("GET", sprite + format + ".png", true);
84614             imageXmlHTTP.responseType = "arraybuffer";
84615             imageXmlHTTP.onload = () => {
84616                 let image = new Image();
84617                 image.onload = () => {
84618                     this._spriteAtlasOperation$.next((atlas) => {
84619                         atlas.image = image;
84620                         return atlas;
84621                     });
84622                 };
84623                 let blob = new Blob([imageXmlHTTP.response]);
84624                 image.src = window.URL.createObjectURL(blob);
84625             };
84626             imageXmlHTTP.onerror = (error) => {
84627                 console.error(new Error(`Failed to fetch sprite sheet (${sprite}${format}.png)`));
84628             };
84629             imageXmlHTTP.send();
84630             let jsonXmlHTTP = new XMLHttpRequest();
84631             jsonXmlHTTP.open("GET", sprite + format + ".json", true);
84632             jsonXmlHTTP.responseType = "text";
84633             jsonXmlHTTP.onload = () => {
84634                 let json = JSON.parse(jsonXmlHTTP.response);
84635                 this._spriteAtlasOperation$.next((atlas) => {
84636                     atlas.json = json;
84637                     return atlas;
84638                 });
84639             };
84640             jsonXmlHTTP.onerror = (error) => {
84641                 console.error(new Error(`Failed to fetch sheet (${sprite}${format}.json)`));
84642             };
84643             jsonXmlHTTP.send();
84644         }
84645         get spriteAtlas$() {
84646             return this._spriteAtlas$;
84647         }
84648         dispose() {
84649             this._atlasSubscription.unsubscribe();
84650         }
84651     }
84652
84653     class TouchService {
84654         constructor(canvasContainer, domContainer) {
84655             this._subscriptions = new SubscriptionHolder();
84656             const subs = this._subscriptions;
84657             this._activeSubject$ = new BehaviorSubject(false);
84658             this._active$ = this._activeSubject$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
84659             subs.push(fromEvent(domContainer, "touchmove")
84660                 .subscribe((event) => {
84661                 event.preventDefault();
84662             }));
84663             this._touchStart$ = fromEvent(canvasContainer, "touchstart");
84664             this._touchMove$ = fromEvent(canvasContainer, "touchmove");
84665             this._touchEnd$ = fromEvent(canvasContainer, "touchend");
84666             this._touchCancel$ = fromEvent(canvasContainer, "touchcancel");
84667             const tapStart$ = this._touchStart$.pipe(filter((te) => {
84668                 return te.touches.length === 1 && te.targetTouches.length === 1;
84669             }), share());
84670             this._doubleTap$ = tapStart$.pipe(bufferWhen(() => {
84671                 return tapStart$.pipe(first(), switchMap(() => {
84672                     return merge(timer(300), tapStart$).pipe(take(1));
84673                 }));
84674             }), filter((events) => {
84675                 return events.length === 2;
84676             }), map((events) => {
84677                 return events[events.length - 1];
84678             }), share());
84679             subs.push(this._doubleTap$
84680                 .subscribe((event) => {
84681                 event.preventDefault();
84682             }));
84683             this._singleTouchMove$ = this._touchMove$.pipe(filter((te) => {
84684                 return te.touches.length === 1 && te.targetTouches.length === 1;
84685             }), share());
84686             let singleTouchStart$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
84687                 return te.touches.length === 1 && te.targetTouches.length === 1;
84688             }));
84689             let multipleTouchStart$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
84690                 return te.touches.length >= 1;
84691             }));
84692             let touchStop$ = merge(this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
84693                 return te.touches.length === 0;
84694             }));
84695             this._singleTouchDragStart$ = singleTouchStart$.pipe(mergeMap(() => {
84696                 return this._singleTouchMove$.pipe(takeUntil(merge(touchStop$, multipleTouchStart$)), take(1));
84697             }));
84698             this._singleTouchDragEnd$ = singleTouchStart$.pipe(mergeMap(() => {
84699                 return merge(touchStop$, multipleTouchStart$).pipe(first());
84700             }));
84701             this._singleTouchDrag$ = singleTouchStart$.pipe(switchMap(() => {
84702                 return this._singleTouchMove$.pipe(skip(1), takeUntil(merge(multipleTouchStart$, touchStop$)));
84703             }));
84704             let touchesChanged$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$);
84705             this._pinchStart$ = touchesChanged$.pipe(filter((te) => {
84706                 return te.touches.length === 2 && te.targetTouches.length === 2;
84707             }));
84708             this._pinchEnd$ = touchesChanged$.pipe(filter((te) => {
84709                 return te.touches.length !== 2 || te.targetTouches.length !== 2;
84710             }));
84711             this._pinchOperation$ = new Subject();
84712             this._pinch$ = this._pinchOperation$.pipe(scan((pinch, operation) => {
84713                 return operation(pinch);
84714             }, {
84715                 changeX: 0,
84716                 changeY: 0,
84717                 clientX: 0,
84718                 clientY: 0,
84719                 distance: 0,
84720                 distanceChange: 0,
84721                 distanceX: 0,
84722                 distanceY: 0,
84723                 originalEvent: null,
84724                 pageX: 0,
84725                 pageY: 0,
84726                 screenX: 0,
84727                 screenY: 0,
84728                 touch1: null,
84729                 touch2: null,
84730             }));
84731             const pinchSubscription = this._touchMove$.pipe(filter((te) => {
84732                 return te.touches.length === 2 && te.targetTouches.length === 2;
84733             }), map((te) => {
84734                 return (previous) => {
84735                     let touch1 = te.touches[0];
84736                     let touch2 = te.touches[1];
84737                     let minX = Math.min(touch1.clientX, touch2.clientX);
84738                     let maxX = Math.max(touch1.clientX, touch2.clientX);
84739                     let minY = Math.min(touch1.clientY, touch2.clientY);
84740                     let maxY = Math.max(touch1.clientY, touch2.clientY);
84741                     let centerClientX = minX + (maxX - minX) / 2;
84742                     let centerClientY = minY + (maxY - minY) / 2;
84743                     let centerPageX = centerClientX + touch1.pageX - touch1.clientX;
84744                     let centerPageY = centerClientY + touch1.pageY - touch1.clientY;
84745                     let centerScreenX = centerClientX + touch1.screenX - touch1.clientX;
84746                     let centerScreenY = centerClientY + touch1.screenY - touch1.clientY;
84747                     let distanceX = Math.abs(touch1.clientX - touch2.clientX);
84748                     let distanceY = Math.abs(touch1.clientY - touch2.clientY);
84749                     let distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
84750                     let distanceChange = distance - previous.distance;
84751                     let changeX = distanceX - previous.distanceX;
84752                     let changeY = distanceY - previous.distanceY;
84753                     let current = {
84754                         changeX: changeX,
84755                         changeY: changeY,
84756                         clientX: centerClientX,
84757                         clientY: centerClientY,
84758                         distance: distance,
84759                         distanceChange: distanceChange,
84760                         distanceX: distanceX,
84761                         distanceY: distanceY,
84762                         originalEvent: te,
84763                         pageX: centerPageX,
84764                         pageY: centerPageY,
84765                         screenX: centerScreenX,
84766                         screenY: centerScreenY,
84767                         touch1: touch1,
84768                         touch2: touch2,
84769                     };
84770                     return current;
84771                 };
84772             }))
84773                 .subscribe(this._pinchOperation$);
84774             subs.push(pinchSubscription);
84775             this._pinchChange$ = this._pinchStart$.pipe(switchMap(() => {
84776                 return this._pinch$.pipe(skip(1), takeUntil(this._pinchEnd$));
84777             }));
84778         }
84779         get active$() {
84780             return this._active$;
84781         }
84782         get activate$() {
84783             return this._activeSubject$;
84784         }
84785         get doubleTap$() {
84786             return this._doubleTap$;
84787         }
84788         get touchStart$() {
84789             return this._touchStart$;
84790         }
84791         get touchMove$() {
84792             return this._touchMove$;
84793         }
84794         get touchEnd$() {
84795             return this._touchEnd$;
84796         }
84797         get touchCancel$() {
84798             return this._touchCancel$;
84799         }
84800         get singleTouchDragStart$() {
84801             return this._singleTouchDragStart$;
84802         }
84803         get singleTouchDrag$() {
84804             return this._singleTouchDrag$;
84805         }
84806         get singleTouchDragEnd$() {
84807             return this._singleTouchDragEnd$;
84808         }
84809         get pinch$() {
84810             return this._pinchChange$;
84811         }
84812         get pinchStart$() {
84813             return this._pinchStart$;
84814         }
84815         get pinchEnd$() {
84816             return this._pinchEnd$;
84817         }
84818         dispose() {
84819             this._subscriptions.unsubscribe();
84820         }
84821     }
84822
84823     class ConfigurationService {
84824         constructor(options) {
84825             var _a, _b, _c, _d;
84826             const host = (_b = (_a = options === null || options === void 0 ? void 0 : options.url) === null || _a === void 0 ? void 0 : _a.exploreHost) !== null && _b !== void 0 ? _b : "www.mapillary.com";
84827             const scheme = (_d = (_c = options === null || options === void 0 ? void 0 : options.url) === null || _c === void 0 ? void 0 : _c.scheme) !== null && _d !== void 0 ? _d : "https";
84828             const exploreUrl = `${scheme}://${host}`;
84829             this._exploreUrl$ = of(exploreUrl);
84830             const imageTiling = (options === null || options === void 0 ? void 0 : options.imageTiling) === false ? false : true;
84831             this._imageTiling$ = of(imageTiling);
84832         }
84833         get exploreUrl$() {
84834             return this._exploreUrl$;
84835         }
84836         get imageTiling$() {
84837             return this._imageTiling$;
84838         }
84839     }
84840
84841     class Container {
84842         constructor(options, stateService, dom) {
84843             var _a;
84844             this._onWindowResize = () => {
84845                 if (this._trackResize) {
84846                     this.renderService.resize$.next();
84847                 }
84848             };
84849             this._dom = dom !== null && dom !== void 0 ? dom : new DOM();
84850             if (typeof options.container === "string") {
84851                 this._container = this._dom.document
84852                     .getElementById(options.container);
84853                 if (!this._container) {
84854                     throw new Error(`Container "${options.container}" not found.`);
84855                 }
84856             }
84857             else if (options.container instanceof HTMLElement) {
84858                 this._container = options.container;
84859             }
84860             else {
84861                 throw new Error(`Invalid type: "container" must be ` +
84862                     `a String or HTMLElement.`);
84863             }
84864             this._trackResize =
84865                 options.trackResize === false ?
84866                     false : true;
84867             this.id = (_a = this._container.id) !== null && _a !== void 0 ? _a : "mapillary-fallback-container-id";
84868             this._container.classList
84869                 .add("mapillary-viewer");
84870             this._canvasContainer = this._dom
84871                 .createElement("div", "mapillary-interactive", this._container);
84872             this._canvas = this._dom
84873                 .createElement("canvas", "mapillary-canvas");
84874             this._canvas.style.position = "absolute";
84875             this._canvas.setAttribute("tabindex", "0");
84876             // Add DOM container after canvas container to
84877             // render DOM elements on top of the interactive
84878             // canvas.
84879             this._domContainer = this._dom
84880                 .createElement("div", "mapillary-dom", this._container);
84881             this.configurationService = new ConfigurationService(options);
84882             this.renderService =
84883                 new RenderService(this._container, stateService.currentState$, options.renderMode);
84884             this.glRenderer =
84885                 new GLRenderer(this._canvas, this._canvasContainer, this.renderService);
84886             this.domRenderer =
84887                 new DOMRenderer(this._domContainer, this.renderService, stateService.currentState$);
84888             this.keyboardService =
84889                 new KeyboardService(this._canvasContainer);
84890             this.mouseService =
84891                 new MouseService(this._container, this._canvasContainer, this._domContainer, document);
84892             this.touchService =
84893                 new TouchService(this._canvasContainer, this._domContainer);
84894             this.spriteService =
84895                 new SpriteService(options.sprite);
84896             window.addEventListener('resize', this._onWindowResize, false);
84897         }
84898         get canvas() {
84899             return !!this._canvas.parentNode ?
84900                 this._canvas : null;
84901         }
84902         get canvasContainer() {
84903             return this._canvasContainer;
84904         }
84905         get container() {
84906             return this._container;
84907         }
84908         get domContainer() {
84909             return this._domContainer;
84910         }
84911         remove() {
84912             window.removeEventListener('resize', this._onWindowResize, false);
84913             this.spriteService.dispose();
84914             this.touchService.dispose();
84915             this.mouseService.dispose();
84916             this.glRenderer.remove();
84917             this.domRenderer.remove();
84918             this.renderService.dispose();
84919             this._removeNode(this._canvasContainer);
84920             this._removeNode(this._domContainer);
84921             this._container.classList
84922                 .remove("mapillary-viewer");
84923         }
84924         _removeNode(node) {
84925             if (node.parentNode) {
84926                 node.parentNode.removeChild(node);
84927             }
84928         }
84929     }
84930
84931     class CacheService {
84932         constructor(_graphService, _stateService, _api) {
84933             this._graphService = _graphService;
84934             this._stateService = _stateService;
84935             this._api = _api;
84936             this._subscriptions = new SubscriptionHolder();
84937             this._started = false;
84938             this._cellDepth = 1;
84939         }
84940         get started() {
84941             return this._started;
84942         }
84943         configure(configuration) {
84944             if (!configuration) {
84945                 this._cellDepth = 1;
84946                 return;
84947             }
84948             this._cellDepth = Math.max(1, Math.min(3, configuration.cellDepth));
84949         }
84950         start() {
84951             if (this._started) {
84952                 return;
84953             }
84954             const subs = this._subscriptions;
84955             subs.push(this._stateService.currentState$
84956                 .pipe(distinctUntilChanged(undefined, (frame) => {
84957                 return frame.state.currentImage.id;
84958             }), map((frame) => {
84959                 const state = frame.state;
84960                 const trajectory = state.trajectory;
84961                 const trajectoryKeys = trajectory
84962                     .map((n) => {
84963                     return n.id;
84964                 });
84965                 const sequenceKey = trajectory[trajectory.length - 1].sequenceId;
84966                 return [
84967                     trajectoryKeys,
84968                     state.currentImage.originalLngLat,
84969                     sequenceKey,
84970                 ];
84971             }), bufferCount(1, 5), withLatestFrom(this._graphService.graphMode$), switchMap(([keepBuffer, graphMode]) => {
84972                 const keepKeys = keepBuffer[0][0];
84973                 const lngLat = keepBuffer[0][1];
84974                 const geometry = this._api.data.geometry;
84975                 const cellId = geometry.lngLatToCellId(lngLat);
84976                 const keepCellIds = connectedComponent(cellId, this._cellDepth, geometry);
84977                 const keepSequenceKey = graphMode === GraphMode.Sequence ?
84978                     keepBuffer[0][2] :
84979                     undefined;
84980                 return this._graphService
84981                     .uncache$(keepKeys, keepCellIds, keepSequenceKey);
84982             }))
84983                 .subscribe(() => { }));
84984             subs.push(this._graphService.graphMode$
84985                 .pipe(skip(1), withLatestFrom(this._stateService.currentState$), switchMap(([mode, frame]) => {
84986                 return mode === GraphMode.Sequence ?
84987                     this._keyToEdges(frame.state.currentImage.id, (image) => {
84988                         return image.sequenceEdges$;
84989                     }) :
84990                     from(frame.state.trajectory
84991                         .map((image) => {
84992                         return image.id;
84993                     })
84994                         .slice(frame.state.currentIndex)).pipe(mergeMap((key) => {
84995                         return this._keyToEdges(key, (image) => {
84996                             return image.spatialEdges$;
84997                         });
84998                     }, 6));
84999             }))
85000                 .subscribe(() => { }));
85001             subs.push(this._graphService.dataAdded$
85002                 .pipe(withLatestFrom(this._stateService.currentId$), switchMap(([_, imageId]) => {
85003                 return this._graphService.cacheImage$(imageId);
85004             }))
85005                 .subscribe(() => { }));
85006             this._started = true;
85007         }
85008         stop() {
85009             if (!this._started) {
85010                 return;
85011             }
85012             this._subscriptions.unsubscribe();
85013             this._started = false;
85014         }
85015         _keyToEdges(key, imageToEdgeMap) {
85016             return this._graphService.cacheImage$(key).pipe(switchMap(imageToEdgeMap), first((status) => {
85017                 return status.cached;
85018             }), timeout(15000), catchError((error) => {
85019                 console.error(`Failed to cache edges (${key}).`, error);
85020                 return empty();
85021             }));
85022         }
85023     }
85024
85025     class LoadingService {
85026         constructor() {
85027             this._loadersSubject$ = new Subject();
85028             this._loaders$ = this._loadersSubject$.pipe(scan((loaders, loader) => {
85029                 if (loader.task !== undefined) {
85030                     loaders[loader.task] = loader.loading;
85031                 }
85032                 return loaders;
85033             }, {}), startWith({}), publishReplay(1), refCount());
85034         }
85035         get loading$() {
85036             return this._loaders$.pipe(map((loaders) => {
85037                 for (const key in loaders) {
85038                     if (!loaders.hasOwnProperty(key)) {
85039                         continue;
85040                     }
85041                     if (loaders[key]) {
85042                         return true;
85043                     }
85044                 }
85045                 return false;
85046             }), debounceTime(100), distinctUntilChanged());
85047         }
85048         taskLoading$(task) {
85049             return this._loaders$.pipe(map((loaders) => {
85050                 return !!loaders[task];
85051             }), debounceTime(100), distinctUntilChanged());
85052         }
85053         startLoading(task) {
85054             this._loadersSubject$.next({ loading: true, task: task });
85055         }
85056         stopLoading(task) {
85057             this._loadersSubject$.next({ loading: false, task: task });
85058         }
85059     }
85060
85061     var PanMode;
85062     (function (PanMode) {
85063         PanMode[PanMode["Disabled"] = 0] = "Disabled";
85064         PanMode[PanMode["Enabled"] = 1] = "Enabled";
85065         PanMode[PanMode["Started"] = 2] = "Started";
85066     })(PanMode || (PanMode = {}));
85067     class PanService {
85068         constructor(graphService, stateService, enabled, graphCalculator, spatial, viewportCoords) {
85069             this._subscriptions = new SubscriptionHolder();
85070             this._graphService = graphService;
85071             this._stateService = stateService;
85072             this._graphCalculator = graphCalculator !== null && graphCalculator !== void 0 ? graphCalculator : new GraphCalculator();
85073             this._spatial = spatial !== null && spatial !== void 0 ? spatial : new Spatial();
85074             this._viewportCoords = viewportCoords !== null && viewportCoords !== void 0 ? viewportCoords : new ViewportCoords();
85075             this._mode = enabled !== false ?
85076                 PanMode.Enabled : PanMode.Disabled;
85077             this._panImagesSubject$ = new Subject();
85078             this._panImages$ = this._panImagesSubject$.pipe(startWith([]), publishReplay(1), refCount());
85079             this._subscriptions.push(this._panImages$.subscribe());
85080         }
85081         get panImages$() {
85082             return this._panImages$;
85083         }
85084         dispose() {
85085             this.stop();
85086             if (this._panImagesSubscription != null) {
85087                 this._panImagesSubscription.unsubscribe();
85088             }
85089             this._subscriptions.unsubscribe();
85090         }
85091         enable() {
85092             if (this._mode !== PanMode.Disabled) {
85093                 return;
85094             }
85095             this._mode = PanMode.Enabled;
85096             this.start();
85097         }
85098         disable() {
85099             if (this._mode === PanMode.Disabled) {
85100                 return;
85101             }
85102             this.stop();
85103             this._mode = PanMode.Disabled;
85104         }
85105         start() {
85106             if (this._mode !== PanMode.Enabled) {
85107                 return;
85108             }
85109             const panImages$ = this._stateService.currentImage$.pipe(switchMap((current) => {
85110                 if (!current.merged || isSpherical(current.cameraType)) {
85111                     return of([]);
85112                 }
85113                 const current$ = of(current);
85114                 const bounds = this._graphCalculator.boundingBoxCorners(current.lngLat, 20);
85115                 const adjacent$ = this._graphService
85116                     .cacheBoundingBox$(bounds[0], bounds[1]).pipe(catchError((error) => {
85117                     console.error(`Failed to cache periphery bounding box (${current.id})`, error);
85118                     return empty();
85119                 }), map((images) => {
85120                     if (isSpherical(current.cameraType)) {
85121                         return [];
85122                     }
85123                     const potential = [];
85124                     for (const image of images) {
85125                         if (image.id === current.id) {
85126                             continue;
85127                         }
85128                         if (image.mergeId !== current.mergeId) {
85129                             continue;
85130                         }
85131                         if (isSpherical(image.cameraType)) {
85132                             continue;
85133                         }
85134                         if (this._distance(image, current) > 4) {
85135                             continue;
85136                         }
85137                         potential.push(image);
85138                     }
85139                     return potential;
85140                 }));
85141                 return combineLatest(current$, adjacent$).pipe(withLatestFrom(this._stateService.reference$), map(([[cn, adjacent], reference]) => {
85142                     const currentDirection = this._spatial.viewingDirection(cn.rotation);
85143                     const currentTranslation = computeTranslation({ lat: cn.lngLat.lat, lng: cn.lngLat.lng, alt: cn.computedAltitude }, cn.rotation, reference);
85144                     const currentTransform = this._createTransform(cn, currentTranslation);
85145                     const currentAzimuthal = this._spatial.wrap(this._spatial.azimuthal(currentDirection.toArray(), currentTransform.upVector().toArray()), 0, 2 * Math.PI);
85146                     const currentProjectedPoints = this._computeProjectedPoints(currentTransform);
85147                     const currentHFov = this._computeHorizontalFov(currentProjectedPoints) / 180 * Math.PI;
85148                     const preferredOverlap = Math.PI / 8;
85149                     let left = undefined;
85150                     let right = undefined;
85151                     for (const a of adjacent) {
85152                         const translation = computeTranslation({ lat: a.lngLat.lat, lng: a.lngLat.lng, alt: a.computedAltitude }, a.rotation, reference);
85153                         const transform = this._createTransform(a, translation);
85154                         const projectedPoints = this._computeProjectedPoints(transform);
85155                         const hFov = this._computeHorizontalFov(projectedPoints) / 180 * Math.PI;
85156                         const direction = this._spatial.viewingDirection(a.rotation);
85157                         const azimuthal = this._spatial.wrap(this._spatial.azimuthal(direction.toArray(), transform.upVector().toArray()), 0, 2 * Math.PI);
85158                         const directionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, direction.x, direction.y);
85159                         let overlap = Number.NEGATIVE_INFINITY;
85160                         if (directionChange > 0) {
85161                             if (currentAzimuthal > azimuthal) {
85162                                 overlap = currentAzimuthal - 2 * Math.PI + currentHFov / 2 - (azimuthal - hFov / 2);
85163                             }
85164                             else {
85165                                 overlap = currentAzimuthal + currentHFov / 2 - (azimuthal - hFov / 2);
85166                             }
85167                         }
85168                         else {
85169                             if (currentAzimuthal < azimuthal) {
85170                                 overlap = azimuthal + hFov / 2 - (currentAzimuthal + 2 * Math.PI - currentHFov / 2);
85171                             }
85172                             else {
85173                                 overlap = azimuthal + hFov / 2 - (currentAzimuthal - currentHFov / 2);
85174                             }
85175                         }
85176                         const nonOverlap = Math.abs(hFov - overlap);
85177                         const distanceCost = this._distance(a, cn);
85178                         const timeCost = Math.min(this._timeDifference(a, cn), 4);
85179                         const overlapCost = 20 * Math.abs(overlap - preferredOverlap);
85180                         const fovCost = Math.min(5, 1 / Math.min(hFov / currentHFov, 1));
85181                         const nonOverlapCost = overlap > 0 ? -2 * nonOverlap : 0;
85182                         const cost = distanceCost + timeCost + overlapCost + fovCost + nonOverlapCost;
85183                         if (overlap > 0 &&
85184                             overlap < 0.5 * currentHFov &&
85185                             overlap < 0.5 * hFov &&
85186                             nonOverlap > 0.5 * currentHFov) {
85187                             if (directionChange > 0) {
85188                                 if (!left) {
85189                                     left = [cost, a, transform, hFov];
85190                                 }
85191                                 else {
85192                                     if (cost < left[0]) {
85193                                         left = [cost, a, transform, hFov];
85194                                     }
85195                                 }
85196                             }
85197                             else {
85198                                 if (!right) {
85199                                     right = [cost, a, transform, hFov];
85200                                 }
85201                                 else {
85202                                     if (cost < right[0]) {
85203                                         right = [cost, a, transform, hFov];
85204                                     }
85205                                 }
85206                             }
85207                         }
85208                     }
85209                     const panImagess = [];
85210                     if (!!left) {
85211                         panImagess.push([left[1], left[2], left[3]]);
85212                     }
85213                     if (!!right) {
85214                         panImagess.push([right[1], right[2], right[3]]);
85215                     }
85216                     return panImagess;
85217                 }), startWith([]));
85218             }));
85219             this._panImagesSubscription = this._stateService.currentState$.pipe(map((frame) => {
85220                 return frame.state.imagesAhead > 0;
85221             }), distinctUntilChanged(), switchMap((traversing) => {
85222                 return traversing ? of([]) : panImages$;
85223             }))
85224                 .subscribe((panImages) => {
85225                 this._panImagesSubject$.next(panImages);
85226             });
85227             this._mode = PanMode.Started;
85228         }
85229         stop() {
85230             if (this._mode !== PanMode.Started) {
85231                 return;
85232             }
85233             this._panImagesSubscription.unsubscribe();
85234             this._panImagesSubject$.next([]);
85235             this._mode = PanMode.Enabled;
85236         }
85237         _distance(image, reference) {
85238             const [x, y, z] = geodeticToEnu(image.lngLat.lng, image.lngLat.lat, image.computedAltitude, reference.lngLat.lng, reference.lngLat.lat, reference.computedAltitude);
85239             return Math.sqrt(x * x + y * y + z * z);
85240         }
85241         _timeDifference(image, reference) {
85242             const milliSecond = (1000 * 60 * 60 * 24 * 30);
85243             return Math.abs(image.capturedAt - reference.capturedAt) / milliSecond;
85244         }
85245         _createTransform(image, translation) {
85246             return new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.assetsCached ? image.image : undefined, undefined, image.cameraParameters, image.cameraType);
85247         }
85248         _computeProjectedPoints(transform) {
85249             const vertices = [[1, 0]];
85250             const directions = [[0, 0.5]];
85251             const pointsPerLine = 20;
85252             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
85253         }
85254         _computeHorizontalFov(projectedPoints) {
85255             const fovs = projectedPoints
85256                 .map((projectedPoint) => {
85257                 return this._coordToFov(projectedPoint[0]);
85258             });
85259             const fov = Math.min(...fovs);
85260             return fov;
85261         }
85262         _coordToFov(x) {
85263             return 2 * Math.atan(x) * 180 / Math.PI;
85264         }
85265     }
85266
85267     /**
85268      * @class API
85269      *
85270      * @classdesc Provides methods for access to the API.
85271      */
85272     class APIWrapper {
85273         constructor(_data) {
85274             this._data = _data;
85275         }
85276         get data() {
85277             return this._data;
85278         }
85279         getCoreImages$(cellId) {
85280             return this._wrap$(this._data.getCoreImages(cellId));
85281         }
85282         getImages$(imageIds) {
85283             return this._wrap$(this._data.getImages(imageIds));
85284         }
85285         getImageTiles$(tiles) {
85286             return this._wrap$(this._data.getImageTiles(tiles));
85287         }
85288         getSequence$(sequenceId) {
85289             return this._wrap$(this._data.getSequence(sequenceId));
85290         }
85291         getSpatialImages$(imageIds) {
85292             return this._wrap$(this._data.getSpatialImages(imageIds));
85293         }
85294         setAccessToken(accessToken) {
85295             this._data.setAccessToken(accessToken);
85296         }
85297         _wrap$(promise) {
85298             return Observable.create((subscriber) => {
85299                 promise.then((value) => {
85300                     subscriber.next(value);
85301                     subscriber.complete();
85302                 }, (error) => {
85303                     subscriber.error(error);
85304                 });
85305             });
85306         }
85307     }
85308
85309     /**
85310      * @class GraphService
85311      *
85312      * @classdesc Represents a service for graph operations.
85313      */
85314     class GraphService {
85315         /**
85316          * Create a new graph service instance.
85317          *
85318          * @param {Graph} graph - Graph instance to be operated on.
85319          */
85320         constructor(graph) {
85321             this._dataAdded$ = new Subject();
85322             this._subscriptions = new SubscriptionHolder();
85323             this._onDataAdded = (event) => {
85324                 this._graph$
85325                     .pipe(first(), mergeMap(graph => {
85326                     return graph.updateCells$(event.cellIds).pipe(tap(() => { graph.resetSpatialEdges(); }));
85327                 }))
85328                     .subscribe(cellId => { this._dataAdded$.next(cellId); });
85329             };
85330             const subs = this._subscriptions;
85331             this._graph$ = concat(of(graph), graph.changed$).pipe(publishReplay(1), refCount());
85332             subs.push(this._graph$.subscribe(() => { }));
85333             this._graphMode = GraphMode.Spatial;
85334             this._graphModeSubject$ = new Subject();
85335             this._graphMode$ = this._graphModeSubject$.pipe(startWith(this._graphMode), publishReplay(1), refCount());
85336             subs.push(this._graphMode$.subscribe(() => { }));
85337             this._firstGraphSubjects$ = [];
85338             this._initializeCacheSubscriptions = [];
85339             this._sequenceSubscriptions = [];
85340             this._spatialSubscriptions = [];
85341             graph.api.data.on("datacreate", this._onDataAdded);
85342         }
85343         /**
85344          * Get dataAdded$.
85345          *
85346          * @returns {Observable<string>} Observable emitting
85347          * a cell id every time data has been added to a cell.
85348          */
85349         get dataAdded$() {
85350             return this._dataAdded$;
85351         }
85352         /**
85353          * Get filter observable.
85354          *
85355          * @desciption Emits the filter every time it has changed.
85356          *
85357          * @returns {Observable<FilterFunction>} Observable
85358          * emitting the filter function every time it is set.
85359          */
85360         get filter$() {
85361             return this._graph$.pipe(first(), mergeMap((graph) => {
85362                 return graph.filter$;
85363             }));
85364         }
85365         /**
85366          * Get graph mode observable.
85367          *
85368          * @description Emits the current graph mode.
85369          *
85370          * @returns {Observable<GraphMode>} Observable
85371          * emitting the current graph mode when it changes.
85372          */
85373         get graphMode$() {
85374             return this._graphMode$;
85375         }
85376         /**
85377          * Cache full images in a bounding box.
85378          *
85379          * @description When called, the full properties of
85380          * the image are retrieved. The image cache is not initialized
85381          * for any new images retrieved and the image assets are not
85382          * retrieved, {@link cacheImage$} needs to be called for caching
85383          * assets.
85384          *
85385          * @param {LngLat} sw - South west corner of bounding box.
85386          * @param {LngLat} ne - North east corner of bounding box.
85387          * @return {Observable<Array<Image>>} Observable emitting a single item,
85388          * the images of the bounding box, when they have all been retrieved.
85389          * @throws {Error} Propagates any IO image caching errors to the caller.
85390          */
85391         cacheBoundingBox$(sw, ne) {
85392             return this._graph$.pipe(first(), mergeMap((graph) => {
85393                 return graph.cacheBoundingBox$(sw, ne);
85394             }));
85395         }
85396         /**
85397          * Cache full images in a cell.
85398          *
85399          * @description When called, the full properties of
85400          * the image are retrieved. The image cache is not initialized
85401          * for any new images retrieved and the image assets are not
85402          * retrieved, {@link cacheImage$} needs to be called for caching
85403          * assets.
85404          *
85405          * @param {string} cellId - Id of the cell.
85406          * @return {Observable<Array<Image>>} Observable emitting a single item,
85407          * the images of the cell, when they have all been retrieved.
85408          * @throws {Error} Propagates any IO image caching errors to the caller.
85409          */
85410         cacheCell$(cellId) {
85411             return this._graph$.pipe(first(), mergeMap((graph) => {
85412                 return graph.cacheCell$(cellId);
85413             }));
85414         }
85415         /**
85416          * Cache a image in the graph and retrieve it.
85417          *
85418          * @description When called, the full properties of
85419          * the image are retrieved and the image cache is initialized.
85420          * After that the image assets are cached and the image
85421          * is emitted to the observable when.
85422          * In parallel to caching the image assets, the sequence and
85423          * spatial edges of the image are cached. For this, the sequence
85424          * of the image and the required tiles and spatial images are
85425          * retrieved. The sequence and spatial edges may be set before
85426          * or after the image is returned.
85427          *
85428          * @param {string} id - Id of the image to cache.
85429          * @return {Observable<Image>} Observable emitting a single item,
85430          * the image, when it has been retrieved and its assets are cached.
85431          * @throws {Error} Propagates any IO image caching errors to the caller.
85432          */
85433         cacheImage$(id) {
85434             const firstGraphSubject$ = new Subject();
85435             this._firstGraphSubjects$.push(firstGraphSubject$);
85436             const firstGraph$ = firstGraphSubject$.pipe(publishReplay(1), refCount());
85437             const image$ = firstGraph$.pipe(map((graph) => {
85438                 return graph.getNode(id);
85439             }), mergeMap((image) => {
85440                 return image.assetsCached ?
85441                     of(image) :
85442                     image.cacheAssets$();
85443             }), publishReplay(1), refCount());
85444             image$.subscribe(undefined, (error) => {
85445                 console.error(`Failed to cache image (${id}).`, error);
85446             });
85447             let initializeCacheSubscription;
85448             initializeCacheSubscription = this._graph$.pipe(first(), mergeMap((graph) => {
85449                 if (graph.isCachingFull(id) || !graph.hasNode(id)) {
85450                     return graph.cacheFull$(id);
85451                 }
85452                 if (graph.isCachingFill(id) || !graph.getNode(id).complete) {
85453                     return graph.cacheFill$(id);
85454                 }
85455                 return of(graph);
85456             }), tap((graph) => {
85457                 if (!graph.hasNode(id)) {
85458                     throw new GraphMapillaryError(`Failed to cache image (${id})`);
85459                 }
85460                 if (!graph.hasInitializedCache(id)) {
85461                     graph.initializeCache(id);
85462                 }
85463             }), finalize(() => {
85464                 if (initializeCacheSubscription == null) {
85465                     return;
85466                 }
85467                 this._removeFromArray(initializeCacheSubscription, this._initializeCacheSubscriptions);
85468                 this._removeFromArray(firstGraphSubject$, this._firstGraphSubjects$);
85469             }))
85470                 .subscribe((graph) => {
85471                 firstGraphSubject$.next(graph);
85472                 firstGraphSubject$.complete();
85473             }, (error) => {
85474                 firstGraphSubject$.error(error);
85475             });
85476             if (!initializeCacheSubscription.closed) {
85477                 this._initializeCacheSubscriptions.push(initializeCacheSubscription);
85478             }
85479             const graphSequence$ = firstGraph$.pipe(catchError(() => {
85480                 return empty();
85481             }), mergeMap((graph) => {
85482                 if (graph.isCachingNodeSequence(id) || !graph.hasNodeSequence(id)) {
85483                     return graph.cacheNodeSequence$(id);
85484                 }
85485                 return of(graph);
85486             }), publishReplay(1), refCount());
85487             let sequenceSubscription;
85488             sequenceSubscription = graphSequence$.pipe(tap((graph) => {
85489                 if (!graph.getNode(id).sequenceEdges.cached) {
85490                     graph.cacheSequenceEdges(id);
85491                 }
85492             }), finalize(() => {
85493                 if (sequenceSubscription == null) {
85494                     return;
85495                 }
85496                 this._removeFromArray(sequenceSubscription, this._sequenceSubscriptions);
85497             }))
85498                 .subscribe(() => { return; }, (error) => {
85499                 console.error(`Failed to cache sequence edges (${id}).`, error);
85500             });
85501             if (!sequenceSubscription.closed) {
85502                 this._sequenceSubscriptions.push(sequenceSubscription);
85503             }
85504             if (this._graphMode === GraphMode.Spatial) {
85505                 let spatialSubscription;
85506                 spatialSubscription = firstGraph$.pipe(catchError(() => {
85507                     return empty();
85508                 }), expand((graph) => {
85509                     if (graph.hasTiles(id)) {
85510                         return empty();
85511                     }
85512                     return from(graph.cacheTiles$(id)).pipe(mergeMap((graph$) => {
85513                         return graph$.pipe(mergeMap((g) => {
85514                             if (g.isCachingTiles(id)) {
85515                                 return empty();
85516                             }
85517                             return of(g);
85518                         }), catchError((error) => {
85519                             console.error(`Failed to cache tile data (${id}).`, error);
85520                             return empty();
85521                         }));
85522                     }));
85523                 }), takeLast(1), mergeMap((graph) => {
85524                     if (graph.hasSpatialArea(id)) {
85525                         return of(graph);
85526                     }
85527                     return from(graph.cacheSpatialArea$(id)).pipe(mergeMap((graph$) => {
85528                         return graph$.pipe(catchError((error) => {
85529                             console.error(`Failed to cache spatial images (${id}).`, error);
85530                             return empty();
85531                         }));
85532                     }));
85533                 }), takeLast(1), mergeMap((graph) => {
85534                     return graph.hasNodeSequence(id) ?
85535                         of(graph) :
85536                         graph.cacheNodeSequence$(id);
85537                 }), tap((graph) => {
85538                     if (!graph.getNode(id).spatialEdges.cached) {
85539                         graph.cacheSpatialEdges(id);
85540                     }
85541                 }), finalize(() => {
85542                     if (spatialSubscription == null) {
85543                         return;
85544                     }
85545                     this._removeFromArray(spatialSubscription, this._spatialSubscriptions);
85546                 }))
85547                     .subscribe(() => { return; }, (error) => {
85548                     const message = `Failed to cache spatial edges (${id}).`;
85549                     console.error(message, error);
85550                 });
85551                 if (!spatialSubscription.closed) {
85552                     this._spatialSubscriptions.push(spatialSubscription);
85553                 }
85554             }
85555             return image$.pipe(first((image) => {
85556                 return image.assetsCached;
85557             }));
85558         }
85559         /**
85560          * Cache a sequence in the graph and retrieve it.
85561          *
85562          * @param {string} sequenceId - Sequence id.
85563          * @returns {Observable<Sequence>} Observable emitting a single item,
85564          * the sequence, when it has been retrieved and its assets are cached.
85565          * @throws {Error} Propagates any IO image caching errors to the caller.
85566          */
85567         cacheSequence$(sequenceId) {
85568             return this._graph$.pipe(first(), mergeMap((graph) => {
85569                 if (graph.isCachingSequence(sequenceId) || !graph.hasSequence(sequenceId)) {
85570                     return graph.cacheSequence$(sequenceId);
85571                 }
85572                 return of(graph);
85573             }), map((graph) => {
85574                 return graph.getSequence(sequenceId);
85575             }));
85576         }
85577         /**
85578          * Cache a sequence and its images in the graph and retrieve the sequence.
85579          *
85580          * @description Caches a sequence and its assets are cached and
85581          * retrieves all images belonging to the sequence. The image assets
85582          * or edges will not be cached.
85583          *
85584          * @param {string} sequenceId - Sequence id.
85585          * @param {string} referenceImageId - Id of image to use as reference
85586          * for optimized caching.
85587          * @returns {Observable<Sequence>} Observable emitting a single item,
85588          * the sequence, when it has been retrieved, its assets are cached and
85589          * all images belonging to the sequence has been retrieved.
85590          * @throws {Error} Propagates any IO image caching errors to the caller.
85591          */
85592         cacheSequenceImages$(sequenceId, referenceImageId) {
85593             return this._graph$.pipe(first(), mergeMap((graph) => {
85594                 if (graph.isCachingSequence(sequenceId) || !graph.hasSequence(sequenceId)) {
85595                     return graph.cacheSequence$(sequenceId);
85596                 }
85597                 return of(graph);
85598             }), mergeMap((graph) => {
85599                 if (graph.isCachingSequenceNodes(sequenceId) || !graph.hasSequenceNodes(sequenceId)) {
85600                     return graph.cacheSequenceNodes$(sequenceId, referenceImageId);
85601                 }
85602                 return of(graph);
85603             }), map((graph) => {
85604                 return graph.getSequence(sequenceId);
85605             }));
85606         }
85607         /**
85608          * Dispose the graph service and its children.
85609          */
85610         dispose() {
85611             this._graph$
85612                 .pipe(first())
85613                 .subscribe((graph) => { graph.unsubscribe(); });
85614             this._subscriptions.unsubscribe();
85615         }
85616         /**
85617          * Set a spatial edge filter on the graph.
85618          *
85619          * @description Resets the spatial edges of all cached images.
85620          *
85621          * @param {FilterExpression} filter - Filter expression to be applied.
85622          * @return {Observable<Graph>} Observable emitting a single item,
85623          * the graph, when the spatial edges have been reset.
85624          */
85625         setFilter$(filter) {
85626             this._resetSubscriptions(this._spatialSubscriptions);
85627             return this._graph$.pipe(first(), tap((graph) => {
85628                 graph.resetSpatialEdges();
85629                 graph.setFilter(filter);
85630             }), map(() => {
85631                 return undefined;
85632             }));
85633         }
85634         /**
85635          * Set the graph mode.
85636          *
85637          * @description If graph mode is set to spatial, caching
85638          * is performed with emphasis on spatial edges. If graph
85639          * mode is set to sequence no tile data is requested and
85640          * no spatial edges are computed.
85641          *
85642          * When setting graph mode to sequence all spatial
85643          * subscriptions are aborted.
85644          *
85645          * @param {GraphMode} mode - Graph mode to set.
85646          */
85647         setGraphMode(mode) {
85648             if (this._graphMode === mode) {
85649                 return;
85650             }
85651             if (mode === GraphMode.Sequence) {
85652                 this._resetSubscriptions(this._spatialSubscriptions);
85653             }
85654             this._graphMode = mode;
85655             this._graphModeSubject$.next(this._graphMode);
85656         }
85657         /**
85658          * Reset the graph.
85659          *
85660          * @description Resets the graph but keeps the images of the
85661          * supplied ids.
85662          *
85663          * @param {Array<string>} keepIds - Ids of images to keep in graph.
85664          * @return {Observable<Image>} Observable emitting a single item,
85665          * the graph, when it has been reset.
85666          */
85667         reset$(keepIds) {
85668             this._abortSubjects(this._firstGraphSubjects$);
85669             this._resetSubscriptions(this._initializeCacheSubscriptions);
85670             this._resetSubscriptions(this._sequenceSubscriptions);
85671             this._resetSubscriptions(this._spatialSubscriptions);
85672             return this._graph$.pipe(first(), tap((graph) => {
85673                 graph.reset(keepIds);
85674             }), map(() => {
85675                 return undefined;
85676             }));
85677         }
85678         /**
85679          * Uncache the graph.
85680          *
85681          * @description Uncaches the graph by removing tiles, images and
85682          * sequences. Keeps the images of the supplied ids and the tiles
85683          * related to those images.
85684          *
85685          * @param {Array<string>} keepIds - Ids of images to keep in graph.
85686          * @param {Array<string>} keepCellIds - Ids of cells to keep in graph.
85687          * @param {string} keepSequenceId - Optional id of sequence
85688          * for which the belonging images should not be disposed or
85689          * removed from the graph. These images may still be uncached if
85690          * not specified in keep ids param.
85691          * @return {Observable<Graph>} Observable emitting a single item,
85692          * the graph, when the graph has been uncached.
85693          */
85694         uncache$(keepIds, keepCellIds, keepSequenceId) {
85695             return this._graph$.pipe(first(), tap((graph) => {
85696                 graph.uncache(keepIds, keepCellIds, keepSequenceId);
85697             }), map(() => {
85698                 return undefined;
85699             }));
85700         }
85701         _abortSubjects(subjects) {
85702             for (const subject of subjects.slice()) {
85703                 this._removeFromArray(subject, subjects);
85704                 subject.error(new Error("Cache image request was aborted."));
85705             }
85706         }
85707         _removeFromArray(object, objects) {
85708             const index = objects.indexOf(object);
85709             if (index !== -1) {
85710                 objects.splice(index, 1);
85711             }
85712         }
85713         _resetSubscriptions(subscriptions) {
85714             for (const subscription of subscriptions.slice()) {
85715                 this._removeFromArray(subscription, subscriptions);
85716                 if (!subscription.closed) {
85717                     subscription.unsubscribe();
85718                 }
85719             }
85720         }
85721     }
85722
85723     class FrameGenerator {
85724         constructor(root) {
85725             if (root.requestAnimationFrame) {
85726                 this._cancelAnimationFrame = root.cancelAnimationFrame.bind(root);
85727                 this._requestAnimationFrame = root.requestAnimationFrame.bind(root);
85728             }
85729             else if (root.mozRequestAnimationFrame) {
85730                 this._cancelAnimationFrame = root.mozCancelAnimationFrame.bind(root);
85731                 this._requestAnimationFrame = root.mozRequestAnimationFrame.bind(root);
85732             }
85733             else if (root.webkitRequestAnimationFrame) {
85734                 this._cancelAnimationFrame = root.webkitCancelAnimationFrame.bind(root);
85735                 this._requestAnimationFrame = root.webkitRequestAnimationFrame.bind(root);
85736             }
85737             else if (root.msRequestAnimationFrame) {
85738                 this._cancelAnimationFrame = root.msCancelAnimationFrame.bind(root);
85739                 this._requestAnimationFrame = root.msRequestAnimationFrame.bind(root);
85740             }
85741             else if (root.oRequestAnimationFrame) {
85742                 this._cancelAnimationFrame = root.oCancelAnimationFrame.bind(root);
85743                 this._requestAnimationFrame = root.oRequestAnimationFrame.bind(root);
85744             }
85745             else {
85746                 this._cancelAnimationFrame = root.clearTimeout.bind(root);
85747                 this._requestAnimationFrame = (cb) => { return root.setTimeout(cb, 1000 / 60); };
85748             }
85749         }
85750         get cancelAnimationFrame() {
85751             return this._cancelAnimationFrame;
85752         }
85753         get requestAnimationFrame() {
85754             return this._requestAnimationFrame;
85755         }
85756     }
85757
85758     class CustomState extends StateBase {
85759         constructor(state) {
85760             super(state);
85761         }
85762         setViewMatrix(viewMatrix) {
85763             const viewMatrixInverse = new Matrix4()
85764                 .fromArray(viewMatrix)
85765                 .invert();
85766             const me = viewMatrixInverse.elements;
85767             const eye = new Vector3(me[12], me[13], me[14]);
85768             const forward = new Vector3(-me[8], -me[9], -me[10]);
85769             const up = new Vector3(me[4], me[5], me[6]);
85770             const camera = this._camera;
85771             camera.position.copy(eye);
85772             camera.lookat.copy(eye
85773                 .clone()
85774                 .add(forward));
85775             camera.up.copy(up);
85776             const focal = 0.5 / Math.tan(Math.PI / 3);
85777             camera.focal = focal;
85778         }
85779     }
85780
85781     class EarthState extends StateBase {
85782         constructor(state) {
85783             super(state);
85784             const eye = this._camera.position.clone();
85785             const forward = this._camera.lookat
85786                 .clone()
85787                 .sub(eye)
85788                 .normalize();
85789             const xy = Math.sqrt(forward.x * forward.x + forward.y * forward.y);
85790             const angle = Math.atan2(forward.z, xy);
85791             const lookat = new Vector3();
85792             if (angle > -Math.PI / 45) {
85793                 lookat.copy(eye);
85794                 eye.add(new Vector3(forward.x, forward.y, 0)
85795                     .multiplyScalar(-50));
85796                 eye.z = 30;
85797             }
85798             else {
85799                 // Target a point on invented ground and keep forward direction
85800                 const l0 = eye.clone();
85801                 const n = new Vector3(0, 0, 1);
85802                 const p0 = new Vector3(0, 0, -2);
85803                 const d = new Vector3().subVectors(p0, l0).dot(n) / forward.dot(n);
85804                 const maxDistance = 10000;
85805                 const intersection = l0
85806                     .clone()
85807                     .add(forward.
85808                     clone()
85809                     .multiplyScalar(Math.min(maxDistance, d)));
85810                 lookat.copy(intersection);
85811                 const t = eye
85812                     .clone()
85813                     .sub(intersection)
85814                     .normalize();
85815                 eye.copy(intersection.add(t.multiplyScalar(Math.max(50, t.length()))));
85816             }
85817             this._camera.position.copy(eye);
85818             this._camera.lookat.copy(lookat);
85819             this._camera.up.set(0, 0, 1);
85820         }
85821         dolly(delta) {
85822             const camera = this._camera;
85823             const offset = camera.position
85824                 .clone()
85825                 .sub(camera.lookat);
85826             const length = offset.length();
85827             const scaled = length * Math.pow(2, -delta);
85828             const clipped = Math.max(1, Math.min(scaled, 4000));
85829             offset.normalize();
85830             offset.multiplyScalar(clipped);
85831             camera.position
85832                 .copy(camera.lookat)
85833                 .add(offset);
85834         }
85835         orbit(rotation) {
85836             const camera = this._camera;
85837             const q = new Quaternion()
85838                 .setFromUnitVectors(camera.up, new Vector3(0, 0, 1));
85839             const qInverse = q
85840                 .clone()
85841                 .invert();
85842             const offset = camera.position
85843                 .clone()
85844                 .sub(camera.lookat);
85845             offset.applyQuaternion(q);
85846             const length = offset.length();
85847             let phi = Math.atan2(offset.y, offset.x);
85848             phi += rotation.phi;
85849             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
85850             theta += rotation.theta;
85851             const threshold = Math.PI / 36;
85852             theta = Math.max(threshold, Math.min(Math.PI / 2 - threshold, theta));
85853             offset.x = Math.sin(theta) * Math.cos(phi);
85854             offset.y = Math.sin(theta) * Math.sin(phi);
85855             offset.z = Math.cos(theta);
85856             offset.applyQuaternion(qInverse);
85857             camera.position
85858                 .copy(camera.lookat)
85859                 .add(offset.multiplyScalar(length));
85860         }
85861         truck(direction) {
85862             const camera = this._camera;
85863             camera.position
85864                 .add(new Vector3().fromArray(direction));
85865             camera.lookat
85866                 .add(new Vector3().fromArray(direction));
85867         }
85868         update() { }
85869     }
85870
85871     class InteractiveWaitingState extends InteractiveStateBase {
85872         constructor(state) {
85873             super(state);
85874             this._adjustCameras();
85875             this._motionless = this._motionlessTransition();
85876         }
85877         prepend(images) {
85878             super.prepend(images);
85879             this._motionless = this._motionlessTransition();
85880         }
85881         set(images) {
85882             super.set(images);
85883             this._motionless = this._motionlessTransition();
85884         }
85885         move(delta) {
85886             this._alpha = Math.max(0, Math.min(1, this._alpha + delta));
85887         }
85888         moveTo(position) {
85889             this._alpha = Math.max(0, Math.min(1, position));
85890         }
85891         update(fps) {
85892             this._updateRotation();
85893             if (!this._rotationDelta.isZero) {
85894                 this._applyRotation(this._rotationDelta, this._previousCamera);
85895                 this._applyRotation(this._rotationDelta, this._currentCamera);
85896             }
85897             this._updateRotationBasic();
85898             if (this._basicRotation[0] !== 0 || this._basicRotation[1] !== 0) {
85899                 this._applyRotationBasic(this._basicRotation);
85900             }
85901             let animationSpeed = this._animationSpeed * (60 / fps);
85902             this._updateZoom(animationSpeed);
85903             this._updateLookat(animationSpeed);
85904             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
85905         }
85906         _getAlpha() {
85907             return this._motionless ? Math.round(this._alpha) : this._alpha;
85908         }
85909         _setCurrentCamera() {
85910             super._setCurrentCamera();
85911             this._adjustCameras();
85912         }
85913         _adjustCameras() {
85914             if (this._previousImage == null) {
85915                 return;
85916             }
85917             if (isSpherical(this._currentImage.cameraType)) {
85918                 let lookat = this._camera.lookat.clone().sub(this._camera.position);
85919                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
85920             }
85921             if (isSpherical(this._previousImage.cameraType)) {
85922                 let lookat = this._currentCamera.lookat.clone().sub(this._currentCamera.position);
85923                 this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
85924             }
85925         }
85926     }
85927
85928     class WaitingState extends StateBase {
85929         constructor(state) {
85930             super(state);
85931             this._zoom = 0;
85932             this._adjustCameras();
85933             this._motionless = this._motionlessTransition();
85934         }
85935         prepend(images) {
85936             super.prepend(images);
85937             this._motionless = this._motionlessTransition();
85938         }
85939         set(images) {
85940             super.set(images);
85941             this._motionless = this._motionlessTransition();
85942         }
85943         move(delta) {
85944             this._alpha = Math.max(0, Math.min(1, this._alpha + delta));
85945         }
85946         moveTo(position) {
85947             this._alpha = Math.max(0, Math.min(1, position));
85948         }
85949         update(fps) {
85950             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
85951         }
85952         _getAlpha() {
85953             return this._motionless ? Math.round(this._alpha) : this._alpha;
85954         }
85955         _setCurrentCamera() {
85956             super._setCurrentCamera();
85957             this._adjustCameras();
85958         }
85959         _adjustCameras() {
85960             if (this._previousImage == null) {
85961                 return;
85962             }
85963             if (isSpherical(this._currentImage.cameraType)) {
85964                 let lookat = this._camera.lookat.clone().sub(this._camera.position);
85965                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
85966             }
85967             if (isSpherical(this._previousImage.cameraType)) {
85968                 let lookat = this._currentCamera.lookat.clone().sub(this._currentCamera.position);
85969                 this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
85970             }
85971         }
85972     }
85973
85974     class StateTransitionMatrix {
85975         constructor() {
85976             const custom = State[State.Custom];
85977             const earth = State[State.Earth];
85978             const traverse = State[State.Traversing];
85979             const wait = State[State.Waiting];
85980             const waitInteractively = State[State.WaitingInteractively];
85981             this._creators = new Map();
85982             const creator = this._creators;
85983             creator.set(custom, CustomState);
85984             creator.set(earth, EarthState);
85985             creator.set(traverse, TraversingState);
85986             creator.set(wait, WaitingState);
85987             creator.set(waitInteractively, InteractiveWaitingState);
85988             this._transitions = new Map();
85989             const transitions = this._transitions;
85990             transitions.set(custom, [earth, traverse]);
85991             transitions.set(earth, [custom, traverse]);
85992             transitions.set(traverse, [custom, earth, wait, waitInteractively]);
85993             transitions.set(wait, [traverse, waitInteractively]);
85994             transitions.set(waitInteractively, [traverse, wait]);
85995         }
85996         getState(state) {
85997             if (state instanceof CustomState) {
85998                 return State.Custom;
85999             }
86000             else if (state instanceof EarthState) {
86001                 return State.Earth;
86002             }
86003             else if (state instanceof TraversingState) {
86004                 return State.Traversing;
86005             }
86006             else if (state instanceof WaitingState) {
86007                 return State.Waiting;
86008             }
86009             else if (state instanceof InteractiveWaitingState) {
86010                 return State.WaitingInteractively;
86011             }
86012             throw new Error("Invalid state instance");
86013         }
86014         generate(state, options) {
86015             const concreteState = this._creators.get(State[state]);
86016             return new concreteState(options);
86017         }
86018         transition(state, to) {
86019             if (!this.validate(state, to)) {
86020                 throw new Error("Invalid transition");
86021             }
86022             return this.generate(to, state);
86023         }
86024         validate(state, to) {
86025             const source = State[this.getState(state)];
86026             const target = State[to];
86027             const transitions = this._transitions;
86028             return transitions.has(source) &&
86029                 transitions.get(source).includes(target);
86030         }
86031     }
86032
86033     class StateContext {
86034         constructor(state, transitionMode) {
86035             this._transitions = new StateTransitionMatrix();
86036             this._state = this._transitions.generate(state, {
86037                 alpha: 1,
86038                 camera: new Camera(),
86039                 currentIndex: -1,
86040                 reference: { alt: 0, lat: 0, lng: 0 },
86041                 trajectory: [],
86042                 transitionMode: transitionMode == null ? exports.TransitionMode.Default : transitionMode,
86043                 zoom: 0,
86044             });
86045         }
86046         get state() {
86047             return this._transitions.getState(this._state);
86048         }
86049         get reference() {
86050             return this._state.reference;
86051         }
86052         get alpha() {
86053             return this._state.alpha;
86054         }
86055         get camera() {
86056             return this._state.camera;
86057         }
86058         get zoom() {
86059             return this._state.zoom;
86060         }
86061         get currentImage() {
86062             return this._state.currentImage;
86063         }
86064         get previousImage() {
86065             return this._state.previousImage;
86066         }
86067         get currentCamera() {
86068             return this._state.currentCamera;
86069         }
86070         get currentTransform() {
86071             return this._state.currentTransform;
86072         }
86073         get previousTransform() {
86074             return this._state.previousTransform;
86075         }
86076         get trajectory() {
86077             return this._state.trajectory;
86078         }
86079         get currentIndex() {
86080             return this._state.currentIndex;
86081         }
86082         get lastImage() {
86083             return this._state.trajectory[this._state.trajectory.length - 1];
86084         }
86085         get imagesAhead() {
86086             return this._state.trajectory.length - 1 - this._state.currentIndex;
86087         }
86088         get motionless() {
86089             return this._state.motionless;
86090         }
86091         custom() {
86092             this._transition(State.Custom);
86093         }
86094         earth() {
86095             this._transition(State.Earth);
86096         }
86097         traverse() {
86098             this._transition(State.Traversing);
86099         }
86100         wait() {
86101             this._transition(State.Waiting);
86102         }
86103         waitInteractively() {
86104             this._transition(State.WaitingInteractively);
86105         }
86106         getCenter() {
86107             return this._state.getCenter();
86108         }
86109         setCenter(center) {
86110             this._state.setCenter(center);
86111         }
86112         setZoom(zoom) {
86113             this._state.setZoom(zoom);
86114         }
86115         update(fps) {
86116             this._state.update(fps);
86117         }
86118         append(images) {
86119             this._state.append(images);
86120         }
86121         prepend(images) {
86122             this._state.prepend(images);
86123         }
86124         remove(n) {
86125             this._state.remove(n);
86126         }
86127         clear() {
86128             this._state.clear();
86129         }
86130         clearPrior() {
86131             this._state.clearPrior();
86132         }
86133         cut() {
86134             this._state.cut();
86135         }
86136         set(images) {
86137             this._state.set(images);
86138         }
86139         setViewMatrix(matrix) {
86140             this._state.setViewMatrix(matrix);
86141         }
86142         rotate(delta) {
86143             this._state.rotate(delta);
86144         }
86145         rotateUnbounded(delta) {
86146             this._state.rotateUnbounded(delta);
86147         }
86148         rotateWithoutInertia(delta) {
86149             this._state.rotateWithoutInertia(delta);
86150         }
86151         rotateBasic(basicRotation) {
86152             this._state.rotateBasic(basicRotation);
86153         }
86154         rotateBasicUnbounded(basicRotation) {
86155             this._state.rotateBasicUnbounded(basicRotation);
86156         }
86157         rotateBasicWithoutInertia(basicRotation) {
86158             this._state.rotateBasicWithoutInertia(basicRotation);
86159         }
86160         rotateToBasic(basic) {
86161             this._state.rotateToBasic(basic);
86162         }
86163         move(delta) {
86164             this._state.move(delta);
86165         }
86166         moveTo(delta) {
86167             this._state.moveTo(delta);
86168         }
86169         zoomIn(delta, reference) {
86170             this._state.zoomIn(delta, reference);
86171         }
86172         setSpeed(speed) {
86173             this._state.setSpeed(speed);
86174         }
86175         setTransitionMode(mode) {
86176             this._state.setTransitionMode(mode);
86177         }
86178         dolly(delta) {
86179             this._state.dolly(delta);
86180         }
86181         orbit(rotation) {
86182             this._state.orbit(rotation);
86183         }
86184         truck(direction) {
86185             this._state.truck(direction);
86186         }
86187         _transition(to) {
86188             if (!this._transitions.validate(this._state, to)) {
86189                 const from = this._transitions.getState(this._state);
86190                 console.warn(`Transition not valid (${State[from]} - ${State[to]})`);
86191                 return;
86192             }
86193             const state = this._transitions.transition(this._state, to);
86194             this._state = state;
86195         }
86196     }
86197
86198     class StateService {
86199         constructor(initialState, transitionMode) {
86200             this._appendImage$ = new Subject();
86201             this._subscriptions = new SubscriptionHolder();
86202             const subs = this._subscriptions;
86203             this._start$ = new Subject();
86204             this._frame$ = new Subject();
86205             this._fpsSampleRate = 30;
86206             this._contextOperation$ = new BehaviorSubject((context) => {
86207                 return context;
86208             });
86209             this._context$ = this._contextOperation$.pipe(scan((context, operation) => {
86210                 return operation(context);
86211             }, new StateContext(initialState, transitionMode)), publishReplay(1), refCount());
86212             this._state$ = this._context$.pipe(map((context) => {
86213                 return context.state;
86214             }), distinctUntilChanged(), publishReplay(1), refCount());
86215             this._fps$ = this._start$.pipe(switchMap(() => {
86216                 return this._frame$.pipe(bufferCount(1, this._fpsSampleRate), map(() => {
86217                     return new Date().getTime();
86218                 }), pairwise(), map((times) => {
86219                     return Math.max(20, 1000 * this._fpsSampleRate / (times[1] - times[0]));
86220                 }), startWith(60));
86221             }), share());
86222             this._currentState$ = this._frame$.pipe(withLatestFrom(this._fps$, this._context$, (frameId, fps, context) => {
86223                 return [frameId, fps, context];
86224             }), filter((fc) => {
86225                 return fc[2].currentImage != null;
86226             }), tap((fc) => {
86227                 fc[2].update(fc[1]);
86228             }), map((fc) => {
86229                 return { fps: fc[1], id: fc[0], state: fc[2] };
86230             }), share());
86231             this._lastState$ = this._currentState$.pipe(publishReplay(1), refCount());
86232             let imageChanged$ = this._currentState$.pipe(distinctUntilChanged(undefined, (f) => {
86233                 return f.state.currentImage.id;
86234             }), publishReplay(1), refCount());
86235             let imageChangedSubject$ = new Subject();
86236             subs.push(imageChanged$
86237                 .subscribe(imageChangedSubject$));
86238             this._currentId$ = new BehaviorSubject(null);
86239             subs.push(imageChangedSubject$.pipe(map((f) => {
86240                 return f.state.currentImage.id;
86241             }))
86242                 .subscribe(this._currentId$));
86243             this._currentImage$ = imageChangedSubject$.pipe(map((f) => {
86244                 return f.state.currentImage;
86245             }), publishReplay(1), refCount());
86246             this._currentCamera$ = imageChangedSubject$.pipe(map((f) => {
86247                 return f.state.currentCamera;
86248             }), publishReplay(1), refCount());
86249             this._currentTransform$ = imageChangedSubject$.pipe(map((f) => {
86250                 return f.state.currentTransform;
86251             }), publishReplay(1), refCount());
86252             this._reference$ = imageChangedSubject$.pipe(map((f) => {
86253                 return f.state.reference;
86254             }), distinctUntilChanged((r1, r2) => {
86255                 return r1.lat === r2.lat && r1.lng === r2.lng;
86256             }, (reference) => {
86257                 return { lat: reference.lat, lng: reference.lng };
86258             }), publishReplay(1), refCount());
86259             this._currentImageExternal$ = imageChanged$.pipe(map((f) => {
86260                 return f.state.currentImage;
86261             }), publishReplay(1), refCount());
86262             subs.push(this._appendImage$.pipe(map((image) => {
86263                 return (context) => {
86264                     context.append([image]);
86265                     return context;
86266                 };
86267             }))
86268                 .subscribe(this._contextOperation$));
86269             this._inMotionOperation$ = new Subject();
86270             subs.push(imageChanged$.pipe(map(() => {
86271                 return true;
86272             }))
86273                 .subscribe(this._inMotionOperation$));
86274             subs.push(this._inMotionOperation$.pipe(distinctUntilChanged(), filter((moving) => {
86275                 return moving;
86276             }), switchMap(() => {
86277                 return this._currentState$.pipe(filter((frame) => {
86278                     return frame.state.imagesAhead === 0;
86279                 }), map((frame) => {
86280                     return [frame.state.camera.clone(), frame.state.zoom];
86281                 }), pairwise(), map((pair) => {
86282                     let c1 = pair[0][0];
86283                     let c2 = pair[1][0];
86284                     let z1 = pair[0][1];
86285                     let z2 = pair[1][1];
86286                     return c1.diff(c2) > 1e-5 || Math.abs(z1 - z2) > 1e-5;
86287                 }), first((changed) => {
86288                     return !changed;
86289                 }));
86290             }))
86291                 .subscribe(this._inMotionOperation$));
86292             this._inMotion$ = this._inMotionOperation$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
86293             this._inTranslationOperation$ = new Subject();
86294             subs.push(imageChanged$.pipe(map(() => {
86295                 return true;
86296             }))
86297                 .subscribe(this._inTranslationOperation$));
86298             subs.push(this._inTranslationOperation$.pipe(distinctUntilChanged(), filter((inTranslation) => {
86299                 return inTranslation;
86300             }), switchMap(() => {
86301                 return this._currentState$.pipe(filter((frame) => {
86302                     return frame.state.imagesAhead === 0;
86303                 }), map((frame) => {
86304                     return frame.state.camera.position.clone();
86305                 }), pairwise(), map((pair) => {
86306                     return pair[0].distanceToSquared(pair[1]) !== 0;
86307                 }), first((changed) => {
86308                     return !changed;
86309                 }));
86310             }))
86311                 .subscribe(this._inTranslationOperation$));
86312             this._inTranslation$ = this._inTranslationOperation$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
86313             subs.push(this._state$.subscribe(() => { }));
86314             subs.push(this._currentImage$.subscribe(() => { }));
86315             subs.push(this._currentCamera$.subscribe(() => { }));
86316             subs.push(this._currentTransform$.subscribe(() => { }));
86317             subs.push(this._reference$.subscribe(() => { }));
86318             subs.push(this._currentImageExternal$.subscribe(() => { }));
86319             subs.push(this._lastState$.subscribe(() => { }));
86320             subs.push(this._inMotion$.subscribe(() => { }));
86321             subs.push(this._inTranslation$.subscribe(() => { }));
86322             this._frameId = null;
86323             this._frameGenerator = new FrameGenerator(window);
86324         }
86325         get currentState$() {
86326             return this._currentState$;
86327         }
86328         get currentImage$() {
86329             return this._currentImage$;
86330         }
86331         get currentId$() {
86332             return this._currentId$;
86333         }
86334         get currentImageExternal$() {
86335             return this._currentImageExternal$;
86336         }
86337         get currentCamera$() {
86338             return this._currentCamera$;
86339         }
86340         get currentTransform$() {
86341             return this._currentTransform$;
86342         }
86343         get state$() {
86344             return this._state$;
86345         }
86346         get reference$() {
86347             return this._reference$;
86348         }
86349         get inMotion$() {
86350             return this._inMotion$;
86351         }
86352         get inTranslation$() {
86353             return this._inTranslation$;
86354         }
86355         get appendImage$() {
86356             return this._appendImage$;
86357         }
86358         dispose() {
86359             this.stop();
86360             this._subscriptions.unsubscribe();
86361         }
86362         custom() {
86363             this._inMotionOperation$.next(true);
86364             this._invokeContextOperation((context) => {
86365                 context.custom();
86366             });
86367         }
86368         earth() {
86369             this._inMotionOperation$.next(true);
86370             this._invokeContextOperation((context) => { context.earth(); });
86371         }
86372         traverse() {
86373             this._inMotionOperation$.next(true);
86374             this._invokeContextOperation((context) => { context.traverse(); });
86375         }
86376         wait() {
86377             this._invokeContextOperation((context) => { context.wait(); });
86378         }
86379         waitInteractively() {
86380             this._invokeContextOperation((context) => { context.waitInteractively(); });
86381         }
86382         appendImagess(images) {
86383             this._invokeContextOperation((context) => { context.append(images); });
86384         }
86385         prependImages(images) {
86386             this._invokeContextOperation((context) => { context.prepend(images); });
86387         }
86388         removeImages(n) {
86389             this._invokeContextOperation((context) => { context.remove(n); });
86390         }
86391         clearImages() {
86392             this._invokeContextOperation((context) => { context.clear(); });
86393         }
86394         clearPriorImages() {
86395             this._invokeContextOperation((context) => { context.clearPrior(); });
86396         }
86397         cutImages() {
86398             this._invokeContextOperation((context) => { context.cut(); });
86399         }
86400         setImages(images) {
86401             this._invokeContextOperation((context) => { context.set(images); });
86402         }
86403         setViewMatrix(matrix) {
86404             this._inMotionOperation$.next(true);
86405             this._invokeContextOperation((context) => { context.setViewMatrix(matrix); });
86406         }
86407         rotate(delta) {
86408             this._inMotionOperation$.next(true);
86409             this._invokeContextOperation((context) => { context.rotate(delta); });
86410         }
86411         rotateUnbounded(delta) {
86412             this._inMotionOperation$.next(true);
86413             this._invokeContextOperation((context) => { context.rotateUnbounded(delta); });
86414         }
86415         rotateWithoutInertia(delta) {
86416             this._inMotionOperation$.next(true);
86417             this._invokeContextOperation((context) => { context.rotateWithoutInertia(delta); });
86418         }
86419         rotateBasic(basicRotation) {
86420             this._inMotionOperation$.next(true);
86421             this._invokeContextOperation((context) => { context.rotateBasic(basicRotation); });
86422         }
86423         rotateBasicUnbounded(basicRotation) {
86424             this._inMotionOperation$.next(true);
86425             this._invokeContextOperation((context) => { context.rotateBasicUnbounded(basicRotation); });
86426         }
86427         rotateBasicWithoutInertia(basicRotation) {
86428             this._inMotionOperation$.next(true);
86429             this._invokeContextOperation((context) => { context.rotateBasicWithoutInertia(basicRotation); });
86430         }
86431         rotateToBasic(basic) {
86432             this._inMotionOperation$.next(true);
86433             this._invokeContextOperation((context) => { context.rotateToBasic(basic); });
86434         }
86435         move(delta) {
86436             this._inMotionOperation$.next(true);
86437             this._invokeContextOperation((context) => { context.move(delta); });
86438         }
86439         moveTo(position) {
86440             this._inMotionOperation$.next(true);
86441             this._invokeContextOperation((context) => { context.moveTo(position); });
86442         }
86443         dolly(delta) {
86444             this._inMotionOperation$.next(true);
86445             this._invokeContextOperation((context) => { context.dolly(delta); });
86446         }
86447         orbit(rotation) {
86448             this._inMotionOperation$.next(true);
86449             this._invokeContextOperation((context) => { context.orbit(rotation); });
86450         }
86451         truck(direction) {
86452             this._inMotionOperation$.next(true);
86453             this._invokeContextOperation((context) => { context.truck(direction); });
86454         }
86455         /**
86456          * Change zoom level while keeping the reference point position approximately static.
86457          *
86458          * @parameter {number} delta - Change in zoom level.
86459          * @parameter {Array<number>} reference - Reference point in basic coordinates.
86460          */
86461         zoomIn(delta, reference) {
86462             this._inMotionOperation$.next(true);
86463             this._invokeContextOperation((context) => { context.zoomIn(delta, reference); });
86464         }
86465         getCenter() {
86466             return this._lastState$.pipe(first(), map((frame) => {
86467                 return frame.state.getCenter();
86468             }));
86469         }
86470         getZoom() {
86471             return this._lastState$.pipe(first(), map((frame) => {
86472                 return frame.state.zoom;
86473             }));
86474         }
86475         setCenter(center) {
86476             this._inMotionOperation$.next(true);
86477             this._invokeContextOperation((context) => { context.setCenter(center); });
86478         }
86479         setSpeed(speed) {
86480             this._invokeContextOperation((context) => { context.setSpeed(speed); });
86481         }
86482         setTransitionMode(mode) {
86483             this._invokeContextOperation((context) => { context.setTransitionMode(mode); });
86484         }
86485         setZoom(zoom) {
86486             this._inMotionOperation$.next(true);
86487             this._invokeContextOperation((context) => { context.setZoom(zoom); });
86488         }
86489         start() {
86490             if (this._frameId == null) {
86491                 this._start$.next(null);
86492                 this._frameId = this._frameGenerator.requestAnimationFrame(this._frame.bind(this));
86493                 this._frame$.next(this._frameId);
86494             }
86495         }
86496         stop() {
86497             if (this._frameId != null) {
86498                 this._frameGenerator.cancelAnimationFrame(this._frameId);
86499                 this._frameId = null;
86500             }
86501         }
86502         _invokeContextOperation(action) {
86503             this._contextOperation$
86504                 .next((context) => {
86505                 action(context);
86506                 return context;
86507             });
86508         }
86509         _frame() {
86510             this._frameId = this._frameGenerator.requestAnimationFrame(this._frame.bind(this));
86511             this._frame$.next(this._frameId);
86512         }
86513     }
86514
86515     function cameraControlsToState(cameraControls) {
86516         switch (cameraControls) {
86517             case exports.CameraControls.Custom:
86518                 return State.Custom;
86519             case exports.CameraControls.Earth:
86520                 return State.Earth;
86521             case exports.CameraControls.Street:
86522                 return State.Traversing;
86523             default:
86524                 return null;
86525         }
86526     }
86527
86528     class Navigator {
86529         constructor(options, api, graphService, loadingService, stateService, cacheService, playService, panService) {
86530             var _a;
86531             if (api) {
86532                 this._api = api;
86533             }
86534             else if (options.dataProvider) {
86535                 if (options.dataProvider instanceof DataProviderBase) {
86536                     this._api = new APIWrapper(options.dataProvider);
86537                 }
86538                 else {
86539                     throw new Error("Incorrect type: 'dataProvider' must extend the DataProviderBase class.");
86540                 }
86541             }
86542             else {
86543                 this._api = new APIWrapper(new GraphDataProvider({
86544                     accessToken: options.accessToken,
86545                 }));
86546             }
86547             this._graphService = graphService !== null && graphService !== void 0 ? graphService : new GraphService(new Graph(this.api));
86548             this._loadingName = "navigator";
86549             this._loadingService = loadingService !== null && loadingService !== void 0 ? loadingService : new LoadingService();
86550             const cameraControls = (_a = options.cameraControls) !== null && _a !== void 0 ? _a : exports.CameraControls.Street;
86551             this._stateService = stateService !== null && stateService !== void 0 ? stateService : new StateService(cameraControlsToState(cameraControls), options.transitionMode);
86552             this._cacheService = cacheService !== null && cacheService !== void 0 ? cacheService : new CacheService(this._graphService, this._stateService, this._api);
86553             this._playService = playService !== null && playService !== void 0 ? playService : new PlayService(this._graphService, this._stateService);
86554             this._panService = panService !== null && panService !== void 0 ? panService : new PanService(this._graphService, this._stateService, options.combinedPanning);
86555             this._idRequested$ = new BehaviorSubject(null);
86556             this._movedToId$ = new BehaviorSubject(null);
86557             this._request$ = null;
86558             this._requestSubscription = null;
86559             this._imageRequestSubscription = null;
86560         }
86561         get api() {
86562             return this._api;
86563         }
86564         get cacheService() {
86565             return this._cacheService;
86566         }
86567         get graphService() {
86568             return this._graphService;
86569         }
86570         get loadingService() {
86571             return this._loadingService;
86572         }
86573         get movedToId$() {
86574             return this._movedToId$;
86575         }
86576         get panService() {
86577             return this._panService;
86578         }
86579         get playService() {
86580             return this._playService;
86581         }
86582         get stateService() {
86583             return this._stateService;
86584         }
86585         dispose() {
86586             this._abortRequest("viewer removed");
86587             this._cacheService.stop();
86588             this._graphService.dispose();
86589             this._panService.dispose();
86590             this._playService.dispose();
86591             this._stateService.dispose();
86592         }
86593         moveTo$(id) {
86594             this._abortRequest(`to id ${id}`);
86595             this._loadingService.startLoading(this._loadingName);
86596             const image$ = this._moveTo$(id);
86597             return this._makeRequest$(image$);
86598         }
86599         moveDir$(direction) {
86600             this._abortRequest(`in dir ${exports.NavigationDirection[direction]}`);
86601             this._loadingService.startLoading(this._loadingName);
86602             const image$ = this.stateService.currentImage$.pipe(first(), mergeMap((image) => {
86603                 return ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
86604                     image.sequenceEdges$ :
86605                     image.spatialEdges$).pipe(first(), map((status) => {
86606                     for (let edge of status.edges) {
86607                         if (edge.data.direction === direction) {
86608                             return edge.target;
86609                         }
86610                     }
86611                     return null;
86612                 }));
86613             }), mergeMap((directionId) => {
86614                 if (directionId == null) {
86615                     this._loadingService.stopLoading(this._loadingName);
86616                     return throwError(new Error(`Direction (${direction}) does not exist for current image.`));
86617                 }
86618                 return this._moveTo$(directionId);
86619             }));
86620             return this._makeRequest$(image$);
86621         }
86622         setFilter$(filter) {
86623             this._stateService.clearImages();
86624             return this._movedToId$.pipe(first(), mergeMap((id) => {
86625                 if (id != null) {
86626                     return this._trajectoryIds$().pipe(mergeMap((ids) => {
86627                         return this._graphService.setFilter$(filter).pipe(mergeMap(() => {
86628                             return this._cacheIds$(ids);
86629                         }));
86630                     }), last());
86631                 }
86632                 return this._idRequested$.pipe(first(), mergeMap((requestedId) => {
86633                     if (requestedId != null) {
86634                         return this._graphService.setFilter$(filter).pipe(mergeMap(() => {
86635                             return this._graphService.cacheImage$(requestedId);
86636                         }));
86637                     }
86638                     return this._graphService.setFilter$(filter).pipe(map(() => {
86639                         return undefined;
86640                     }));
86641                 }));
86642             }), map(() => {
86643                 return undefined;
86644             }));
86645         }
86646         setAccessToken$(accessToken) {
86647             this._abortRequest("to set user token");
86648             this._stateService.clearImages();
86649             return this._movedToId$.pipe(first(), tap(() => {
86650                 this._api.setAccessToken(accessToken);
86651             }), mergeMap((id) => {
86652                 return id == null ?
86653                     this._graphService.reset$([]) :
86654                     this._trajectoryIds$().pipe(mergeMap((ids) => {
86655                         return this._graphService.reset$(ids).pipe(mergeMap(() => {
86656                             return this._cacheIds$(ids);
86657                         }));
86658                     }), last(), map(() => {
86659                         return undefined;
86660                     }));
86661             }));
86662         }
86663         _cacheIds$(ids) {
86664             const cacheImages$ = ids
86665                 .map((id) => {
86666                 return this._graphService.cacheImage$(id);
86667             });
86668             return from(cacheImages$).pipe(mergeAll());
86669         }
86670         _abortRequest(reason) {
86671             if (this._requestSubscription != null) {
86672                 this._requestSubscription.unsubscribe();
86673                 this._requestSubscription = null;
86674             }
86675             if (this._imageRequestSubscription != null) {
86676                 this._imageRequestSubscription.unsubscribe();
86677                 this._imageRequestSubscription = null;
86678             }
86679             if (this._request$ != null) {
86680                 if (!(this._request$.isStopped || this._request$.hasError)) {
86681                     this._request$.error(new CancelMapillaryError(`Request aborted by a subsequent request ${reason}.`));
86682                 }
86683                 this._request$ = null;
86684             }
86685         }
86686         _makeRequest$(image$) {
86687             const request$ = new ReplaySubject(1);
86688             this._requestSubscription = request$
86689                 .subscribe(undefined, () => { });
86690             this._request$ = request$;
86691             this._imageRequestSubscription = image$
86692                 .subscribe((image) => {
86693                 this._request$ = null;
86694                 request$.next(image);
86695                 request$.complete();
86696             }, (error) => {
86697                 this._request$ = null;
86698                 request$.error(error);
86699             });
86700             return request$;
86701         }
86702         _moveTo$(id) {
86703             this._idRequested$.next(id);
86704             return this._graphService.cacheImage$(id).pipe(tap((image) => {
86705                 this._stateService.setImages([image]);
86706                 this._movedToId$.next(image.id);
86707             }), finalize(() => {
86708                 this._loadingService.stopLoading(this._loadingName);
86709             }));
86710         }
86711         _trajectoryIds$() {
86712             return this._stateService.currentState$.pipe(first(), map((frame) => {
86713                 return frame.state.trajectory
86714                     .map((image) => {
86715                     return image.id;
86716                 });
86717             }));
86718         }
86719     }
86720
86721     class Projection {
86722         constructor(viewportCoords, spatial) {
86723             this._spatial = spatial !== null && spatial !== void 0 ? spatial : new Spatial();
86724             this._viewportCoords = viewportCoords !== null && viewportCoords !== void 0 ? viewportCoords : new ViewportCoords();
86725         }
86726         basicToCanvas(basicPoint, container, render, transform) {
86727             return this._viewportCoords
86728                 .basicToCanvasSafe(basicPoint[0], basicPoint[1], container, transform, render.perspective);
86729         }
86730         canvasToBasic(canvasPoint, container, render, transform) {
86731             let basicPoint = this._viewportCoords
86732                 .canvasToBasic(canvasPoint[0], canvasPoint[1], container, transform, render.perspective);
86733             if (basicPoint[0] < 0 ||
86734                 basicPoint[0] > 1 ||
86735                 basicPoint[1] < 0 ||
86736                 basicPoint[1] > 1) {
86737                 basicPoint = null;
86738             }
86739             return basicPoint;
86740         }
86741         eventToUnprojection(event, container, render, reference, transform) {
86742             const pixelPoint = this._viewportCoords
86743                 .canvasPosition(event, container);
86744             return this.canvasToUnprojection(pixelPoint, container, render, reference, transform);
86745         }
86746         canvasToUnprojection(canvasPoint, container, render, reference, transform) {
86747             const canvasX = canvasPoint[0];
86748             const canvasY = canvasPoint[1];
86749             const [viewportX, viewportY] = this._viewportCoords
86750                 .canvasToViewport(canvasX, canvasY, container);
86751             const point3d = new Vector3(viewportX, viewportY, 1)
86752                 .unproject(render.perspective);
86753             let basicPoint = transform
86754                 .projectBasic(point3d.toArray());
86755             if (basicPoint[0] < 0 ||
86756                 basicPoint[0] > 1 ||
86757                 basicPoint[1] < 0 ||
86758                 basicPoint[1] > 1) {
86759                 basicPoint = null;
86760             }
86761             const direction3d = point3d
86762                 .clone()
86763                 .sub(render.camera.position)
86764                 .normalize();
86765             const dist = -2 / direction3d.z;
86766             let lngLat = null;
86767             if (dist > 0 && dist < 100 && !!basicPoint) {
86768                 const point = direction3d
86769                     .clone()
86770                     .multiplyScalar(dist)
86771                     .add(render.camera.position);
86772                 const [lng, lat] = enuToGeodetic(point.x, point.y, point.z, reference.lng, reference.lat, reference.alt);
86773                 lngLat = { lat, lng };
86774             }
86775             const unprojection = {
86776                 basicPoint: basicPoint,
86777                 lngLat: lngLat,
86778                 pixelPoint: [canvasX, canvasY],
86779             };
86780             return unprojection;
86781         }
86782         cameraToLngLat(render, reference) {
86783             const position = render.camera.position;
86784             const [lng, lat] = enuToGeodetic(position.x, position.y, position.z, reference.lng, reference.lat, reference.alt);
86785             return { lat, lng };
86786         }
86787         lngLatToCanvas(lngLat, container, render, reference) {
86788             const point3d = geodeticToEnu(lngLat.lng, lngLat.lat, 0, reference.lng, reference.lat, reference.alt);
86789             const canvas = this._viewportCoords
86790                 .projectToCanvasSafe(point3d, container, render.perspective);
86791             return canvas;
86792         }
86793         distanceBetweenLngLats(lngLat1, lngLat2) {
86794             return this._spatial
86795                 .distanceFromLngLat(lngLat1.lng, lngLat1.lat, lngLat2.lng, lngLat2.lat);
86796         }
86797     }
86798
86799     class Observer {
86800         constructor(viewer, navigator, container) {
86801             this._subscriptions = new SubscriptionHolder();
86802             this._emitSubscriptions = new SubscriptionHolder();
86803             this._container = container;
86804             this._viewer = viewer;
86805             this._navigator = navigator;
86806             this._projection = new Projection();
86807             this._started = false;
86808             this._navigable$ = new Subject();
86809             const subs = this._subscriptions;
86810             // load, navigable, dataloading should always emit,
86811             // also when cover is activated.
86812             subs.push(this._navigable$
86813                 .subscribe((navigable) => {
86814                 const type = "navigable";
86815                 const event = {
86816                     navigable,
86817                     target: this._viewer,
86818                     type,
86819                 };
86820                 this._viewer.fire(type, event);
86821             }));
86822             subs.push(this._navigator.loadingService.loading$
86823                 .subscribe((loading) => {
86824                 const type = "dataloading";
86825                 const event = {
86826                     loading,
86827                     target: this._viewer,
86828                     type,
86829                 };
86830                 this._viewer.fire(type, event);
86831             }));
86832             subs.push(this._container.glRenderer.opaqueRender$
86833                 .pipe(first())
86834                 .subscribe(() => {
86835                 const type = "load";
86836                 const event = {
86837                     target: this._viewer,
86838                     type,
86839                 };
86840                 this._viewer.fire(type, event);
86841             }));
86842         }
86843         get started() {
86844             return this._started;
86845         }
86846         get navigable$() {
86847             return this._navigable$;
86848         }
86849         get projection() {
86850             return this._projection;
86851         }
86852         dispose() {
86853             this.stopEmit();
86854             this._subscriptions.unsubscribe();
86855         }
86856         project$(lngLat) {
86857             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentImage$, this._navigator.stateService.reference$).pipe(first(), map(([render, image, reference]) => {
86858                 if (this._projection
86859                     .distanceBetweenLngLats(lngLat, image.lngLat) > 1000) {
86860                     return null;
86861                 }
86862                 const canvasPoint = this._projection.lngLatToCanvas(lngLat, this._container.container, render, reference);
86863                 return !!canvasPoint ?
86864                     [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
86865                     null;
86866             }));
86867         }
86868         projectBasic$(basicPoint) {
86869             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, transform]) => {
86870                 const canvasPoint = this._projection.basicToCanvas(basicPoint, this._container.container, render, transform);
86871                 return !!canvasPoint ?
86872                     [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
86873                     null;
86874             }));
86875         }
86876         startEmit() {
86877             if (this._started) {
86878                 return;
86879             }
86880             this._started = true;
86881             const subs = this._emitSubscriptions;
86882             subs.push(this._navigator.stateService.currentImageExternal$
86883                 .subscribe((image) => {
86884                 const type = "image";
86885                 const event = {
86886                     image: image,
86887                     target: this._viewer,
86888                     type,
86889                 };
86890                 this._viewer.fire(type, event);
86891             }));
86892             subs.push(this._navigator.stateService.currentImageExternal$.pipe(switchMap((image) => {
86893                 return image.sequenceEdges$;
86894             }))
86895                 .subscribe((status) => {
86896                 const type = "sequenceedges";
86897                 const event = {
86898                     status,
86899                     target: this._viewer,
86900                     type,
86901                 };
86902                 this._viewer.fire(type, event);
86903             }));
86904             subs.push(this._navigator.stateService.currentImageExternal$.pipe(switchMap((image) => {
86905                 return image.spatialEdges$;
86906             }))
86907                 .subscribe((status) => {
86908                 const type = "spatialedges";
86909                 const event = {
86910                     status,
86911                     target: this._viewer,
86912                     type,
86913                 };
86914                 this._viewer.fire(type, event);
86915             }));
86916             subs.push(combineLatest(this._navigator.stateService.inMotion$, this._container.mouseService.active$, this._container.touchService.active$).pipe(map((values) => {
86917                 return values[0] || values[1] || values[2];
86918             }), distinctUntilChanged())
86919                 .subscribe((started) => {
86920                 const type = started ? "movestart" : "moveend";
86921                 const event = {
86922                     target: this._viewer,
86923                     type,
86924                 };
86925                 this._viewer.fire(type, event);
86926             }));
86927             subs.push(this._container.renderService.bearing$.pipe(auditTime(100), distinctUntilChanged((b1, b2) => {
86928                 return Math.abs(b2 - b1) < 1;
86929             }))
86930                 .subscribe((bearing) => {
86931                 const type = "bearing";
86932                 const event = {
86933                     bearing,
86934                     target: this._viewer,
86935                     type,
86936                 };
86937                 this._viewer.fire(type, event);
86938             }));
86939             const mouseMove$ = this._container.mouseService.active$.pipe(switchMap((active) => {
86940                 return active ?
86941                     empty() :
86942                     this._container.mouseService.mouseMove$;
86943             }));
86944             subs.push(merge(this._mapMouseEvent$("click", this._container.mouseService.staticClick$), this._mapMouseEvent$("contextmenu", this._container.mouseService.contextMenu$), this._mapMouseEvent$("dblclick", this._container.mouseService.dblClick$), this._mapMouseEvent$("mousedown", this._container.mouseService.mouseDown$), this._mapMouseEvent$("mousemove", mouseMove$), this._mapMouseEvent$("mouseout", this._container.mouseService.mouseOut$), this._mapMouseEvent$("mouseover", this._container.mouseService.mouseOver$), this._mapMouseEvent$("mouseup", this._container.mouseService.mouseUp$))
86945                 .pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.reference$, this._navigator.stateService.currentTransform$, this._navigator.stateService.state$), map(([[type, event], render, reference, transform, state]) => {
86946                 const unprojection = this._projection.eventToUnprojection(event, this._container.container, render, reference, transform);
86947                 const basicPoint = state === State.Traversing ?
86948                     unprojection.basicPoint : null;
86949                 return {
86950                     basicPoint,
86951                     lngLat: unprojection.lngLat,
86952                     originalEvent: event,
86953                     pixelPoint: unprojection.pixelPoint,
86954                     target: this._viewer,
86955                     type: type,
86956                 };
86957             }))
86958                 .subscribe((event) => {
86959                 this._viewer.fire(event.type, event);
86960             }));
86961             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged(([x1, y1], [x2, y2]) => {
86962                 return this._closeTo(x1, x2, 1e-2) &&
86963                     this._closeTo(y1, y2, 1e-2);
86964             }, (rc) => {
86965                 return rc.camera.position.toArray();
86966             }))
86967                 .subscribe(() => {
86968                 const type = "position";
86969                 const event = {
86970                     target: this._viewer,
86971                     type,
86972                 };
86973                 this._viewer.fire(type, event);
86974             }));
86975             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged(([phi1, theta1], [phi2, theta2]) => {
86976                 return this._closeTo(phi1, phi2, 1e-3) &&
86977                     this._closeTo(theta1, theta2, 1e-3);
86978             }, (rc) => {
86979                 return [rc.rotation.phi, rc.rotation.theta];
86980             }))
86981                 .subscribe(() => {
86982                 const type = "pov";
86983                 const event = {
86984                     target: this._viewer,
86985                     type,
86986                 };
86987                 this._viewer.fire(type, event);
86988             }));
86989             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged((fov1, fov2) => {
86990                 return this._closeTo(fov1, fov2, 1e-2);
86991             }, (rc) => {
86992                 return rc.perspective.fov;
86993             }))
86994                 .subscribe(() => {
86995                 const type = "fov";
86996                 const event = {
86997                     target: this._viewer,
86998                     type,
86999                 };
87000                 this._viewer.fire(type, event);
87001             }));
87002         }
87003         stopEmit() {
87004             if (!this.started) {
87005                 return;
87006             }
87007             this._emitSubscriptions.unsubscribe();
87008             this._started = false;
87009         }
87010         unproject$(canvasPoint) {
87011             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.reference$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, reference, transform]) => {
87012                 const unprojection = this._projection.canvasToUnprojection(canvasPoint, this._container.container, render, reference, transform);
87013                 return unprojection.lngLat;
87014             }));
87015         }
87016         unprojectBasic$(canvasPoint) {
87017             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, transform]) => {
87018                 return this._projection.canvasToBasic(canvasPoint, this._container.container, render, transform);
87019             }));
87020         }
87021         _closeTo(v1, v2, absoluteTolerance) {
87022             return Math.abs(v1 - v2) <= absoluteTolerance;
87023         }
87024         _mapMouseEvent$(type, mouseEvent$) {
87025             return mouseEvent$.pipe(map((event) => {
87026                 return [type, event];
87027             }));
87028         }
87029     }
87030
87031     class CustomRenderer {
87032         constructor(_container, _navigator) {
87033             this._container = _container;
87034             this._navigator = _navigator;
87035             this._renderers = {};
87036         }
87037         add(renderer, viewer) {
87038             const subs = new SubscriptionHolder();
87039             this._renderers[renderer.id] = { subs, renderer };
87040             subs.push(combineLatest([
87041                 this._container.glRenderer.webGLRenderer$,
87042                 this._navigator.stateService.reference$,
87043             ])
87044                 .pipe(take(1))
87045                 .subscribe(([gl, reference]) => {
87046                 renderer.onAdd(viewer, reference, gl.getContext());
87047             }));
87048             subs.push(this._container.glRenderer.opaqueRender$
87049                 .pipe(withLatestFrom(this._container.renderService.renderCamera$, this._container.glRenderer.webGLRenderer$))
87050                 .subscribe(([, renderCamera, glRenderer]) => {
87051                 const context = glRenderer.getContext();
87052                 const viewMatrix = renderCamera.perspective.matrixWorldInverse;
87053                 const projectionMatrix = renderCamera.perspective.projectionMatrix;
87054                 renderer.render(context, viewMatrix.toArray(), projectionMatrix.toArray());
87055             }));
87056             subs.push(this._navigator.stateService.reference$
87057                 .pipe(skip(1))
87058                 .subscribe((reference) => {
87059                 renderer.onReference(viewer, reference);
87060             }));
87061         }
87062         dispose(viewer) {
87063             for (const id of Object.keys(this._renderers)) {
87064                 this.remove(id, viewer);
87065             }
87066         }
87067         has(id) {
87068             return id in this._renderers;
87069         }
87070         remove(id, viewer) {
87071             this._renderers[id].subs.unsubscribe();
87072             const renderer = this._renderers[id].renderer;
87073             delete this._renderers[id];
87074             this._container.glRenderer.webGLRenderer$
87075                 .subscribe((gl) => {
87076                 renderer.onRemove(viewer, gl.getContext());
87077             });
87078         }
87079     }
87080
87081     class CustomCameraControls {
87082         constructor(_container, _navigator) {
87083             this._container = _container;
87084             this._navigator = _navigator;
87085             this._controls = null;
87086             this._subscriptions = new SubscriptionHolder();
87087         }
87088         attach(controls, viewer) {
87089             if (this._controls) {
87090                 throw new MapillaryError('Custom camera controls already attached');
87091             }
87092             const attach$ = new Subject();
87093             const active$ = attach$
87094                 .pipe(switchMap(() => {
87095                 return this._navigator.stateService.state$;
87096             }), map((state) => {
87097                 return state === State.Custom;
87098             }), distinctUntilChanged());
87099             const subs = this._subscriptions;
87100             subs.push(active$
87101                 .pipe(startWith(false), pairwise(), withLatestFrom(this._navigator.stateService.reference$, this._container.renderService.renderCamera$))
87102                 .subscribe(([[deactivate, activate], ref, cam]) => {
87103                 if (activate) {
87104                     controls.onActivate(viewer, cam.perspective.matrixWorldInverse.toArray(), cam.perspective.projectionMatrix.toArray(), ref);
87105                 }
87106                 else if (deactivate) {
87107                     controls.onDeactivate(viewer);
87108                 }
87109             }));
87110             subs.push(active$
87111                 .pipe(switchMap(active => {
87112                 return active ?
87113                     this._navigator.stateService.currentState$
87114                         .pipe(skip(1)) :
87115                     empty();
87116             }))
87117                 .subscribe(frame => {
87118                 controls.onAnimationFrame(viewer, frame.id);
87119             }));
87120             subs.push(active$
87121                 .pipe(switchMap(active => {
87122                 return active ?
87123                     this._navigator.stateService.reference$
87124                         .pipe(skip(1)) :
87125                     empty();
87126             }))
87127                 .subscribe(ref => controls.onReference(viewer, ref)));
87128             subs.push(active$
87129                 .pipe(switchMap(active => {
87130                 return active ?
87131                     this._container.renderService.size$
87132                         .pipe(skip(1)) :
87133                     empty();
87134             }))
87135                 .subscribe(() => controls.onResize(viewer)));
87136             subs.push(combineLatest([
87137                 // Include to ensure GL renderer has been initialized
87138                 this._container.glRenderer.webGLRenderer$,
87139                 this._container.renderService.renderCamera$,
87140                 this._navigator.stateService.reference$,
87141                 this._navigator.stateService.state$,
87142             ])
87143                 .pipe(first())
87144                 .subscribe(() => {
87145                 const projectionMatrixCallback = (projectionMatrix) => {
87146                     if (!this._controls ||
87147                         controls !== this._controls) {
87148                         return;
87149                     }
87150                     this._updateProjectionMatrix(projectionMatrix);
87151                 };
87152                 const viewMatrixCallback = (viewMatrix) => {
87153                     if (!this._controls ||
87154                         controls !== this._controls) {
87155                         return;
87156                     }
87157                     this._updateViewMatrix(viewMatrix);
87158                 };
87159                 controls.onAttach(viewer, viewMatrixCallback, projectionMatrixCallback);
87160                 attach$.next();
87161                 attach$.complete();
87162             }));
87163             this._controls = controls;
87164         }
87165         dispose(viewer) {
87166             this.detach(viewer);
87167         }
87168         detach(viewer) {
87169             if (!this._controls) {
87170                 return;
87171             }
87172             this._subscriptions.unsubscribe();
87173             this._navigator.stateService.state$
87174                 .subscribe(state => {
87175                 if (state === State.Custom) {
87176                     this._controls.onDeactivate(viewer);
87177                 }
87178                 this._controls.onDetach(viewer);
87179                 this._controls = null;
87180             });
87181         }
87182         _updateProjectionMatrix(projectionMatrix) {
87183             this._navigator.stateService.state$
87184                 .pipe(first())
87185                 .subscribe(state => {
87186                 if (state !== State.Custom) {
87187                     const message = "Incorrect camera control mode for " +
87188                         "projection matrix update";
87189                     console.warn(message);
87190                     return;
87191                 }
87192                 this._container.renderService.projectionMatrix$
87193                     .next(projectionMatrix);
87194             });
87195         }
87196         _updateViewMatrix(viewMatrix) {
87197             this._navigator.stateService.state$
87198                 .pipe(first())
87199                 .subscribe(state => {
87200                 if (state !== State.Custom) {
87201                     const message = "Incorrect camera control mode for " +
87202                         "view matrix update";
87203                     console.warn(message);
87204                     return;
87205                 }
87206                 this._navigator.stateService.setViewMatrix(viewMatrix);
87207             });
87208         }
87209     }
87210
87211     /**
87212      * @class Viewer
87213      *
87214      * @classdesc The Viewer object represents the navigable image viewer.
87215      * Create a Viewer by specifying a container, client ID, image id and
87216      * other options. The viewer exposes methods and events for programmatic
87217      * interaction.
87218      *
87219      * In the case of asynchronous methods, MapillaryJS returns promises to
87220      * the results. Notifications are always emitted through JavaScript events.
87221      */
87222     class Viewer extends EventEmitter {
87223         /**
87224          * Create a new viewer instance.
87225          *
87226          * @description It is possible to initialize the viewer with or
87227          * without a id.
87228          *
87229          * When you want to show a specific image in the viewer from
87230          * the start you should initialize it with a id.
87231          *
87232          * When you do not know the first image id at implementation
87233          * time, e.g. in a map-viewer application you should initialize
87234          * the viewer without a id and call `moveTo` instead.
87235          *
87236          * When initializing with a id the viewer is bound to that id
87237          * until the image for that id has been successfully loaded.
87238          * Also, a cover with the image of the id will be shown.
87239          * If the data for that id can not be loaded because the id is
87240          * faulty or other errors occur it is not possible to navigate
87241          * to another id because the viewer is not navigable. The viewer
87242          * becomes navigable when the data for the id has been loaded and
87243          * the image is shown in the viewer. This way of initializing
87244          * the viewer is mostly for embedding in blog posts and similar
87245          * where one wants to show a specific image initially.
87246          *
87247          * If the viewer is initialized without a id (with null or
87248          * undefined) it is not bound to any particular id and it is
87249          * possible to move to any id with `viewer.moveTo("<my-image-id>")`.
87250          * If the first move to a id fails it is possible to move to another
87251          * id. The viewer will show a black background until a move
87252          * succeeds. This way of intitializing is suited for a map-viewer
87253          * application when the initial id is not known at implementation
87254          * time.
87255          *
87256          * @param {ViewerOptions} options - Optional configuration object
87257          * specifing Viewer's and the components' initial setup.
87258          *
87259          * @example
87260          * ```js
87261          * var viewer = new Viewer({
87262          *     accessToken: "<my-access-token>",
87263          *     container: "<my-container-id>",
87264          * });
87265          * ```
87266          */
87267         constructor(options) {
87268             super();
87269             this._navigator =
87270                 new Navigator(options);
87271             this._container =
87272                 new Container(options, this._navigator.stateService);
87273             this._observer =
87274                 new Observer(this, this._navigator, this._container);
87275             this._componentController =
87276                 new ComponentController(this._container, this._navigator, this._observer, options.imageId, options.component);
87277             this._customRenderer =
87278                 new CustomRenderer(this._container, this._navigator);
87279             this._customCameraControls =
87280                 new CustomCameraControls(this._container, this._navigator);
87281         }
87282         /**
87283          * Return a boolean indicating if the viewer is in a navigable state.
87284          *
87285          * @description The navigable state indicates if the viewer supports
87286          * moving, i.e. calling the {@link moveTo} and {@link moveDir}
87287          * methods or changing the authentication state,
87288          * i.e. calling {@link setAccessToken}. The viewer will not be in a navigable
87289          * state if the cover is activated and the viewer has been supplied a id.
87290          * When the cover is deactivated or the viewer is activated without being
87291          * supplied a id it will be navigable.
87292          *
87293          * @returns {boolean} Boolean indicating whether the viewer is navigable.
87294          */
87295         get isNavigable() {
87296             return this._componentController.navigable;
87297         }
87298         /**
87299          * Activate the combined panning functionality.
87300          *
87301          * @description The combined panning functionality is active by default.
87302          */
87303         activateCombinedPanning() {
87304             this._navigator.panService.enable();
87305         }
87306         /**
87307          * Activate a component.
87308          *
87309          * @param {ComponentName | FallbackComponentName} name - Name of
87310          * the component which will become active.
87311          *
87312          * @example
87313          * ```js
87314          * viewer.activateComponent("marker");
87315          * ```
87316          */
87317         activateComponent(name) {
87318             this._componentController.activate(name);
87319         }
87320         /**
87321          * Activate the cover (deactivates all other components).
87322          */
87323         activateCover() {
87324             this._componentController.activateCover();
87325         }
87326         /**
87327          * Add a custom renderer to the viewer's rendering pipeline.
87328          *
87329          * @description During a render pass, custom renderers
87330          * are called in the order they were added.
87331          *
87332          * @param renderer - The custom renderer implementation.
87333          */
87334         addCustomRenderer(renderer) {
87335             this._customRenderer.add(renderer, this);
87336         }
87337         /**
87338          * Attach custom camera controls to control the viewer's
87339          * camera pose and projection.
87340          *
87341          * @description Custom camera controls allow the API user
87342          * to move the viewer's camera freely and define the camera
87343          * projection. These camera properties are used
87344          * to render the viewer 3D scene directly into the
87345          * viewer's GL context.
87346          *
87347          * Only a single custom camera control instance can be
87348          * attached to the viewer. A new custom camera control
87349          * instance can be attached after detaching a previous
87350          * one.
87351          *
87352          * Set the viewer's camera controls to
87353          * {@link CameraControls.Custom} to activate attached
87354          * camera controls. If {@link CameraControls.Custom}
87355          * has already been set when a custom camera control
87356          * instance is attached, it will be activated immediately.
87357          *
87358          * Set the viewer's camera controls to any other
87359          * {@link CameraControls} mode to deactivate the
87360          * custom camera controls.
87361          *
87362          * @param controls - The custom camera controls implementation.
87363          *
87364          * @throws {MapillaryError} When camera controls attached
87365          * are already attached to the viewer.
87366          */
87367         attachCustomCameraControls(controls) {
87368             this._customCameraControls.attach(controls, this);
87369         }
87370         /**
87371          * Deactivate the combined panning functionality.
87372          *
87373          * @description Deactivating the combined panning functionality
87374          * could be needed in scenarios involving sequence only navigation.
87375          */
87376         deactivateCombinedPanning() {
87377             this._navigator.panService.disable();
87378         }
87379         /**
87380          * Deactivate a component.
87381          *
87382          * @param {ComponentName | FallbackComponentName} name - Name
87383          * of component which become inactive.
87384          *
87385          * @example
87386          * ```js
87387          * viewer.deactivateComponent("pointer");
87388          * ```
87389          */
87390         deactivateComponent(name) {
87391             this._componentController.deactivate(name);
87392         }
87393         /**
87394          * Deactivate the cover (activates all components marked as active).
87395          */
87396         deactivateCover() {
87397             this._componentController.deactivateCover();
87398         }
87399         /**
87400          * Detach a previously attached custom camera control
87401          * instance from the viewer.
87402          *
87403          * @description If no custom camera control instance
87404          * has previously been attached, calling this method
87405          * has no effect.
87406          *
87407          * Already attached custom camera controls need to
87408          * be detached before attaching another custom camera
87409          * control instance.
87410          */
87411         detachCustomCameraControls() {
87412             this._customCameraControls.detach(this);
87413         }
87414         fire(type, event) {
87415             super.fire(type, event);
87416         }
87417         /**
87418          * Get the bearing of the current viewer camera.
87419          *
87420          * @description The bearing depends on how the camera
87421          * is currently rotated and does not correspond
87422          * to the compass angle of the current image if the view
87423          * has been panned.
87424          *
87425          * Bearing is measured in degrees clockwise with respect to
87426          * north.
87427          *
87428          * @returns {Promise<number>} Promise to the bearing
87429          * of the current viewer camera.
87430          *
87431          * @example
87432          * ```js
87433          * viewer.getBearing().then(b => { console.log(b); });
87434          * ```
87435          */
87436         getBearing() {
87437             return new Promise((resolve, reject) => {
87438                 this._container.renderService.bearing$.pipe(first())
87439                     .subscribe((bearing) => {
87440                     resolve(bearing);
87441                 }, (error) => {
87442                     reject(error);
87443                 });
87444             });
87445         }
87446         /**
87447          * Get the viewer's camera control mode.
87448          *
87449          * @description The camera control mode determines
87450          * how the camera is controlled when the viewer
87451          * recieves pointer and keyboard input.
87452          *
87453          * @returns {CameraControls} controls - Camera control mode.
87454          *
87455          * @example
87456          * ```js
87457          * viewer.getCameraControls().then(c => { console.log(c); });
87458          * ```
87459          */
87460         getCameraControls() {
87461             return new Promise((resolve, reject) => {
87462                 this._navigator.stateService.state$.pipe(first())
87463                     .subscribe((state) => {
87464                     switch (state) {
87465                         case State.Custom:
87466                             resolve(exports.CameraControls.Custom);
87467                             break;
87468                         case State.Earth:
87469                             resolve(exports.CameraControls.Earth);
87470                             break;
87471                         default:
87472                             resolve(exports.CameraControls.Street);
87473                             break;
87474                     }
87475                 }, (error) => {
87476                     reject(error);
87477                 });
87478             });
87479         }
87480         /**
87481          * Returns the viewer's canvas element.
87482          *
87483          * @description This is the element onto which the viewer renders
87484          * the WebGL content.
87485          *
87486          * @returns {HTMLCanvasElement} The viewer's canvas element, or
87487          * null or not initialized.
87488          */
87489         getCanvas() {
87490             return this._container.canvas;
87491         }
87492         /**
87493          * Returns the HTML element containing the viewer's canvas element.
87494          *
87495          * @description This is the element to which event bindings for viewer
87496          * interactivity (such as panning and zooming) are attached.
87497          *
87498          * @returns {HTMLDivElement} The container for the viewer's
87499          * canvas element.
87500          */
87501         getCanvasContainer() {
87502             return this._container.canvasContainer;
87503         }
87504         /**
87505          * Get the basic coordinates of the current image that is
87506          * at the center of the viewport.
87507          *
87508          * @description Basic coordinates are 2D coordinates on the [0, 1] interval
87509          * and have the origin point, (0, 0), at the top left corner and the
87510          * maximum value, (1, 1), at the bottom right corner of the original
87511          * image.
87512          *
87513          * @returns {Promise<number[]>} Promise to the basic coordinates
87514          * of the current image at the center for the viewport.
87515          *
87516          * @example
87517          * ```js
87518          * viewer.getCenter().then(c => { console.log(c); });
87519          * ```
87520          */
87521         getCenter() {
87522             return new Promise((resolve, reject) => {
87523                 this._navigator.stateService.getCenter()
87524                     .subscribe((center) => {
87525                     resolve(center);
87526                 }, (error) => {
87527                     reject(error);
87528                 });
87529             });
87530         }
87531         /**
87532          * Get a component.
87533          *
87534          * @param {string} name - Name of component.
87535          * @returns {Component} The requested component.
87536          *
87537          * @example
87538          * ```js
87539          * var pointerComponent = viewer.getComponent("pointer");
87540          * ```
87541          */
87542         getComponent(name) {
87543             return this._componentController.get(name);
87544         }
87545         /**
87546          * Returns the viewer's containing HTML element.
87547          *
87548          * @returns {HTMLElement} The viewer's container.
87549          */
87550         getContainer() {
87551             return this._container.container;
87552         }
87553         /**
87554          * Get the viewer's current vertical field of view.
87555          *
87556          * @description The vertical field of view rendered on the viewer canvas
87557          * measured in degrees.
87558          *
87559          * @returns {Promise<number>} Promise to the current field of view
87560          * of the viewer camera.
87561          *
87562          * @example
87563          * ```js
87564          * viewer.getFieldOfView().then(fov => { console.log(fov); });
87565          * ```
87566          */
87567         getFieldOfView() {
87568             return new Promise((resolve, reject) => {
87569                 this._container.renderService.renderCamera$.pipe(first())
87570                     .subscribe((rc) => {
87571                     resolve(rc.perspective.fov);
87572                 }, (error) => {
87573                     reject(error);
87574                 });
87575             });
87576         }
87577         /**
87578          * Get the viewer's current image.
87579          *
87580          * @returns {Promise<Image>} Promise to the current image.
87581          *
87582          * @example
87583          * ```js
87584          * viewer.getImage().then(image => { console.log(image.id); });
87585          * ```
87586          */
87587         getImage() {
87588             return new Promise((resolve, reject) => {
87589                 this._navigator.stateService.currentImage$.pipe(first())
87590                     .subscribe((image) => { resolve(image); }, (error) => { reject(error); });
87591             });
87592         }
87593         /**
87594          * Get the viewer's current point of view.
87595          *
87596          * @returns {Promise<PointOfView>} Promise to the current point of view
87597          * of the viewer camera.
87598          *
87599          * @example
87600          * ```js
87601          * viewer.getPointOfView().then(pov => { console.log(pov); });
87602          * ```
87603          */
87604         getPointOfView() {
87605             return new Promise((resolve, reject) => {
87606                 combineLatest(this._container.renderService.renderCamera$, this._container.renderService.bearing$).pipe(first())
87607                     .subscribe(([rc, bearing]) => {
87608                     resolve({
87609                         bearing: bearing,
87610                         tilt: rc.getTilt(),
87611                     });
87612                 }, (error) => {
87613                     reject(error);
87614                 });
87615             });
87616         }
87617         /**
87618          * Get the viewer's current position
87619          *
87620          * @returns {Promise<LngLat>} Promise to the viewers's current
87621          * position.
87622          *
87623          * @example
87624          * ```js
87625          * viewer.getPosition().then(pos => { console.log(pos); });
87626          * ```
87627          */
87628         getPosition() {
87629             return new Promise((resolve, reject) => {
87630                 combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.reference$).pipe(first())
87631                     .subscribe(([render, reference]) => {
87632                     resolve(this._observer.projection.cameraToLngLat(render, reference));
87633                 }, (error) => {
87634                     reject(error);
87635                 });
87636             });
87637         }
87638         /**
87639          * Get the image's current zoom level.
87640          *
87641          * @returns {Promise<number>} Promise to the viewers's current
87642          * zoom level.
87643          *
87644          * @example
87645          * ```js
87646          * viewer.getZoom().then(z => { console.log(z); });
87647          * ```
87648          */
87649         getZoom() {
87650             return new Promise((resolve, reject) => {
87651                 this._navigator.stateService.getZoom()
87652                     .subscribe((zoom) => {
87653                     resolve(zoom);
87654                 }, (error) => {
87655                     reject(error);
87656                 });
87657             });
87658         }
87659         /**
87660          * Check if a custom renderer has been added to the viewer's
87661          * rendering pipeline.
87662          *
87663          * @param {string} id - Unique id of the custom renderer.
87664          * @returns {boolean} Value indicating whether the customer
87665          * renderer has been added.
87666          */
87667         hasCustomRenderer(rendererId) {
87668             return this._customRenderer.has(rendererId);
87669         }
87670         /**
87671          * Navigate in a given direction.
87672          *
87673          * @param {NavigationDirection} direction - Direction in which which to move.
87674          * @returns {Promise<Image>} Promise to the image that was navigated to.
87675          * @throws If the current image does not have the edge direction
87676          * or the edges has not yet been cached.
87677          * @throws Propagates any IO errors to the caller.
87678          * @throws When viewer is not navigable.
87679          * @throws {@link CancelMapillaryError} When a subsequent move request
87680          * is made before the move dir call has completed.
87681          *
87682          * @example
87683          * ```js
87684          * viewer.moveDir(NavigationDirection.Next).then(
87685          *     image => { console.log(image); },
87686          *     error => { console.error(error); });
87687          * ```
87688          */
87689         moveDir(direction) {
87690             const moveDir$ = this.isNavigable ?
87691                 this._navigator.moveDir$(direction) :
87692                 throwError(new Error("Calling moveDir is not supported when viewer is not navigable."));
87693             return new Promise((resolve, reject) => {
87694                 moveDir$.subscribe((image) => {
87695                     resolve(image);
87696                 }, (error) => {
87697                     reject(error);
87698                 });
87699             });
87700         }
87701         /**
87702          * Navigate to a given image id.
87703          *
87704          * @param {string} imageId - Id of the image to move to.
87705          * @returns {Promise<Image>} Promise to the image that was navigated to.
87706          * @throws Propagates any IO errors to the caller.
87707          * @throws When viewer is not navigable.
87708          * @throws {@link CancelMapillaryError} When a subsequent
87709          * move request is made before the move to id call has completed.
87710          *
87711          * @example
87712          * ```js
87713          * viewer.moveTo("<my-image-id>").then(
87714          *     image => { console.log(image); },
87715          *     error => { console.error(error); });
87716          * ```
87717          */
87718         moveTo(imageId) {
87719             const moveTo$ = this.isNavigable ?
87720                 this._navigator.moveTo$(imageId) :
87721                 throwError(new Error("Calling moveTo is not supported when viewer is not navigable."));
87722             return new Promise((resolve, reject) => {
87723                 moveTo$.subscribe((image) => {
87724                     resolve(image);
87725                 }, (error) => {
87726                     reject(error);
87727                 });
87728             });
87729         }
87730         off(type, handler) {
87731             super.off(type, handler);
87732         }
87733         on(type, handler) {
87734             super.on(type, handler);
87735         }
87736         /**
87737          * Project geodetic coordinates to canvas pixel coordinates.
87738          *
87739          * @description The geodetic coordinates may not always correspond to pixel
87740          * coordinates, e.g. if the geodetic coordinates have a position behind the
87741          * viewer camera. In the case of no correspondence the returned value will
87742          * be `null`.
87743          *
87744          * If the distance from the viewer camera position to the provided
87745          * longitude-latitude is more than 1000 meters `null` will be returned.
87746          *
87747          * The projection is performed from the ground plane, i.e.
87748          * the altitude with respect to the ground plane for the geodetic
87749          * point is zero.
87750          *
87751          * Note that whenever the camera moves, the result of the method will be
87752          * different.
87753          *
87754          * @param {LngLat} lngLat - Geographical coordinates to project.
87755          * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
87756          * to the lngLat.
87757          *
87758          * @example
87759          * ```js
87760          * viewer.project({ lat: 0, lng: 0 })
87761          *     .then(pixelPoint => {
87762          *          if (!pixelPoint) {
87763          *              console.log("no correspondence");
87764          *          }
87765          *
87766          *          console.log(pixelPoint);
87767          *     });
87768          * ```
87769          */
87770         project(lngLat) {
87771             return new Promise((resolve, reject) => {
87772                 this._observer.project$(lngLat)
87773                     .subscribe((pixelPoint) => {
87774                     resolve(pixelPoint);
87775                 }, (error) => {
87776                     reject(error);
87777                 });
87778             });
87779         }
87780         /**
87781          * Project basic image coordinates for the current image to canvas pixel
87782          * coordinates.
87783          *
87784          * @description The basic image coordinates may not always correspond to a
87785          * pixel point that lies in the visible area of the viewer container. In the
87786          * case of no correspondence the returned value can be `null`.
87787          *
87788          *
87789          * @param {Array<number>} basicPoint - Basic images coordinates to project.
87790          * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
87791          * to the basic image point.
87792          *
87793          * @example
87794          * ```js
87795          * viewer.projectFromBasic([0.3, 0.7])
87796          *     .then(pixelPoint => { console.log(pixelPoint); });
87797          * ```
87798          */
87799         projectFromBasic(basicPoint) {
87800             return new Promise((resolve, reject) => {
87801                 this._observer.projectBasic$(basicPoint)
87802                     .subscribe((pixelPoint) => {
87803                     resolve(pixelPoint);
87804                 }, (error) => {
87805                     reject(error);
87806                 });
87807             });
87808         }
87809         /**
87810          * Clean up and release all internal resources associated with
87811          * this viewer.
87812          *
87813          * @description This includes DOM elements, event bindings, and
87814          * WebGL resources.
87815          *
87816          * Use this method when you are done using the viewer and wish to
87817          * ensure that it no longer consumes browser resources. Afterwards,
87818          * you must not call any other methods on the viewer.
87819          *
87820          * @fires remove
87821          *
87822          * @example
87823          * ```js
87824          * viewer.remove();
87825          * ```
87826          */
87827         remove() {
87828             this._customRenderer.dispose(this);
87829             this._customCameraControls.dispose(this);
87830             this._observer.dispose();
87831             this._componentController.remove();
87832             this._navigator.dispose();
87833             this._container.remove();
87834             const type = "remove";
87835             const event = {
87836                 target: this,
87837                 type,
87838             };
87839             this.fire(type, event);
87840         }
87841         /**
87842          * Remove a custom renderer from the viewer's rendering pipeline.
87843          *
87844          * @param id - Unique id of the custom renderer.
87845          */
87846         removeCustomRenderer(rendererId) {
87847             this._customRenderer.remove(rendererId, this);
87848         }
87849         /**
87850          * Detect the viewer's new width and height and resize it
87851          * manually.
87852          *
87853          * @description The components will also detect the viewer's
87854          * new size and resize their rendered elements if needed.
87855          *
87856          * When the {@link ViewerOptions.trackResize} option is
87857          * set to true, the viewer will automatically resize
87858          * when the browser window is resized. If any other
87859          * custom behavior is preferred, the option should be set
87860          * to false and the {@link Viewer.resize} method should
87861          * be called on demand.
87862          *
87863          * @example
87864          * ```js
87865          * viewer.resize();
87866          * ```
87867          */
87868         resize() {
87869             this._container.renderService.resize$.next();
87870         }
87871         /**
87872          * Set the viewer's camera control mode.
87873          *
87874          * @description The camera control mode determines
87875          * how the camera is controlled when the viewer
87876          * recieves pointer and keyboard input.
87877          *
87878          * Changing the camera control mode is not possible
87879          * when the slider component is active and attempts
87880          * to do so will be ignored.
87881          *
87882          * @param {CameraControls} controls - Camera control mode.
87883          *
87884          * @example
87885          * ```js
87886          * viewer.setCameraControls(CameraControls.Street);
87887          * ```
87888          */
87889         setCameraControls(controls) {
87890             const state = cameraControlsToState(controls);
87891             if (state === State.Traversing) {
87892                 this._navigator.stateService.traverse();
87893             }
87894             else if (state === State.Earth) {
87895                 this._navigator.stateService.earth();
87896             }
87897             else if (state === State.Custom) {
87898                 this._navigator.stateService.custom();
87899             }
87900             else {
87901                 console.warn(`Unsupported camera control transition (${controls})`);
87902             }
87903         }
87904         /**
87905          * Set the basic coordinates of the current image to be in the
87906          * center of the viewport.
87907          *
87908          * @description Basic coordinates are 2D coordinates on the [0, 1] interval
87909          * and has the origin point, (0, 0), at the top left corner and the
87910          * maximum value, (1, 1), at the bottom right corner of the original
87911          * image.
87912          *
87913          * @param {number[]} The basic coordinates of the current
87914          * image to be at the center for the viewport.
87915          *
87916          * @example
87917          * ```js
87918          * viewer.setCenter([0.5, 0.5]);
87919          * ```
87920          */
87921         setCenter(center) {
87922             this._navigator.stateService.setCenter(center);
87923         }
87924         /**
87925          * Set the viewer's current vertical field of view.
87926          *
87927          * @description Sets the vertical field of view rendered
87928          * on the viewer canvas measured in degrees. The value
87929          * will be clamped to be able to set a valid zoom level
87930          * based on the projection model of the current image and
87931          * the viewer's current render mode.
87932          *
87933          * @param {number} fov - Vertical field of view in degrees.
87934          *
87935          * @example
87936          * ```js
87937          * viewer.setFieldOfView(45);
87938          * ```
87939          */
87940         setFieldOfView(fov) {
87941             this._container.renderService.renderCamera$.pipe(first())
87942                 .subscribe((rc) => {
87943                 const zoom = rc.fovToZoom(fov);
87944                 this._navigator.stateService.setZoom(zoom);
87945             });
87946         }
87947         /**
87948          * Set the filter selecting images to use when calculating
87949          * the spatial edges.
87950          *
87951          * @description The following filter types are supported:
87952          *
87953          * Comparison
87954          *
87955          * `["==", key, value]` equality: `image[key] = value`
87956          *
87957          * `["!=", key, value]` inequality: `image[key] â‰  value`
87958          *
87959          * `["<", key, value]` less than: `image[key] < value`
87960          *
87961          * `["<=", key, value]` less than or equal: `image[key] â‰¤ value`
87962          *
87963          * `[">", key, value]` greater than: `image[key] > value`
87964          *
87965          * `[">=", key, value]` greater than or equal: `image[key] â‰¥ value`
87966          *
87967          * Set membership
87968          *
87969          * `["in", key, v0, ..., vn]` set inclusion: `image[key] âˆˆ {v0, ..., vn}`
87970          *
87971          * `["!in", key, v0, ..., vn]` set exclusion: `image[key] âˆ‰ {v0, ..., vn}`
87972          *
87973          * Combining
87974          *
87975          * `["all", f0, ..., fn]` logical `AND`: `f0 âˆ§ ... âˆ§ fn`
87976          *
87977          * A key must be a string that identifies a property name of a
87978          * simple {@link Image} property, i.e. a key of the {@link FilterKey}
87979          * type. A value must be a string, number, or
87980          * boolean. Strictly-typed comparisons are used. The values
87981          * `f0, ..., fn` of the combining filter must be filter expressions.
87982          *
87983          * Clear the filter by setting it to null or empty array.
87984          *
87985          * Commonly used filter properties (see the {@link Image} class
87986          * documentation for a full list of properties that can be used
87987          * in a filter) are shown the the example code.
87988          *
87989          * @param {FilterExpression} filter - The filter expression.
87990          * @returns {Promise<void>} Promise that resolves after filter is applied.
87991          *
87992          * @example
87993          * ```js
87994          * // Examples
87995          * viewer.setFilter(["==", "cameraType", "spherical"]);
87996          * viewer.setFilter([">=", "capturedAt", <my-time-stamp>]);
87997          * viewer.setFilter(["in", "sequenceId", "<sequence-id-1>", "<sequence-id-2>"]);
87998          * ```
87999          */
88000         setFilter(filter) {
88001             return new Promise((resolve, reject) => {
88002                 this._navigator.setFilter$(filter)
88003                     .subscribe(() => {
88004                     resolve(undefined);
88005                 }, (error) => {
88006                     reject(error);
88007                 });
88008             });
88009         }
88010         /**
88011          * Set the viewer's render mode.
88012          *
88013          * @param {RenderMode} renderMode - Render mode.
88014          *
88015          * @example
88016          * ```js
88017          * viewer.setRenderMode(RenderMode.Letterbox);
88018          * ```
88019          */
88020         setRenderMode(renderMode) {
88021             this._container.renderService.renderMode$.next(renderMode);
88022         }
88023         /**
88024          * Set the viewer's transition mode.
88025          *
88026          * @param {TransitionMode} transitionMode - Transition mode.
88027          *
88028          * @example
88029          * ```js
88030          * viewer.setTransitionMode(TransitionMode.Instantaneous);
88031          * ```
88032          */
88033         setTransitionMode(transitionMode) {
88034             this._navigator.stateService.setTransitionMode(transitionMode);
88035         }
88036         /**
88037          * Set an access token for authenticated API requests of protected
88038          * resources.
88039          *
88040          * The token may be a user access token or a client access token.
88041          *
88042          * @description When the supplied user token is null or undefined,
88043          * any previously set user bearer token will be cleared and the
88044          * viewer will make unauthenticated requests.
88045          *
88046          * Calling setAccessToken aborts all outstanding move requests.
88047          * The promises of those move requests will be rejected with a
88048          * {@link CancelMapillaryError} the rejections need to be caught.
88049          *
88050          * Calling setAccessToken also resets the complete viewer cache
88051          * so it should not be called repeatedly.
88052          *
88053          * @param {string} [accessToken] accessToken - Optional user
88054          * access token or client access token.
88055          * @returns {Promise<void>} Promise that resolves after token
88056          * is set.
88057          *
88058          * @throws When viewer is not navigable.
88059          *
88060          * @example
88061          * ```js
88062          * viewer.setAccessToken("<my access token>")
88063          *     .then(() => { console.log("user token set"); });
88064          * ```
88065          */
88066         setAccessToken(accessToken) {
88067             const setAccessToken$ = this.isNavigable ?
88068                 this._navigator.setAccessToken$(accessToken) :
88069                 throwError(new Error("Calling setAccessToken is not supported when viewer is not navigable."));
88070             return new Promise((resolve, reject) => {
88071                 setAccessToken$
88072                     .subscribe(() => {
88073                     resolve(undefined);
88074                 }, (error) => {
88075                     reject(error);
88076                 });
88077             });
88078         }
88079         /**
88080          * Set the image's current zoom level.
88081          *
88082          * @description Possible zoom level values are on the [0, 3] interval.
88083          * Zero means zooming out to fit the image to the view whereas three
88084          * shows the highest level of detail.
88085          *
88086          * @param {number} The image's current zoom level.
88087          *
88088          * @example
88089          * ```js
88090          * viewer.setZoom(2);
88091          * ```
88092          */
88093         setZoom(zoom) {
88094             this._navigator.stateService.setZoom(zoom);
88095         }
88096         /**
88097          * Trigger the rendering of a single frame.
88098          *
88099          * @description Use this method with custom renderers to
88100          * force the viewer to rerender when the custom content
88101          * changes. Calling this multiple times before the next
88102          * frame is rendered will still result in only a single
88103          * frame being rendered.
88104          */
88105         triggerRerender() {
88106             this._container.glRenderer.triggerRerender();
88107         }
88108         /**
88109          * Unproject canvas pixel coordinates to geodetic
88110          * coordinates.
88111          *
88112          * @description The pixel point may not always correspond to geodetic
88113          * coordinates. In the case of no correspondence the returned value will
88114          * be `null`.
88115          *
88116          * The unprojection to a lngLat will be performed towards the ground plane, i.e.
88117          * the altitude with respect to the ground plane for the returned lngLat is zero.
88118          *
88119          * @param {Array<number>} pixelPoint - Pixel coordinates to unproject.
88120          * @returns {Promise<LngLat>} Promise to the lngLat corresponding to the pixel point.
88121          *
88122          * @example
88123          * ```js
88124          * viewer.unproject([100, 100])
88125          *     .then(lngLat => { console.log(lngLat); });
88126          * ```
88127          */
88128         unproject(pixelPoint) {
88129             return new Promise((resolve, reject) => {
88130                 this._observer.unproject$(pixelPoint)
88131                     .subscribe((lngLat) => {
88132                     resolve(lngLat);
88133                 }, (error) => {
88134                     reject(error);
88135                 });
88136             });
88137         }
88138         /**
88139          * Unproject canvas pixel coordinates to basic image coordinates for the
88140          * current image.
88141          *
88142          * @description The pixel point may not always correspond to basic image
88143          * coordinates. In the case of no correspondence the returned value will
88144          * be `null`.
88145          *
88146          * @param {Array<number>} pixelPoint - Pixel coordinates to unproject.
88147          * @returns {Promise<LngLat>} Promise to the basic coordinates corresponding
88148          * to the pixel point.
88149          *
88150          * @example
88151          * ```js
88152          * viewer.unprojectToBasic([100, 100])
88153          *     .then(basicPoint => { console.log(basicPoint); });
88154          * ```
88155          */
88156         unprojectToBasic(pixelPoint) {
88157             return new Promise((resolve, reject) => {
88158                 this._observer.unprojectBasic$(pixelPoint)
88159                     .subscribe((basicPoint) => {
88160                     resolve(basicPoint);
88161                 }, (error) => {
88162                     reject(error);
88163                 });
88164             });
88165         }
88166     }
88167
88168     /**
88169      * Internal bootstrap
88170      *
88171      * This is a workaround to make the CommonJS unit testing
88172      * work with Jest. Once Jest/Node supports ES6 modules
88173      * fully this should be removed. GeoRBush and UnitBezier
88174      * are registered here only to avoid loading them during
88175      * unit tests.
88176      */
88177     Graph.register(GeoRBush);
88178     MarkerSet.register(GeoRBush);
88179     TraversingState.register(unitbezier);
88180     ComponentService.registerCover(CoverComponent);
88181     ComponentService.register(AttributionComponent);
88182     ComponentService.register(BearingComponent);
88183     ComponentService.register(CacheComponent);
88184     ComponentService.register(DirectionComponent);
88185     ComponentService.register(ImageComponent);
88186     ComponentService.register(KeyboardComponent);
88187     ComponentService.register(MarkerComponent);
88188     ComponentService.register(PointerComponent);
88189     ComponentService.register(PopupComponent);
88190     ComponentService.register(SequenceComponent);
88191     ComponentService.register(SliderComponent);
88192     ComponentService.register(SpatialComponent);
88193     ComponentService.register(TagComponent);
88194     ComponentService.register(ZoomComponent);
88195     ComponentService.register(ImageFallbackComponent);
88196     ComponentService.register(NavigationFallbackComponent);
88197
88198     exports.ArgumentMapillaryError = ArgumentMapillaryError;
88199     exports.BearingComponent = BearingComponent;
88200     exports.CacheComponent = CacheComponent;
88201     exports.CancelMapillaryError = CancelMapillaryError;
88202     exports.CircleMarker = CircleMarker;
88203     exports.Component = Component;
88204     exports.DataProviderBase = DataProviderBase;
88205     exports.DirectionComponent = DirectionComponent;
88206     exports.DragPanHandler = DragPanHandler;
88207     exports.ExtremePointTag = ExtremePointTag;
88208     exports.Geometry = Geometry;
88209     exports.GeometryProviderBase = GeometryProviderBase;
88210     exports.GeometryTagError = GeometryTagError;
88211     exports.GraphDataProvider = GraphDataProvider;
88212     exports.GraphMapillaryError = GraphMapillaryError;
88213     exports.Image = Image$1;
88214     exports.KeyPlayHandler = KeyPlayHandler;
88215     exports.KeySequenceNavigationHandler = KeySequenceNavigationHandler;
88216     exports.KeySpatialNavigationHandler = KeySpatialNavigationHandler;
88217     exports.KeyZoomHandler = KeyZoomHandler;
88218     exports.KeyboardComponent = KeyboardComponent;
88219     exports.MapillaryError = MapillaryError;
88220     exports.Marker = Marker;
88221     exports.MarkerComponent = MarkerComponent;
88222     exports.OutlineTag = OutlineTag;
88223     exports.PointGeometry = PointGeometry;
88224     exports.PointerComponent = PointerComponent;
88225     exports.PointsGeometry = PointsGeometry;
88226     exports.PolygonGeometry = PolygonGeometry;
88227     exports.Popup = Popup;
88228     exports.PopupComponent = PopupComponent;
88229     exports.RectGeometry = RectGeometry;
88230     exports.S2GeometryProvider = S2GeometryProvider;
88231     exports.ScrollZoomHandler = ScrollZoomHandler;
88232     exports.SequenceComponent = SequenceComponent;
88233     exports.SimpleMarker = SimpleMarker;
88234     exports.SliderComponent = SliderComponent;
88235     exports.SpatialComponent = SpatialComponent;
88236     exports.SpotTag = SpotTag;
88237     exports.Tag = Tag;
88238     exports.TagComponent = TagComponent;
88239     exports.TouchZoomHandler = TouchZoomHandler;
88240     exports.VertexGeometry = VertexGeometry;
88241     exports.Viewer = Viewer;
88242     exports.ZoomComponent = ZoomComponent;
88243     exports.decompress = decompress;
88244     exports.enuToGeodetic = enuToGeodetic;
88245     exports.fetchArrayBuffer = fetchArrayBuffer;
88246     exports.geodeticToEnu = geodeticToEnu;
88247     exports.isFallbackSupported = isFallbackSupported;
88248     exports.isSupported = isSupported;
88249     exports.readMeshPbf = readMeshPbf;
88250
88251     Object.defineProperty(exports, '__esModule', { value: true });
88252
88253 })));
88254 //# sourceMappingURL=mapillary.unminified.js.map